29#include <Image/ByteImage.h>
33#include <glib-object.h>
35#include <gst/app/gstappbuffer.h>
36#include <gst/app/gstappsink.h>
37#include <gst/app/gstappsrc.h>
45#define VP8DECODE_ELEMENT " vp8dec ! "
46#define RTPVP8_ELEMENT \
47 "application/x-rtp, media=(string)video, clock-rate=(int)90000, " \
48 "encoding-name=(string)VP8-DRAFT-IETF-01, payload=(int)96 ! " \
52#define H264DECODE_ELEMENT " ffdec_h264 ! "
53#define RTPH264_ELEMENT \
54 "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, " \
55 "payload=(int)96 ! " \
70 avcodec_register_all();
72 m_decoder = avcodec_find_decoder(AV_CODEC_ID_H264);
79 if (
m_decoder->capabilities & CODEC_CAP_TRUNCATED)
90 AVDictionary* dictionary =
nullptr;
131 codec = streamProvider->getCodecType();
132 numberImages = streamProvider->getNumberOfImages();
133 int imgWidth, imgHeight, imgType;
134 streamProvider->getImageInformation(imgWidth, imgHeight, imgType);
136 for (
int i = 0; i < numberImages; i++)
138 ppDecodedImages[i] =
new CByteImage(imgWidth, imgHeight, CByteImage::eRGB24);
247 StreamSourceMap::iterator it = streamSources.begin();
249 for (; it != streamSources.end(); it++)
251 gst_element_send_event(it->second->pipeline, gst_event_new_eos());
252 gst_element_send_event(it->second->appsink, gst_event_new_eos());
253 gst_element_set_state(it->second->appsink, GST_STATE_NULL);
255 if (it->second->taskReceive)
257 it->second->taskReceive->stop();
270 it = streamSources.begin();
272 for (; it != streamSources.end(); it++)
276 gst_element_set_state(it->second->pipeline, GST_STATE_NULL);
277 gst_element_set_state(it->second->appsink, GST_STATE_NULL);
278 g_object_unref(it->second->pipeline);
279 it->second->pipeline = NULL;
283 it = streamSources.begin();
285 for (; it != streamSources.end(); it++)
292 streamProvider->stopCapture();
295 catch (Ice::NotRegisteredException& e)
300 catch (Ice::ConnectionRefusedException& e)
312 for (
int i = 0; i < numberImages; i++)
330StreamReceiver::StreamElementsPtr
331StreamReceiver::getStreamElements(std::string streamName)
333 StreamSourceMap::iterator it = streamSources.find(streamName);
335 if (it == streamSources.end())
337 throw armarx::LocalException(
"No Stream registered under the name: '") << streamName <<
"'";
344StreamReceiver::getImageFormat(StreamElementsPtr elem,
int& height,
int& width)
346 GstPad* pad = gst_element_get_static_pad(elem->appsink,
"sink");
354 GstCaps* caps = gst_pad_get_negotiated_caps(pad);
362 GstStructure*
s = gst_caps_get_structure(caps, 0);
363 gst_structure_get_int(s,
"width", &width);
364 gst_structure_get_int(s,
"height", &height);
366 gst_caps_unref(caps);
367 gst_object_unref(pad);
375 m_packet.data =
const_cast<Ice::Byte*
>(chunk.data());
384 std::string err(
"Decoding error");
394 if (
m_picture->format == AV_PIX_FMT_YUV420P)
396 static SwsContext* m_swsCtx = NULL;
398 m_swsCtx = sws_getCachedContext(m_swsCtx,
413 if (sws_scale(m_swsCtx,
424 for (
int i = 0; i < numberImages; ++i)
476 <<
"FPS: " << 1 / (IceUtil::Time::now() - lastReceiveTimestamp).toSecondsDouble();
477 lastReceiveTimestamp = IceUtil::Time::now();
479 if (
getState() < eManagedIceObjectStarted)
484 for (
int i = 0; i < numberImages && i < (int)imagesOut.size(); ++i)
487 memcpy(imagesOut.at(i)->pixels,
496 StreamSourceMap::iterator it = streamSources.begin();
498 for (; it != streamSources.end(); it++, i++)
502 CByteImage* image = imagesOut.at(i);
509 if (!image->m_bOwnMemory)
511 throw armarx::LocalException(
"Output images need to have there own memory");
514 StreamElementsPtr elem = it->second;
517 if (!elem->appsink || !elem->pipeline)
524 if (gst_element_get_state(elem->appsink, &state, NULL, 1000000000) ==
525 GST_STATE_CHANGE_FAILURE ||
526 state != GST_STATE_PLAYING)
529 <<
" not playing state: " << state <<
" - skipping" << std::endl;
533 GstBuffer* buffer = gst_app_sink_pull_buffer(GST_APP_SINK(elem->appsink));
545 getImageFormat(elem, height, width);
551 int buf_size = GST_BUFFER_SIZE(buffer);
553 if (width * height * 3 != buf_size)
555 ARMARX_WARNING <<
"Invalid buffer size: actual " << buf_size <<
" vs. expected "
556 << width * height * 3;
560 memcpy(image->pixels, GST_BUFFER_DATA(buffer), width * height * 3);
568 gst_buffer_unref(buffer);
582 streamProvider->getImageInformation(imageWidth, imageHeight, imageType);
586StreamReceiver::receive()
631StreamReceiver::StreamElements::StreamElements(std::string streamName,
633 StreamProviderPrx streamProvider)
635 this->streamName = streamName;
636 this->streamProvider = streamProvider;
639 this->streamID = streamID;
643StreamReceiver::StreamElements::receive()
707StreamReceiver::store()
Property< PropertyType > getProperty(const std::string &name)
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
int getState() const
Retrieve current state of the ManagedIceObject.
void getImageInformation(int &imageWidth, int &imageHeight, int &imageType)
AVCodecContext * m_decoderContext
CByteImage ** ppDecodedImages
void getImages(std::vector< CByteImage * > &imagesOut)
getImages retreives the next buffered images for all streams.
virtual void onInitComponent()
void reportNewStreamData(const Stream::DataChunk &chunk, const Ice::Current &)
virtual void onDisconnectComponent()
virtual void onConnectComponent()
virtual void onExitComponent()
CByteImage * pCombinedDecodedImage
int getNumberOfImages()
getNumberOfImages can be called after the component was initialized.
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Mutex::scoped_lock ScopedLock
double s(double t, double s0, double v0, double a0, double j)
This file offers overloads of toIce() and fromIce() functions for STL container types.