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 void
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 =
54  4; //TODO: random value. May be changing can make decoding faster
55 
56  AVDictionary* dictionary = nullptr;
57  if (avcodec_open2(m_decoderContext, m_decoder, &dictionary) < 0)
58  {
59  ARMARX_ERROR << "Could not open decoder";
60  }
61  ARMARX_INFO << "H264 Decoder successfully opened";
62 
63  //m_picture = avcodec_alloc_frame();
64  m_picture = av_frame_alloc();
65 }
66 
67 void
69 {
70  std::unique_lock lock(decodedImageMutex);
71  ppDecodedImages = new CByteImage*[numberImages];
72 
73  streamProvider = getProxy<Stream::StreamProviderPrx>(
74  getProperty<std::string>("UsedStreamProvider").getValue());
75  // codec = streamProvider->getCodecType();
76  numberImages = streamProvider->getNumberOfImages();
78  int imgWidth, imgHeight, imgType;
79  streamProvider->getImageInformation(imgWidth, imgHeight, imgType);
80  ARMARX_INFO << "number of Images: " << numberImages;
81  for (int i = 0; i < numberImages; i++)
82  {
83  ppDecodedImages[i] = new CByteImage(imgWidth, imgHeight, CByteImage::eRGB24);
84  }
85  pCombinedDecodedImage = new CByteImage(imgWidth, imgHeight * numberImages, CByteImage::eRGB24);
86  setImageFormat(visionx::ImageDimension(imgWidth, imgHeight), visionx::eRgb);
87  ImageProvider::onConnectComponent();
88 }
89 
90 void
92 {
93  std::unique_lock lock(decodedImageMutex);
94  delete pCombinedDecodedImage;
95  pCombinedDecodedImage = nullptr;
96  if (ppDecodedImages)
97  {
98  for (int i = 0; i < numberImages; i++)
99  {
100  delete ppDecodedImages[i];
101  }
102 
103  delete[] ppDecodedImages;
104  ppDecodedImages = nullptr;
105  }
106 }
107 
108 void
110 {
111 }
112 
115 {
118 }
119 
120 void
121 StreamDecoderImageProvider::reportNewStreamData(const Stream::DataChunk& chunk,
122  Ice::Long imageTimestamp,
123  const Ice::Current&)
124 {
125  std::unique_lock lock(streamDecodeMutex);
126  m_packet.size = chunk.size();
127  m_packet.data = const_cast<Ice::Byte*>(chunk.data());
128  // ARMARX_INFO << "H264Decoder: received encoded frame with framesize " << enc_frame.size();
129 
130  while (m_packet.size > 0)
131  {
132  int got_picture;
133 #pragma GCC diagnostic push
134 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
135  int len = avcodec_decode_video2(m_decoderContext, m_picture, &got_picture, &m_packet);
136 #pragma GCC diagnostic pop
137  if (len < 0)
138  {
139  std::string err("Decoding error");
140  ARMARX_ERROR << err;
141  return;
142  }
143  if (got_picture)
144  {
145  ARMARX_DEBUG << deactivateSpam(1) << "H264Decoder: frame decoded!";
146  // std::vector<unsigned char> result;
147  // this->storePicture(result);
148 
149  if (m_picture->format == AV_PIX_FMT_YUV420P)
150  {
151 
152  // QImage frame_img = QImage(width, height, QImage::Format_RGB888);
153  m_swsCtx = sws_getCachedContext(m_swsCtx,
154  m_picture->width,
155  m_picture->height,
156  AV_PIX_FMT_YUV420P,
157  m_picture->width,
158  m_picture->height,
159  AV_PIX_FMT_RGB24,
160  SWS_GAUSS,
161  NULL,
162  NULL,
163  NULL);
164  std::unique_lock lock(decodedImageMutex);
165 
166  uint8_t* dstSlice[] = {pCombinedDecodedImage->pixels};
167  int dstStride = m_picture->width * 3;
168  if (sws_scale(m_swsCtx,
169  m_picture->data,
170  m_picture->linesize,
171  0,
172  m_picture->height,
173  dstSlice,
174  &dstStride) != m_picture->height)
175  {
176  ARMARX_INFO << "SCALING FAILED!";
177  return;
178  }
179  for (int i = 0; i < numberImages; ++i)
180  {
181  size_t imageByteSize = ppDecodedImages[i]->width * ppDecodedImages[i]->height *
182  ppDecodedImages[i]->bytesPerPixel;
183  // if(ppInputImages[i]->type != CByteImage::eRGB24)
184  // {
185  // ::ImageProcessor::ConvertImage(imageProviderInfo, eRgb,)
186  // }
187  memcpy(ppDecodedImages[i]->pixels,
188  pCombinedDecodedImage->pixels + i * imageByteSize,
189  imageByteSize);
190  }
191  updateTimestamp(imageTimestamp);
193  // ARMARX_INFO << "New decoded image!";
194  }
195  else
196  {
197  ARMARX_INFO << "Other format: " << m_picture->format;
198  }
199 
200  // emit newDecodedFrame(frame_img);
201  // }
202  // else if (m_picture->format == PIX_FMT_RGB32)
203  // {
204  // QImage img = QImage(result.data(), m_picture->width, m_picture->height, QImage::Format_RGB32);
205  // ARMARX_INFO << "New decoded image!";
206  // emit newDecodedFrame(img);
207  // }
208  // else if (m_picture->format == AV_PIX_FMT_RGB24)
209  // {
210  // QImage img = QImage(result.data(), m_picture->width, m_picture->height, QImage::Format_RGB888);
211  // ARMARX_INFO << "New decoded image!";
212  // emit newDecodedFrame(img);
213  // }
214  // else
215  // {
216  // std::string err = std::string( "Unsupported pixel format! Can't create QImage!");
217  // ARMARX_INFO << err;
218  // emit criticalError( err );
219  // return false;
220  // }
221  }
222  m_packet.size -= len;
223  m_packet.data += len;
224  }
225 }
armarx::StreamDecoderImageProvider::numberImages
int numberImages
Definition: StreamDecoderImageProvider.h:105
armarx::StreamDecoderImageProvider::onDisconnectImageProvider
void onDisconnectImageProvider() override
Definition: StreamDecoderImageProvider.cpp:91
armarx::StreamDecoderImageProvider::m_swsCtx
SwsContext * m_swsCtx
Definition: StreamDecoderImageProvider.h:113
armarx::StreamDecoderImageProvider::m_packet
AVPacket m_packet
Definition: StreamDecoderImageProvider.h:110
armarx::StreamDecoderImageProvider::decodedImageMutex
std::mutex decodedImageMutex
Definition: StreamDecoderImageProvider.h:111
armarx::StreamDecoderImageProvider::onExitImageProvider
void onExitImageProvider() override
This is called when the Component::onExitComponent() setup is called.
Definition: StreamDecoderImageProvider.cpp:109
armarx::StreamDecoderImageProvider::streamDecodeMutex
std::mutex streamDecodeMutex
Definition: StreamDecoderImageProvider.h:112
visionx::ImageProvider::setImageFormat
void setImageFormat(ImageDimension imageDimension, ImageType imageType, BayerPatternType bayerPatternType=visionx::eBayerPatternRg)
Sets the image basic format data.
Definition: ImageProvider.cpp:305
armarx::StreamDecoderImageProvider::pCombinedDecodedImage
CByteImage * pCombinedDecodedImage
Definition: StreamDecoderImageProvider.h:114
visionx::ImageProvider::updateTimestamp
void updateTimestamp(Ice::Long timestamp, bool threadSafe=true)
Updates the timestamp of the currently captured image.
Definition: ImageProvider.cpp:175
StreamDecoderImageProvider.h
armarx::StreamDecoderImageProvider::m_picture
AVFrame * m_picture
Definition: StreamDecoderImageProvider.h:109
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::VariantType::Long
const VariantTypeId Long
Definition: Variant.h:918
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::StreamDecoderImageProvider::m_decoderContext
AVCodecContext * m_decoderContext
Definition: StreamDecoderImageProvider.h:107
visionx::ImageProvider::provideImages
void provideImages(void **inputBuffers, const IceUtil::Time &imageTimestamp=IceUtil::Time())
send images raw.
Definition: ImageProvider.cpp:351
armarx::StreamDecoderImageProvider::m_decoder
AVCodec * m_decoder
Definition: StreamDecoderImageProvider.h:106
visionx::ImageProvider::setNumberImages
void setNumberImages(int numberImages)
Sets the number of images on each capture.
Definition: ImageProvider.cpp:344
armarx::ManagedIceObject::usingTopic
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Definition: ManagedIceObject.cpp:254
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
armarx::StreamDecoderImageProvider::ppDecodedImages
CByteImage ** ppDecodedImages
Definition: StreamDecoderImageProvider.h:114
armarx::StreamDecoderImageProvider::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: StreamDecoderImageProvider.cpp:114
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
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:121
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::StreamDecoderImageProvider::streamProvider
Stream::StreamProviderPrx streamProvider
Definition: StreamDecoderImageProvider.h:101
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:99
armarx::StreamDecoderImageProviderPropertyDefinitions
Definition: StreamDecoderImageProvider.h:47
armarx::StreamDecoderImageProvider::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: StreamDecoderImageProvider.cpp:68
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:35
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:154
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27