StreamDecoderImageProvider.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package VisionX::ArmarXObjects::StreamDecoderImageProvider
17  * @author Mirko Waechter ( mirko dot waechter at kit dot edu )
18  * @date 2016
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
24 
25 #include <Image/ByteImage.h>
26 using namespace armarx;
27 
28 
30 {
31  pCombinedDecodedImage = NULL;
32  usingProxy(getProperty<std::string>("UsedStreamProvider").getValue());
33  usingTopic(getProperty<std::string>("imageStreamTopicName").getValue());
34  numberImages = 0;
35 
36  avcodec_register_all();
37  av_init_packet(&m_packet);
38  m_decoder = avcodec_find_decoder(AV_CODEC_ID_H264);
39  if (!m_decoder)
40  {
41  ARMARX_ERROR << ("Can't find H264 decoder!");
42  }
43  m_decoderContext = avcodec_alloc_context3(m_decoder);
44 
45  if (m_decoder->capabilities & AV_CODEC_CAP_TRUNCATED)
46  {
47  m_decoderContext->flags |= AV_CODEC_FLAG_TRUNCATED;
48  }
49 
50 
51  //we can receive truncated frames
52  m_decoderContext->flags2 |= AV_CODEC_FLAG2_CHUNKS;
53  m_decoderContext->thread_count = 4;//TODO: random value. May be changing can make decoding faster
54 
55  AVDictionary* dictionary = nullptr;
56  if (avcodec_open2(m_decoderContext, m_decoder, &dictionary) < 0)
57  {
58  ARMARX_ERROR << "Could not open decoder";
59  }
60  ARMARX_INFO << "H264 Decoder successfully opened";
61 
62  //m_picture = avcodec_alloc_frame();
63  m_picture = av_frame_alloc();
64 }
65 
66 
68 {
69  std::unique_lock lock(decodedImageMutex);
70  ppDecodedImages = new CByteImage*[numberImages];
71 
72  streamProvider = getProxy<Stream::StreamProviderPrx>(getProperty<std::string>("UsedStreamProvider").getValue());
73  // codec = streamProvider->getCodecType();
74  numberImages = streamProvider->getNumberOfImages();
76  int imgWidth, imgHeight, imgType;
77  streamProvider->getImageInformation(imgWidth, imgHeight, imgType);
78  ARMARX_INFO << "number of Images: " << numberImages;
79  for (int i = 0; i < numberImages ; i++)
80  {
81  ppDecodedImages[i] = new CByteImage(imgWidth, imgHeight, CByteImage::eRGB24);
82  }
83  pCombinedDecodedImage = new CByteImage(imgWidth, imgHeight * numberImages, CByteImage::eRGB24);
84  setImageFormat(visionx::ImageDimension(imgWidth, imgHeight), visionx::eRgb);
85  ImageProvider::onConnectComponent();
86 }
87 
88 
90 {
91  std::unique_lock lock(decodedImageMutex);
92  delete pCombinedDecodedImage;
93  pCombinedDecodedImage = nullptr;
94  if (ppDecodedImages)
95  {
96  for (int i = 0; i < numberImages ; i++)
97  {
98  delete ppDecodedImages[i];
99  }
100 
101  delete[] ppDecodedImages;
102  ppDecodedImages = nullptr;
103  }
104 
105 }
106 
107 
109 {
110 
111 }
112 
114 {
117 }
118 
119 void StreamDecoderImageProvider::reportNewStreamData(const Stream::DataChunk& chunk, Ice::Long imageTimestamp, const Ice::Current&)
120 {
121  std::unique_lock lock(streamDecodeMutex);
122  m_packet.size = chunk.size();
123  m_packet.data = const_cast<Ice::Byte*>(chunk.data());
124  // ARMARX_INFO << "H264Decoder: received encoded frame with framesize " << enc_frame.size();
125 
126  while (m_packet.size > 0)
127  {
128  int got_picture;
129 #pragma GCC diagnostic push
130 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
131  int len = avcodec_decode_video2(m_decoderContext, m_picture, &got_picture, &m_packet);
132 #pragma GCC diagnostic pop
133  if (len < 0)
134  {
135  std::string err("Decoding error");
136  ARMARX_ERROR << err;
137  return;
138  }
139  if (got_picture)
140  {
141  ARMARX_DEBUG << deactivateSpam(1) << "H264Decoder: frame decoded!";
142  // std::vector<unsigned char> result;
143  // this->storePicture(result);
144 
145  if (m_picture->format == AV_PIX_FMT_YUV420P)
146  {
147 
148  // QImage frame_img = QImage(width, height, QImage::Format_RGB888);
149  m_swsCtx = sws_getCachedContext(m_swsCtx, m_picture->width,
150  m_picture->height, AV_PIX_FMT_YUV420P,
151  m_picture->width, m_picture->height,
152  AV_PIX_FMT_RGB24, SWS_GAUSS,
153  NULL, NULL, NULL);
154  std::unique_lock lock(decodedImageMutex);
155 
156  uint8_t* dstSlice[] = { pCombinedDecodedImage->pixels };
157  int dstStride = m_picture->width * 3;
158  if (sws_scale(m_swsCtx, m_picture->data, m_picture->linesize,
159  0, m_picture->height, dstSlice, &dstStride) != m_picture->height)
160  {
161  ARMARX_INFO << "SCALING FAILED!";
162  return;
163  }
164  for (int i = 0; i < numberImages; ++i)
165  {
166  size_t imageByteSize = ppDecodedImages[i]->width * ppDecodedImages[i]->height * ppDecodedImages[i]->bytesPerPixel;
167  // if(ppInputImages[i]->type != CByteImage::eRGB24)
168  // {
169  // ::ImageProcessor::ConvertImage(imageProviderInfo, eRgb,)
170  // }
171  memcpy(ppDecodedImages[i]->pixels, pCombinedDecodedImage->pixels + i * imageByteSize, imageByteSize);
172  }
173  updateTimestamp(imageTimestamp);
175  // ARMARX_INFO << "New decoded image!";
176  }
177  else
178  {
179  ARMARX_INFO << "Other format: " << m_picture->format;
180  }
181 
182  // emit newDecodedFrame(frame_img);
183  // }
184  // else if (m_picture->format == PIX_FMT_RGB32)
185  // {
186  // QImage img = QImage(result.data(), m_picture->width, m_picture->height, QImage::Format_RGB32);
187  // ARMARX_INFO << "New decoded image!";
188  // emit newDecodedFrame(img);
189  // }
190  // else if (m_picture->format == AV_PIX_FMT_RGB24)
191  // {
192  // QImage img = QImage(result.data(), m_picture->width, m_picture->height, QImage::Format_RGB888);
193  // ARMARX_INFO << "New decoded image!";
194  // emit newDecodedFrame(img);
195  // }
196  // else
197  // {
198  // std::string err = std::string( "Unsupported pixel format! Can't create QImage!");
199  // ARMARX_INFO << err;
200  // emit criticalError( err );
201  // return false;
202  // }
203  }
204  m_packet.size -= len;
205  m_packet.data += len;
206  }
207 
208 
209 }
210 
armarx::StreamDecoderImageProvider::numberImages
int numberImages
Definition: StreamDecoderImageProvider.h:99
armarx::StreamDecoderImageProvider::onDisconnectImageProvider
void onDisconnectImageProvider() override
Definition: StreamDecoderImageProvider.cpp:89
armarx::StreamDecoderImageProvider::m_swsCtx
SwsContext * m_swsCtx
Definition: StreamDecoderImageProvider.h:107
armarx::StreamDecoderImageProvider::m_packet
AVPacket m_packet
Definition: StreamDecoderImageProvider.h:104
armarx::StreamDecoderImageProvider::decodedImageMutex
std::mutex decodedImageMutex
Definition: StreamDecoderImageProvider.h:105
armarx::StreamDecoderImageProvider::onExitImageProvider
void onExitImageProvider() override
This is called when the Component::onExitComponent() setup is called.
Definition: StreamDecoderImageProvider.cpp:108
armarx::StreamDecoderImageProvider::streamDecodeMutex
std::mutex streamDecodeMutex
Definition: StreamDecoderImageProvider.h:106
visionx::ImageProvider::setImageFormat
void setImageFormat(ImageDimension imageDimension, ImageType imageType, BayerPatternType bayerPatternType=visionx::eBayerPatternRg)
Sets the image basic format data.
Definition: ImageProvider.cpp:275
armarx::StreamDecoderImageProvider::pCombinedDecodedImage
CByteImage * pCombinedDecodedImage
Definition: StreamDecoderImageProvider.h:108
visionx::ImageProvider::updateTimestamp
void updateTimestamp(Ice::Long timestamp, bool threadSafe=true)
Updates the timestamp of the currently captured image.
Definition: ImageProvider.cpp:165
StreamDecoderImageProvider.h
armarx::StreamDecoderImageProvider::m_picture
AVFrame * m_picture
Definition: StreamDecoderImageProvider.h:103
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::VariantType::Long
const VariantTypeId Long
Definition: Variant.h:917
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
armarx::StreamDecoderImageProvider::m_decoderContext
AVCodecContext * m_decoderContext
Definition: StreamDecoderImageProvider.h:101
visionx::ImageProvider::provideImages
void provideImages(void **inputBuffers, const IceUtil::Time &imageTimestamp=IceUtil::Time())
send images raw.
Definition: ImageProvider.cpp:319
armarx::StreamDecoderImageProvider::m_decoder
AVCodec * m_decoder
Definition: StreamDecoderImageProvider.h:100
visionx::ImageProvider::setNumberImages
void setNumberImages(int numberImages)
Sets the number of images on each capture.
Definition: ImageProvider.cpp:313
armarx::ManagedIceObject::usingTopic
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Definition: ManagedIceObject.cpp:248
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:74
armarx::StreamDecoderImageProvider::ppDecodedImages
CByteImage ** ppDecodedImages
Definition: StreamDecoderImageProvider.h:108
armarx::StreamDecoderImageProvider::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: StreamDecoderImageProvider.cpp:113
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::StreamDecoderImageProvider::onInitImageProvider
void onInitImageProvider() override
This is called when the Component::onInitComponent() is called.
Definition: StreamDecoderImageProvider.cpp:29
armarx::StreamDecoderImageProvider::reportNewStreamData
void reportNewStreamData(const Stream::DataChunk &chunk, Ice::Long imageTimestamp, const Ice::Current &) override
Definition: StreamDecoderImageProvider.cpp:119
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::StreamDecoderImageProvider::streamProvider
Stream::StreamProviderPrx streamProvider
Definition: StreamDecoderImageProvider.h:97
armarx::Logging::deactivateSpam
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.
Definition: Logging.cpp:92
armarx::StreamDecoderImageProviderPropertyDefinitions
Definition: StreamDecoderImageProvider.h:47
armarx::StreamDecoderImageProvider::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: StreamDecoderImageProvider.cpp:67
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:34
armarx::ManagedIceObject::usingProxy
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Definition: ManagedIceObject.cpp:151
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28