27 #include <Image/ByteImage.h>
32 #include <gst/app/gstappsink.h>
33 #include <gst/app/gstappsrc.h>
34 #include <gst/app/gstappbuffer.h>
36 #include <glib-object.h>
43 #define VP8DECODE_ELEMENT " vp8dec ! "
44 #define RTPVP8_ELEMENT "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)VP8-DRAFT-IETF-01, payload=(int)96 ! " \
48 #define H264DECODE_ELEMENT " ffdec_h264 ! "
49 #define RTPH264_ELEMENT "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96 ! " \
55 pCombinedDecodedImage = NULL;
56 usingProxy(getProperty<std::string>(
"UsedStreamProvider").getValue());
57 usingTopic(
"ImageStream");
63 avcodec_register_all();
64 av_init_packet(&m_packet);
65 m_decoder = avcodec_find_decoder(AV_CODEC_ID_H264);
70 m_decoderContext = avcodec_alloc_context3(m_decoder);
72 if (m_decoder->capabilities & CODEC_CAP_TRUNCATED)
74 m_decoderContext->flags |= CODEC_FLAG_TRUNCATED;
79 m_decoderContext->flags2 |= CODEC_FLAG2_CHUNKS;
80 m_decoderContext->thread_count = 4;
82 AVDictionary* dictionary =
nullptr;
83 if (avcodec_open2(m_decoderContext, m_decoder, &dictionary) < 0)
88 m_picture = avcodec_alloc_frame();
119 ppDecodedImages =
new CByteImage*[numberImages];
121 streamProvider = getProxy<Stream::StreamProviderPrx>(getProperty<std::string>(
"UsedStreamProvider").getValue());
122 codec = streamProvider->getCodecType();
123 numberImages = streamProvider->getNumberOfImages();
124 int imgWidth, imgHeight, imgType;
125 streamProvider->getImageInformation(imgWidth, imgHeight, imgType);
127 for (
int i = 0; i < numberImages ; i++)
129 ppDecodedImages[i] =
new CByteImage(imgWidth, imgHeight, CByteImage::eRGB24);
131 pCombinedDecodedImage =
new CByteImage(imgWidth, imgHeight * numberImages, CByteImage::eRGB24);
239 StreamSourceMap::iterator it = streamSources.begin();
241 for (; it != streamSources.end(); it++)
243 gst_element_send_event(it->second->pipeline, gst_event_new_eos());
244 gst_element_send_event(it->second->appsink, gst_event_new_eos());
245 gst_element_set_state(it->second->appsink, GST_STATE_NULL);
247 if (it->second->taskReceive)
249 it->second->taskReceive->stop();
262 it = streamSources.begin();
264 for (; it != streamSources.end(); it++)
268 gst_element_set_state(it->second->pipeline, GST_STATE_NULL);
269 gst_element_set_state(it->second->appsink, GST_STATE_NULL);
270 g_object_unref(it->second->pipeline);
271 it->second->pipeline = NULL;
275 it = streamSources.begin();
277 for (; it != streamSources.end(); it++)
284 streamProvider->stopCapture();
288 catch (Ice::NotRegisteredException& e)
293 catch (Ice::ConnectionRefusedException& e)
303 delete pCombinedDecodedImage;
304 pCombinedDecodedImage =
nullptr;
307 for (
int i = 0; i < numberImages ; i++)
309 delete ppDecodedImages[i];
312 delete[] ppDecodedImages;
313 ppDecodedImages =
nullptr;
326 StreamReceiver::StreamElementsPtr StreamReceiver::getStreamElements(std::string streamName)
328 StreamSourceMap::iterator it = streamSources.find(streamName);
330 if (it == streamSources.end())
332 throw armarx::LocalException(
"No Stream registered under the name: '") << streamName <<
"'";
338 void StreamReceiver::getImageFormat(StreamElementsPtr elem,
int& height,
int& width)
340 GstPad* pad = gst_element_get_static_pad(elem->appsink,
"sink");
348 GstCaps* caps = gst_pad_get_negotiated_caps(pad);
356 GstStructure*
s = gst_caps_get_structure(caps, 0);
357 gst_structure_get_int(
s,
"width", &width);
358 gst_structure_get_int(
s,
"height", &height);
360 gst_caps_unref(caps);
361 gst_object_unref(pad);
367 m_packet.size = chunk.size();
368 m_packet.data =
const_cast<Ice::Byte*
>(chunk.data());
371 while (m_packet.size > 0)
374 int len = avcodec_decode_video2(m_decoderContext, m_picture, &got_picture, &m_packet);
377 std::string err(
"Decoding error");
387 if (m_picture->format == AV_PIX_FMT_YUV420P)
389 static SwsContext* m_swsCtx = NULL;
391 m_swsCtx = sws_getCachedContext(m_swsCtx, m_picture->width,
392 m_picture->height, AV_PIX_FMT_YUV420P,
393 m_picture->width, m_picture->height,
394 AV_PIX_FMT_RGB24, SWS_GAUSS,
398 uint8_t* dstSlice[] = { pCombinedDecodedImage->pixels };
399 int dstStride = m_picture->width * 3;
400 if (sws_scale(m_swsCtx, m_picture->data, m_picture->linesize,
401 0, m_picture->height, dstSlice, &dstStride) != m_picture->height)
406 for (
int i = 0; i < numberImages; ++i)
408 size_t imageByteSize = ppDecodedImages[i]->width * ppDecodedImages[i]->height * ppDecodedImages[i]->bytesPerPixel;
413 memcpy(ppDecodedImages[i]->pixels, pCombinedDecodedImage->pixels + i * imageByteSize, imageByteSize);
419 ARMARX_INFO <<
"Other format: " << m_picture->format;
444 m_packet.size -= len;
445 m_packet.data += len;
458 lastReceiveTimestamp = IceUtil::Time::now();
460 if (getState() < eManagedIceObjectStarted)
465 for (
int i = 0; i < numberImages && i < (int)imagesOut.size(); ++i)
468 memcpy(imagesOut.at(i)->pixels, ppDecodedImages[i]->pixels, ppDecodedImages[i]->width * ppDecodedImages[i]->height * ppDecodedImages[i]->bytesPerPixel);
474 StreamSourceMap::iterator it = streamSources.begin();
476 for (; it != streamSources.end(); it++, i++)
480 CByteImage* image = imagesOut.at(i);
487 if (!image->m_bOwnMemory)
489 throw armarx::LocalException(
"Output images need to have there own memory");
492 StreamElementsPtr elem = it->second;
495 if (!elem->appsink || !elem->pipeline)
502 if (gst_element_get_state(elem->appsink, &state, NULL, 1000000000) == GST_STATE_CHANGE_FAILURE || state != GST_STATE_PLAYING)
504 ARMARX_ERROR <<
deactivateSpam(5) <<
"state of appsink for " << elem->streamName <<
" not playing state: " << state <<
" - skipping" << std::endl;
508 GstBuffer* buffer = gst_app_sink_pull_buffer(GST_APP_SINK(elem->appsink));
520 getImageFormat(elem, height, width);
526 int buf_size = GST_BUFFER_SIZE(buffer);
528 if (width * height * 3 != buf_size)
530 ARMARX_WARNING <<
"Invalid buffer size: actual " << buf_size <<
" vs. expected " << width* height * 3;
534 memcpy(image->pixels, GST_BUFFER_DATA(buffer), width * height * 3);
542 gst_buffer_unref(buffer);
556 streamProvider->getImageInformation(imageWidth, imageHeight, imageType);
559 void StreamReceiver::receive()
608 StreamReceiver::StreamElements::StreamElements(std::string streamName,
int streamID, StreamProviderPrx streamProvider)
610 this->streamName = streamName;
611 this-> streamProvider = streamProvider;
614 this->streamID = streamID;
618 void StreamReceiver::StreamElements::receive()
682 void StreamReceiver::store()