From 67be4abd22b726e277c4b67bfb3abf5a65cfd9b5 Mon Sep 17 00:00:00 2001 From: Zane van Iperen Date: Mon, 15 Mar 2021 17:23:23 +1000 Subject: [PATCH 1/9] lib/moviedecoder: remove unused variable --- libffmpegthumbnailer/moviedecoder.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libffmpegthumbnailer/moviedecoder.cpp b/libffmpegthumbnailer/moviedecoder.cpp index 290e212..aa44adf 100644 --- a/libffmpegthumbnailer/moviedecoder.cpp +++ b/libffmpegthumbnailer/moviedecoder.cpp @@ -570,8 +570,6 @@ bool MovieDecoder::getVideoPacket() bool framesAvailable = true; bool frameDecoded = false; - int attempts = 0; - if (m_pPacket) { av_packet_unref(m_pPacket); From 66f64668e7a063e790813c7733ca438ab112af89 Mon Sep 17 00:00:00 2001 From: Zane van Iperen Date: Mon, 15 Mar 2021 17:42:07 +1000 Subject: [PATCH 2/9] lib/moviedecoder: clang-tidy fixes --- libffmpegthumbnailer/moviedecoder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libffmpegthumbnailer/moviedecoder.cpp b/libffmpegthumbnailer/moviedecoder.cpp index aa44adf..79c950b 100644 --- a/libffmpegthumbnailer/moviedecoder.cpp +++ b/libffmpegthumbnailer/moviedecoder.cpp @@ -503,12 +503,12 @@ void MovieDecoder::seek(int timeInSeconds) avcodec_flush_buffers(m_pFormatContext->streams[m_VideoStream]->codec); int keyFrameAttempts = 0; - bool gotFrame = 0; + bool gotFrame; do { int count = 0; - gotFrame = 0; + gotFrame = false; while (!gotFrame && count < 20) { From 96c22aa66719846854895afcb72962862d5a4ffd Mon Sep 17 00:00:00 2001 From: Zane van Iperen Date: Mon, 15 Mar 2021 20:39:32 +1000 Subject: [PATCH 3/9] lib/moviedecoder: remove SilenceLogLevel Was unused. --- libffmpegthumbnailer/moviedecoder.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libffmpegthumbnailer/moviedecoder.cpp b/libffmpegthumbnailer/moviedecoder.cpp index 79c950b..21df096 100644 --- a/libffmpegthumbnailer/moviedecoder.cpp +++ b/libffmpegthumbnailer/moviedecoder.cpp @@ -41,11 +41,6 @@ using namespace std; namespace ffmpegthumbnailer { -struct SilenceLogLevel -{ - SilenceLogLevel() { av_log_set_level(AV_LOG_QUIET); } -}; - MovieDecoder::MovieDecoder(AVFormatContext* pavContext) : m_VideoStream(-1) , m_pFormatContext(pavContext) From 664680f4bfeb89923f485eba270f9e49a8d02bfc Mon Sep 17 00:00:00 2001 From: Zane van Iperen Date: Mon, 15 Mar 2021 17:25:40 +1000 Subject: [PATCH 4/9] lib/moviedecoder: remove registration calls They're not needed anymore. --- libffmpegthumbnailer/moviedecoder.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libffmpegthumbnailer/moviedecoder.cpp b/libffmpegthumbnailer/moviedecoder.cpp index 21df096..ac3e5b9 100644 --- a/libffmpegthumbnailer/moviedecoder.cpp +++ b/libffmpegthumbnailer/moviedecoder.cpp @@ -65,8 +65,6 @@ MovieDecoder::~MovieDecoder() void MovieDecoder::initialize(const string& filename, bool preferEmbeddedMetadata) { - av_register_all(); - avcodec_register_all(); avformat_network_init(); string inputFile = filename == "-" ? "pipe:" : filename; @@ -386,8 +384,6 @@ void MovieDecoder::initializeFilterGraph(const AVRational& timeBase, const std:: auto del = [] (AVBufferSinkParams* p) { av_freep(p); }; std::unique_ptr buffersinkParams(av_buffersink_params_alloc(), del); - avfilter_register_all(); - m_pFilterGraph = avfilter_graph_alloc(); assert(m_pFilterGraph); From 1ae42e664e1f3c915d186ae00aa2c8018b998708 Mon Sep 17 00:00:00 2001 From: Zane van Iperen Date: Mon, 15 Mar 2021 17:30:21 +1000 Subject: [PATCH 5/9] lib/moviedecoder: remove use of AVBufferSinkParams --- libffmpegthumbnailer/moviedecoder.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/libffmpegthumbnailer/moviedecoder.cpp b/libffmpegthumbnailer/moviedecoder.cpp index ac3e5b9..dece668 100644 --- a/libffmpegthumbnailer/moviedecoder.cpp +++ b/libffmpegthumbnailer/moviedecoder.cpp @@ -379,11 +379,6 @@ std::string MovieDecoder::createScaleString(const std::string& sizeString, bool void MovieDecoder::initializeFilterGraph(const AVRational& timeBase, const std::string& size, bool maintainAspectRatio) { - static const AVPixelFormat pixelFormats[] = { AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE }; - - auto del = [] (AVBufferSinkParams* p) { av_freep(p); }; - std::unique_ptr buffersinkParams(av_buffersink_params_alloc(), del); - m_pFilterGraph = avfilter_graph_alloc(); assert(m_pFilterGraph); @@ -395,10 +390,8 @@ void MovieDecoder::initializeFilterGraph(const AVRational& timeBase, const std:: checkRc(avfilter_graph_create_filter(&m_pFilterSource, avfilter_get_by_name("buffer"), "thumb_buffer", ss.str().c_str(), nullptr, m_pFilterGraph), "Failed to create filter source"); - buffersinkParams->pixel_fmts = pixelFormats; - checkRc(avfilter_graph_create_filter(&m_pFilterSink, avfilter_get_by_name("buffersink"), "thumb_buffersink", nullptr, buffersinkParams.get(), m_pFilterGraph), + checkRc(avfilter_graph_create_filter(&m_pFilterSink, avfilter_get_by_name("buffersink"), "thumb_buffersink", nullptr, nullptr, m_pFilterGraph), "Failed to create filter sink"); - buffersinkParams.release(); AVFilterContext* yadifFilter = nullptr; if (m_pFrame->interlaced_frame != 0) From 19675349662a4ea4455d7d13b01cca28ab585762 Mon Sep 17 00:00:00 2001 From: Zane van Iperen Date: Mon, 15 Mar 2021 17:39:58 +1000 Subject: [PATCH 6/9] lib/moviedecoder: use m_pVideoCodecContext instead of AVStream::codec --- libffmpegthumbnailer/moviedecoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libffmpegthumbnailer/moviedecoder.cpp b/libffmpegthumbnailer/moviedecoder.cpp index dece668..0b7a280 100644 --- a/libffmpegthumbnailer/moviedecoder.cpp +++ b/libffmpegthumbnailer/moviedecoder.cpp @@ -484,7 +484,7 @@ void MovieDecoder::seek(int timeInSeconds) } checkRc(av_seek_frame(m_pFormatContext, -1, timestamp, 0), "Seeking in video failed"); - avcodec_flush_buffers(m_pFormatContext->streams[m_VideoStream]->codec); + avcodec_flush_buffers(m_pVideoCodecContext); int keyFrameAttempts = 0; bool gotFrame; From 4f74f83a009fa2b3f3d546adb24d4f1406910007 Mon Sep 17 00:00:00 2001 From: Zane van Iperen Date: Mon, 15 Mar 2021 17:49:03 +1000 Subject: [PATCH 7/9] lib/moviedecoder: codec -> codecpar --- libffmpegthumbnailer/moviedecoder.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libffmpegthumbnailer/moviedecoder.cpp b/libffmpegthumbnailer/moviedecoder.cpp index 0b7a280..e58904e 100644 --- a/libffmpegthumbnailer/moviedecoder.cpp +++ b/libffmpegthumbnailer/moviedecoder.cpp @@ -145,10 +145,10 @@ int32_t MovieDecoder::findPreferedVideoStream(bool preferEmbeddedMetadata) for (unsigned int i = 0; i < m_pFormatContext->nb_streams; ++i) { AVStream *stream = m_pFormatContext->streams[i]; - auto ctx = m_pFormatContext->streams[i]->codec; - if (ctx->codec_type == AVMEDIA_TYPE_VIDEO) + auto par = m_pFormatContext->streams[i]->codecpar; + if (par->codec_type == AVMEDIA_TYPE_VIDEO) { - if (!preferEmbeddedMetadata || !isStillImageCodec(ctx->codec_id)) + if (!preferEmbeddedMetadata || !isStillImageCodec(par->codec_id)) { videoStreams.push_back(i); continue; From 3ffdd65cbda6ef21d36c96013db1b0f4dc9fc57b Mon Sep 17 00:00:00 2001 From: Zane van Iperen Date: Mon, 15 Mar 2021 17:52:01 +1000 Subject: [PATCH 8/9] lib/movedecoder: don't rely on avformat to allocate a context --- libffmpegthumbnailer/moviedecoder.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libffmpegthumbnailer/moviedecoder.cpp b/libffmpegthumbnailer/moviedecoder.cpp index e58904e..da5f32a 100644 --- a/libffmpegthumbnailer/moviedecoder.cpp +++ b/libffmpegthumbnailer/moviedecoder.cpp @@ -90,8 +90,7 @@ void MovieDecoder::destroy() { if (m_pVideoCodecContext) { - avcodec_close(m_pVideoCodecContext); - m_pVideoCodecContext = nullptr; + avcodec_free_context(&m_pVideoCodecContext); } if ((!m_FormatContextWasGiven) && m_pFormatContext) @@ -196,8 +195,7 @@ void MovieDecoder::initializeVideo(bool preferEmbeddedMetadata) } m_pVideoStream = m_pFormatContext->streams[m_VideoStream]; - m_pVideoCodecContext = m_pVideoStream->codec; - m_pVideoCodec = avcodec_find_decoder(m_pVideoCodecContext->codec_id); + m_pVideoCodec = avcodec_find_decoder(m_pVideoStream->codecpar->codec_id); if (m_pVideoCodec == nullptr) { @@ -207,6 +205,20 @@ void MovieDecoder::initializeVideo(bool preferEmbeddedMetadata) throw logic_error("Video Codec not found"); } + m_pVideoCodecContext = avcodec_alloc_context3(m_pVideoCodec); + + if (m_pVideoCodecContext == nullptr) + { + destroy(); + throw logic_error("Could not allocate video codec context"); + } + + if (avcodec_parameters_to_context(m_pVideoCodecContext, m_pVideoStream->codecpar) < 0) + { + destroy(); + throw logic_error("Could not configure video codec context"); + } + m_pVideoCodecContext->workaround_bugs = 1; if (avcodec_open2(m_pVideoCodecContext, m_pVideoCodec, nullptr) < 0) From f9273852c8e3d7af77d6c8929b1ac6c8a26eca50 Mon Sep 17 00:00:00 2001 From: Zane van Iperen Date: Mon, 15 Mar 2021 20:57:45 +1000 Subject: [PATCH 9/9] lib/moviedecoder: replace avcodec_decode_video2() usage --- libffmpegthumbnailer/moviedecoder.cpp | 31 +++++++++++++++++++++------ 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/libffmpegthumbnailer/moviedecoder.cpp b/libffmpegthumbnailer/moviedecoder.cpp index da5f32a..f32577a 100644 --- a/libffmpegthumbnailer/moviedecoder.cpp +++ b/libffmpegthumbnailer/moviedecoder.cpp @@ -548,17 +548,33 @@ bool MovieDecoder::decodeVideoPacket() return false; } - av_frame_unref(m_pFrame); - - int frameFinished; + int rc = avcodec_send_packet(m_pVideoCodecContext, m_pPacket); + if(rc == AVERROR(EAGAIN)) + { + rc = 0; + } - int bytesDecoded = avcodec_decode_video2(m_pVideoCodecContext, m_pFrame, &frameFinished, m_pPacket); - if (bytesDecoded < 0) + if(rc == AVERROR_EOF) + { + return false; + } + else if(rc < 0) { - throw logic_error("Failed to decode video frame: bytesDecoded < 0"); + throw logic_error("Failed to decode video frame: avcodec_send_packet() < 0"); } - return frameFinished > 0; + rc = avcodec_receive_frame(m_pVideoCodecContext, m_pFrame); + switch(rc) + { + case 0: + return true; + + case AVERROR(EAGAIN): + return false; + + default: + throw logic_error("Failed to decode video frame: avcodec_receive_frame() < 0"); + } } bool MovieDecoder::getVideoPacket() @@ -574,6 +590,7 @@ bool MovieDecoder::getVideoPacket() m_pPacket = new AVPacket(); + while (framesAvailable && !frameDecoded) { framesAvailable = av_read_frame(m_pFormatContext, m_pPacket) >= 0;