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 <libavformat/avformat.h> 24 #include <libavcodec/avcodec.h> 25 #include <libswscale/swscale.h> 26 #include <libavutil/imgutils.h> 45 AVFormatContext* pFormatCtx;
47 AVCodecContext* pCodecCtx;
51 SwsContext* img_convert_ctx;
52 std::vector<uint8_t>
buffer;
58 #define MY_FFMPEG_STATE \ 59 const_cast<TFFMPEGContext*>( \ 60 static_cast<const TFFMPEGContext*>(m_state.get())) 71 ctx->pFormatCtx =
nullptr;
72 ctx->pCodecCtx =
nullptr;
73 ctx->pCodec =
nullptr;
75 ctx->pFrame =
nullptr;
76 ctx->pFrameRGB =
nullptr;
77 ctx->img_convert_ctx =
nullptr;
108 return ctx->pFormatCtx !=
nullptr;
118 const std::string& url,
bool grab_as_grayscale,
bool verbose)
129 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 2, 0) 130 if (avformat_open_input(&ctx->pFormatCtx, url.c_str(),
nullptr,
nullptr) !=
133 if (av_open_input_file(
134 &ctx->pFormatCtx, url.c_str(),
nullptr, 0,
nullptr) != 0)
138 ctx->pFormatCtx =
nullptr;
139 std::cerr <<
"[CFFMPEG_InputStream::openURL] Cannot open video: " << url
146 #
if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 35, 0)
147 avformat_find_stream_info(ctx->pFormatCtx,
nullptr) < 0
149 av_find_stream_info(ctx->pFormatCtx) < 0
153 std::cerr <<
"[CFFMPEG_InputStream::openURL] Couldn't find stream " 162 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 2, 0) 163 av_dump_format(ctx->pFormatCtx, 0, url.c_str(),
false);
165 dump_format(ctx->pFormatCtx, 0, url.c_str(),
false);
170 ctx->videoStream = -1;
171 for (
unsigned int i = 0; i < ctx->pFormatCtx->nb_streams; i++)
173 if (ctx->pFormatCtx->streams[i]->codec->codec_type ==
174 #
if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(53, 0, 0)
181 ctx->videoStream = (int)i;
185 if (ctx->videoStream == -1)
188 <<
"[CFFMPEG_InputStream::openURL] Didn't find a video stream: " 194 ctx->pCodecCtx = ctx->pFormatCtx->streams[ctx->videoStream]->codec;
197 ctx->pCodec = avcodec_find_decoder(ctx->pCodecCtx->codec_id);
198 if (ctx->pCodec ==
nullptr)
200 std::cerr <<
"[CFFMPEG_InputStream::openURL] Codec not found: " << url
206 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 6, 0) 207 if (avcodec_open2(ctx->pCodecCtx, ctx->pCodec,
nullptr) < 0)
209 if (avcodec_open(ctx->pCodecCtx, ctx->pCodec) < 0)
212 std::cerr <<
"[CFFMPEG_InputStream::openURL] Could not open codec: " 217 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 46, 0) 219 ctx->pFrame = av_frame_alloc();
221 ctx->pFrameRGB = av_frame_alloc();
224 ctx->pFrame = avcodec_alloc_frame();
226 ctx->pFrameRGB = avcodec_alloc_frame();
229 if (ctx->pFrameRGB ==
nullptr || ctx->pFrame ==
nullptr)
231 std::cerr <<
"[CFFMPEG_InputStream::openURL] Could not alloc memory " 232 "for frame buffers: " 238 #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(54, 6, 0) 239 size_t numBytes = avpicture_get_size(
241 size_t numBytes = av_image_get_buffer_size(
244 #
if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 00, 0)
251 ctx->pCodecCtx->width, ctx->pCodecCtx->height
252 #
if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(54, 6, 0)
258 ctx->buffer.resize(numBytes);
262 (AVPicture*)ctx->pFrameRGB, &ctx->buffer[0],
264 #
if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 00, 0)
271 ctx->pCodecCtx->width, ctx->pCodecCtx->height);
285 if (!this->
isOpen())
return;
292 avcodec_close(ctx->pCodecCtx);
293 ctx->pCodecCtx =
nullptr;
299 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 35, 0) 300 avformat_close_input(&ctx->pFormatCtx);
302 av_close_input_file(ctx->pFormatCtx);
304 ctx->pFormatCtx =
nullptr;
312 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 46, 0) 313 av_frame_free(&ctx->pFrameRGB);
315 av_free(ctx->pFrameRGB);
317 ctx->pFrameRGB =
nullptr;
321 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 46, 0) 322 av_frame_free(&ctx->pFrame);
324 av_free(ctx->pFrame);
326 ctx->pFrame =
nullptr;
329 if (ctx->img_convert_ctx)
331 sws_freeContext(ctx->img_convert_ctx);
332 ctx->img_convert_ctx =
nullptr;
344 if (!this->
isOpen())
return false;
351 while (av_read_frame(ctx->pFormatCtx, &packet) >= 0)
354 if (packet.stream_index == ctx->videoStream)
357 #if LIBAVCODEC_VERSION_MAJOR > 52 || \ 358 (LIBAVCODEC_VERSION_MAJOR == 52 && LIBAVCODEC_VERSION_MINOR >= 72) 359 avcodec_decode_video2(
360 ctx->pCodecCtx, ctx->pFrame, &frameFinished, &packet);
362 avcodec_decode_video(
363 ctx->pCodecCtx, ctx->pFrame, &frameFinished, packet.data,
370 ctx->img_convert_ctx = sws_getCachedContext(
371 ctx->img_convert_ctx, ctx->pCodecCtx->width,
372 ctx->pCodecCtx->height, ctx->pCodecCtx->pix_fmt,
373 ctx->pCodecCtx->width, ctx->pCodecCtx->height,
375 #
if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 00, 0)
382 SWS_BICUBIC,
nullptr,
nullptr,
nullptr);
385 ctx->img_convert_ctx, ctx->pFrame->data,
386 ctx->pFrame->linesize, 0, ctx->pCodecCtx->height,
387 ctx->pFrameRGB->data, ctx->pFrameRGB->linesize);
395 if (ctx->pFrameRGB->linesize[0] !=
398 "FIXME: linesize!=width case not handled yet.")
401 ctx->pCodecCtx->width, ctx->pCodecCtx->height,
403 ctx->pFrameRGB->data[0]);
406 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 16, 0) 407 av_free_packet(&packet);
409 av_packet_unref(&packet);
416 #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 16, 0) 417 av_free_packet(&packet);
419 av_packet_unref(&packet);
435 if (!this->
isOpen())
return -1;
439 if (!ctx->pCodecCtx)
return -1;
441 return static_cast<double>(ctx->pCodecCtx->time_base.den) /
442 ctx->pCodecCtx->time_base.num;
A class for storing images as grayscale or RGB bitmaps.
#define THROW_EXCEPTION(msg)
Contains classes for various device interfaces.
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.
GLsizei const GLchar ** string
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void set(const T *p)
This method can change the pointer, since the change is made explicitly, not through copy operators t...