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>
21 #define _MSC_STDINT_H_ // We already have pstdint.h in MRPT
22 #include <libavformat/avformat.h>
23 #include <libavcodec/avcodec.h>
24 #include <libswscale/swscale.h>
25 #include <libavutil/imgutils.h>
44 AVFormatContext* pFormatCtx;
46 AVCodecContext* pCodecCtx;
50 SwsContext* img_convert_ctx;
51 std::vector<uint8_t>
buffer;
60 TFFMPEGContext m_state;
69 : m_impl(mrpt::make_impl<CFFMPEG_InputStream::Impl>())
71 TFFMPEGContext* ctx = &m_impl->m_state;
73 ctx->pFormatCtx =
nullptr;
74 ctx->pCodecCtx =
nullptr;
75 ctx->pCodec =
nullptr;
77 ctx->pFrame =
nullptr;
78 ctx->pFrameRGB =
nullptr;
79 ctx->img_convert_ctx =
nullptr;
108 const TFFMPEGContext* ctx = &
m_impl->m_state;
109 return ctx->pFormatCtx !=
nullptr;
124 TFFMPEGContext* ctx = &
m_impl->m_state;
130 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 2, 0)
131 if (avformat_open_input(&ctx->pFormatCtx,
url.c_str(),
nullptr,
nullptr) !=
134 if (av_open_input_file(
135 &ctx->pFormatCtx,
url.c_str(),
nullptr, 0,
nullptr) != 0)
139 ctx->pFormatCtx =
nullptr;
140 std::cerr <<
"[CFFMPEG_InputStream::openURL] Cannot open video: " <<
url
147 #
if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 35, 0)
148 avformat_find_stream_info(ctx->pFormatCtx,
nullptr) < 0
150 av_find_stream_info(ctx->pFormatCtx) < 0
154 std::cerr <<
"[CFFMPEG_InputStream::openURL] Couldn't find stream "
163 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 2, 0)
164 av_dump_format(ctx->pFormatCtx, 0,
url.c_str(),
false);
166 dump_format(ctx->pFormatCtx, 0,
url.c_str(),
false);
171 ctx->videoStream = -1;
172 for (
unsigned int i = 0; i < ctx->pFormatCtx->nb_streams; i++)
174 if (ctx->pFormatCtx->streams[i]->codec->codec_type ==
175 #
if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 0, 0)
182 ctx->videoStream = (int)i;
186 if (ctx->videoStream == -1)
189 <<
"[CFFMPEG_InputStream::openURL] Didn't find a video stream: "
195 ctx->pCodecCtx = ctx->pFormatCtx->streams[ctx->videoStream]->codec;
198 ctx->pCodec = avcodec_find_decoder(ctx->pCodecCtx->codec_id);
199 if (ctx->pCodec ==
nullptr)
201 std::cerr <<
"[CFFMPEG_InputStream::openURL] Codec not found: " <<
url
207 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 6, 0)
208 if (avcodec_open2(ctx->pCodecCtx, ctx->pCodec,
nullptr) < 0)
210 if (avcodec_open(ctx->pCodecCtx, ctx->pCodec) < 0)
213 std::cerr <<
"[CFFMPEG_InputStream::openURL] Could not open codec: "
218 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 46, 0)
220 ctx->pFrame = av_frame_alloc();
222 ctx->pFrameRGB = av_frame_alloc();
225 ctx->pFrame = avcodec_alloc_frame();
227 ctx->pFrameRGB = avcodec_alloc_frame();
230 if (ctx->pFrameRGB ==
nullptr || ctx->pFrame ==
nullptr)
232 std::cerr <<
"[CFFMPEG_InputStream::openURL] Could not alloc memory "
233 "for frame buffers: "
239 #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(54, 6, 0)
240 size_t numBytes = avpicture_get_size(
242 size_t numBytes = av_image_get_buffer_size(
245 #
if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 00, 0)
252 ctx->pCodecCtx->width, ctx->pCodecCtx->height
253 #
if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(54, 6, 0)
259 ctx->buffer.resize(numBytes);
263 (AVPicture*)ctx->pFrameRGB, &ctx->buffer[0],
265 #
if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 00, 0)
272 ctx->pCodecCtx->width, ctx->pCodecCtx->height);
286 if (!this->
isOpen())
return;
288 TFFMPEGContext* ctx = &
m_impl->m_state;
293 avcodec_close(ctx->pCodecCtx);
294 ctx->pCodecCtx =
nullptr;
300 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 35, 0)
301 avformat_close_input(&ctx->pFormatCtx);
303 av_close_input_file(ctx->pFormatCtx);
305 ctx->pFormatCtx =
nullptr;
313 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 46, 0)
314 av_frame_free(&ctx->pFrameRGB);
316 av_free(ctx->pFrameRGB);
318 ctx->pFrameRGB =
nullptr;
322 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 46, 0)
323 av_frame_free(&ctx->pFrame);
325 av_free(ctx->pFrame);
327 ctx->pFrame =
nullptr;
330 if (ctx->img_convert_ctx)
332 sws_freeContext(ctx->img_convert_ctx);
333 ctx->img_convert_ctx =
nullptr;
345 if (!this->
isOpen())
return false;
347 TFFMPEGContext* ctx = &
m_impl->m_state;
352 while (av_read_frame(ctx->pFormatCtx, &packet) >= 0)
355 if (packet.stream_index == ctx->videoStream)
358 #if LIBAVCODEC_VERSION_MAJOR > 52 || \
359 (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 72)
360 avcodec_decode_video2(
361 ctx->pCodecCtx, ctx->pFrame, &frameFinished, &packet);
363 avcodec_decode_video(
364 ctx->pCodecCtx, ctx->pFrame, &frameFinished, packet.data,
371 ctx->img_convert_ctx = sws_getCachedContext(
372 ctx->img_convert_ctx, ctx->pCodecCtx->width,
373 ctx->pCodecCtx->height, ctx->pCodecCtx->pix_fmt,
374 ctx->pCodecCtx->width, ctx->pCodecCtx->height,
376 #
if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 00, 0)
383 SWS_BICUBIC,
nullptr,
nullptr,
nullptr);
386 ctx->img_convert_ctx, ctx->pFrame->data,
387 ctx->pFrame->linesize, 0, ctx->pCodecCtx->height,
388 ctx->pFrameRGB->data, ctx->pFrameRGB->linesize);
396 if (ctx->pFrameRGB->linesize[0] !=
399 "FIXME: linesize!=width case not handled yet.")
402 ctx->pCodecCtx->width, ctx->pCodecCtx->height,
404 ctx->pFrameRGB->data[0]);
407 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 16, 0)
408 av_free_packet(&packet);
410 av_packet_unref(&packet);
417 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 16, 0)
418 av_free_packet(&packet);
420 av_packet_unref(&packet);
436 if (!this->
isOpen())
return -1;
438 const TFFMPEGContext* ctx = &
m_impl->m_state;
440 if (!ctx->pCodecCtx)
return -1;
442 return static_cast<double>(ctx->pCodecCtx->time_base.den) /
443 ctx->pCodecCtx->time_base.num;