10 #if defined(__GNUC__) // Needed for ffmpeg headers. Only allowed here when not 12 #define __STDC_CONSTANT_MACROS // Needed for having "UINT64_C" and so 17 #include <mrpt/config.h> 22 #define _MSC_STDINT_H_ // We already have pstdint.h in MRPT 23 #include <libavcodec/avcodec.h> 24 #include <libavformat/avformat.h> 25 #include <libavutil/imgutils.h> 26 #include <libswscale/swscale.h> 43 AVFormatContext* pFormatCtx{
nullptr};
45 AVCodecParameters* pCodecPars{
nullptr};
46 AVCodec* pCodec{
nullptr};
47 AVCodecContext* pCodecCtx{
nullptr};
48 AVFrame* pFrame{
nullptr};
49 AVFrame* pFrameRGB{
nullptr};
50 SwsContext* img_convert_ctx{
nullptr};
51 std::vector<uint8_t> buffer;
59 TFFMPEGContext m_state;
68 : m_impl(mrpt::make_impl<CFFMPEG_InputStream::Impl>())
71 #if LIBAVFORMAT_VERSION_MAJOR < 58 99 const TFFMPEGContext* ctx = &
m_impl->m_state;
100 return ctx->pFormatCtx !=
nullptr;
110 const std::string&
url,
bool grab_as_grayscale,
bool verbose)
115 TFFMPEGContext* ctx = &
m_impl->m_state;
121 if (avformat_open_input(&ctx->pFormatCtx,
url.c_str(),
nullptr,
nullptr) !=
124 ctx->pFormatCtx =
nullptr;
125 std::cerr <<
"[CFFMPEG_InputStream::openURL] Cannot open video: " <<
url 131 if (avformat_find_stream_info(ctx->pFormatCtx,
nullptr) < 0)
133 std::cerr <<
"[CFFMPEG_InputStream::openURL] Couldn't find stream " 142 av_dump_format(ctx->pFormatCtx, 0,
url.c_str(),
false);
146 ctx->videoStream = -1;
147 for (
unsigned int i = 0; i < ctx->pFormatCtx->nb_streams; i++)
149 if (ctx->pFormatCtx->streams[i]->codecpar->codec_type ==
152 ctx->videoStream = (int)i;
156 if (ctx->videoStream == -1)
159 <<
"[CFFMPEG_InputStream::openURL] Didn't find a video stream: " 165 ctx->pCodecPars = ctx->pFormatCtx->streams[ctx->videoStream]->codecpar;
168 ctx->pCodec = avcodec_find_decoder(ctx->pCodecPars->codec_id);
169 if (ctx->pCodec ==
nullptr)
171 std::cerr <<
"[CFFMPEG_InputStream::openURL] Codec not found: " <<
url 176 ctx->pCodecCtx = avcodec_alloc_context3(
nullptr );
179 std::cerr <<
"[CFFMPEG_InputStream::openURL] Cannot alloc avcodec " 186 if (avcodec_parameters_to_context(
188 ctx->pFormatCtx->streams[ctx->videoStream]->codecpar))
190 std::cerr <<
"[CFFMPEG_InputStream::openURL] Failed " 191 "avcodec_parameters_to_context() for: " 197 ctx->pCodecCtx->codec_id = ctx->pCodec->id;
200 if (avcodec_open2(ctx->pCodecCtx, ctx->pCodec,
nullptr) < 0)
203 <<
"[CFFMPEG_InputStream::openURL] avcodec_open2() failed for: " 209 ctx->pFrame = av_frame_alloc();
211 ctx->pFrameRGB = av_frame_alloc();
213 if (ctx->pFrameRGB ==
nullptr || ctx->pFrame ==
nullptr)
215 std::cerr <<
"[CFFMPEG_InputStream::openURL] Could not alloc memory " 216 "for frame buffers: " 222 int numBytes = av_image_get_buffer_size(
224 ctx->pCodecPars->width, ctx->pCodecPars->height, 1);
227 std::cerr <<
"[CFFMPEG_InputStream::openURL] av_image_get_buffer_size " 229 << numBytes << std::endl;
233 ctx->buffer.resize(numBytes);
237 av_image_fill_arrays(
238 ctx->pFrameRGB->data, ctx->pFrameRGB->linesize, &ctx->buffer[0],
240 ctx->pCodecPars->width, ctx->pCodecPars->height, 1);
254 if (!this->
isOpen())
return;
256 TFFMPEGContext* ctx = &
m_impl->m_state;
261 avcodec_close(ctx->pCodecCtx);
262 ctx->pCodecCtx =
nullptr;
268 avformat_close_input(&ctx->pFormatCtx);
269 ctx->pFormatCtx =
nullptr;
277 av_frame_free(&ctx->pFrameRGB);
278 ctx->pFrameRGB =
nullptr;
282 av_frame_free(&ctx->pFrame);
283 ctx->pFrame =
nullptr;
286 if (ctx->img_convert_ctx)
288 sws_freeContext(ctx->img_convert_ctx);
289 ctx->img_convert_ctx =
nullptr;
301 if (!this->
isOpen())
return false;
303 TFFMPEGContext* ctx = &
m_impl->m_state;
307 while (av_read_frame(ctx->pFormatCtx, &packet) >= 0)
310 if (packet.stream_index == ctx->videoStream)
313 int ret = avcodec_send_packet(ctx->pCodecCtx, &packet);
317 <<
"[CFFMPEG_InputStream] avcodec_send_packet error code=" 323 ret = avcodec_receive_frame(ctx->pCodecCtx, ctx->pFrame);
324 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
328 std::cerr <<
"[CFFMPEG_InputStream] avcodec_receive_frame " 335 ctx->img_convert_ctx = sws_getCachedContext(
336 ctx->img_convert_ctx, ctx->pCodecPars->width,
337 ctx->pCodecPars->height, ctx->pCodecCtx->pix_fmt,
338 ctx->pCodecPars->width, ctx->pCodecPars->height,
342 SWS_BICUBIC,
nullptr,
nullptr,
nullptr);
345 ctx->img_convert_ctx, ctx->pFrame->data, ctx->pFrame->linesize,
346 0, ctx->pCodecPars->height, ctx->pFrameRGB->data,
347 ctx->pFrameRGB->linesize);
354 if (ctx->pFrameRGB->linesize[0] !=
359 ctx->pCodecPars->width, ctx->pCodecPars->height,
361 ctx->pFrameRGB->data[0]);
364 av_packet_unref(&packet);
369 av_packet_unref(&packet);
384 if (!this->
isOpen())
return -1;
386 const TFFMPEGContext* ctx = &
m_impl->m_state;
388 if (!ctx->pCodecCtx)
return -1;
390 return static_cast<double>(ctx->pCodecCtx->time_base.den) /
391 ctx->pCodecCtx->time_base.num;
#define THROW_EXCEPTION(msg)
Contains classes for various device interfaces.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
A class for storing images as grayscale or RGB bitmaps.
void loadFromMemoryBuffer(unsigned int width, unsigned int height, bool color, unsigned char *rawpixels, bool swapRedBlue=false)
Reads the image from raw pixels buffer in memory.