X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fffmpeg_examiner.cc;h=fdcacb465602693fba0bf668cc82d7bd9b82ddd6;hb=d3ecb8495a42d039b07313e393734c49fdc6be66;hp=853db90be3e3ef1ec36cc834a51f0ff6754468e9;hpb=4e2ff7851127cd85c3e7d78b42eb884d0cda0ac3;p=dcpomatic.git diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc index 853db90be..fdcacb465 100644 --- a/src/lib/ffmpeg_examiner.cc +++ b/src/lib/ffmpeg_examiner.cc @@ -26,8 +26,8 @@ #include "ffmpeg_audio_stream.h" #include "ffmpeg_subtitle_stream.h" #include "util.h" -#include "warnings.h" -DCPOMATIC_DISABLE_WARNINGS +#include +LIBDCP_DISABLE_WARNINGS extern "C" { #include #include @@ -37,7 +37,7 @@ extern "C" { #include #include } -DCPOMATIC_ENABLE_WARNINGS +LIBDCP_ENABLE_WARNINGS #include #include "i18n.h" @@ -221,34 +221,38 @@ FFmpegExaminer::video_packet (AVCodecContext* context, string& temporal_referenc return false; } - int r = avcodec_send_packet (context, packet); - if (r < 0 && !(r == AVERROR_EOF && !packet)) { - /* We could cope with AVERROR(EAGAIN) and re-send the packet but I think it should never happen. - * AVERROR_EOF can happen during flush if we've already sent a flush packet. - */ - throw DecodeError (N_("avcodec_send_packet"), N_("FFmpegExaminer::video_packet"), r); - } + bool pending = false; + do { + int r = avcodec_send_packet (context, packet); + if (r < 0) { + LOG_WARNING("avcodec_send_packet returned %1 for a video packet", r); + } - r = avcodec_receive_frame (context, _frame); - if (r == AVERROR(EAGAIN)) { - /* More input is required */ - return true; - } else if (r == AVERROR_EOF) { - /* No more output is coming */ - return false; - } + /* EAGAIN means we should call avcodec_receive_frame and then re-send the same packet */ + pending = r == AVERROR(EAGAIN); + + r = avcodec_receive_frame (context, _video_frame); + if (r == AVERROR(EAGAIN)) { + /* More input is required */ + return true; + } else if (r == AVERROR_EOF) { + /* No more output is coming */ + return false; + } + } while (pending); if (!_first_video) { - _first_video = frame_time (_format_context->streams[_video_stream.get()]); + _first_video = frame_time (_video_frame, _format_context->streams[_video_stream.get()]); } if (_need_video_length) { _video_length = frame_time ( + _video_frame, _format_context->streams[_video_stream.get()] ).get_value_or (ContentTime ()).frames_round (video_frame_rate().get ()); } if (temporal_reference.size() < (PULLDOWN_CHECK_FRAMES * 2)) { - temporal_reference += (_frame->top_field_first ? "T" : "B"); - temporal_reference += (_frame->repeat_pict ? "3" : "2"); + temporal_reference += (_video_frame->top_field_first ? "T" : "B"); + temporal_reference += (_video_frame->repeat_pict ? "3" : "2"); } return true; @@ -263,30 +267,29 @@ FFmpegExaminer::audio_packet (AVCodecContext* context, shared_ptrfirst_audio = frame_time (stream->stream(_format_context)); + stream->first_audio = frame_time (frame, stream->stream(_format_context)); } optional -FFmpegExaminer::frame_time (AVStream* s) const +FFmpegExaminer::frame_time (AVFrame* frame, AVStream* stream) const { optional t; - int64_t const bet = _frame->best_effort_timestamp; + int64_t const bet = frame->best_effort_timestamp; if (bet != AV_NOPTS_VALUE) { - t = ContentTime::from_seconds (bet * av_q2d (s->time_base)); + t = ContentTime::from_seconds (bet * av_q2d(stream->time_base)); } return t; @@ -480,3 +483,13 @@ FFmpegExaminer::range () const return VideoRange::FULL; } } + + +PixelQuanta +FFmpegExaminer::pixel_quanta () const +{ + auto const desc = av_pix_fmt_desc_get(video_codec_context()->pix_fmt); + DCPOMATIC_ASSERT (desc); + return { 1 << desc->log2_chroma_w, 1 << desc->log2_chroma_h }; +} +