X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Flib%2Fffmpeg_decoder.cc;h=f64ccbd3b6305249c4522ee69d175dee6bb26849;hp=2baa99876b173adbf58e52d4774f80c5a2c393cd;hb=84039db657c3cc72719706a136c90741170c765a;hpb=952084c4221c5708e02c783284cf0f7239c6b4c4 diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 2baa99876..f64ccbd3b 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -122,7 +122,7 @@ FFmpegDecoder::flush () /* EOF can happen if we've already sent a flush packet */ throw DecodeError (N_("avcodec_send_packet"), N_("FFmpegDecoder::flush"), r); } - r = avcodec_receive_frame (context, _frame); + r = avcodec_receive_frame (context, audio_frame(i)); if (r >= 0) { process_audio_frame (i); did_something = true; @@ -423,12 +423,6 @@ FFmpegDecoder::seek (ContentTime time, bool accurate) for (auto& i: _next_time) { i.second = boost::optional(); } - - /* We find that we get some errors from av_send_packet after a seek. Perhaps we should ignore - * all of them (which seems risky), or perhaps we should have some proper fix. But instead - * let's ignore the next 2 errors. - */ - _errors_to_ignore = 2; } @@ -453,10 +447,11 @@ FFmpegDecoder::audio_stream_from_index (int index) const void FFmpegDecoder::process_audio_frame (shared_ptr stream) { - auto data = deinterleave_audio (_frame); + auto frame = audio_frame (stream); + auto data = deinterleave_audio (frame); ContentTime ct; - if (_frame->pts == AV_NOPTS_VALUE) { + if (frame->pts == AV_NOPTS_VALUE) { /* In some streams we see not every frame coming through with a timestamp; for those that have AV_NOPTS_VALUE we need to work out the timestamp ourselves. This is particularly noticeable with TrueHD streams (see #1111). @@ -466,7 +461,7 @@ FFmpegDecoder::process_audio_frame (shared_ptr stream) } } else { ct = ContentTime::from_seconds ( - _frame->best_effort_timestamp * + frame->best_effort_timestamp * av_q2d (stream->stream(_format_context)->time_base)) + _pts_offset; } @@ -487,7 +482,7 @@ FFmpegDecoder::process_audio_frame (shared_ptr stream) to_string(ct), data->frames(), stream->id(), - _frame->best_effort_timestamp, + frame->best_effort_timestamp, av_q2d(stream->stream(_format_context)->time_base), to_string(_pts_offset) ); @@ -509,23 +504,14 @@ FFmpegDecoder::decode_and_process_audio_packet (AVPacket* packet) } auto context = _codec_context[stream->index(_format_context)]; + auto frame = audio_frame (stream); int r = avcodec_send_packet (context, packet); if (r < 0) { - /* We could cope with AVERROR(EAGAIN) and re-send the packet but I think it should never happen. - * Likewise I think AVERROR_EOF should not happen. - */ - if (_errors_to_ignore > 0) { - /* We see errors here after a seek, which is hopefully to be nothing to worry about */ - --_errors_to_ignore; - LOG_GENERAL("Ignoring error %1 avcodec_send_packet after seek; will ignore %2 more", r, _errors_to_ignore); - return; - } - throw DecodeError (N_("avcodec_send_packet"), N_("FFmpegDecoder::decode_and_process_audio_packet"), r); + LOG_WARNING("avcodec_send_packet returned %1 for an audio packet", r); } - while (r >= 0) { - r = avcodec_receive_frame (context, _frame); + r = avcodec_receive_frame (context, frame); if (r == AVERROR(EAGAIN)) { /* More input is required */ return; @@ -548,14 +534,11 @@ FFmpegDecoder::decode_and_process_video_packet (AVPacket* packet) auto context = video_codec_context(); 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_("FFmpegDecoder::decode_and_process_video_packet"), r); + if (r < 0) { + LOG_WARNING("avcodec_send_packet returned %1 for a video packet", r); } - r = avcodec_receive_frame (context, _frame); + r = avcodec_receive_frame (context, _video_frame); if (r == AVERROR(EAGAIN) || r == AVERROR_EOF || (r < 0 && !packet)) { /* More input is required, no more frames are coming, or we are flushing and there was * some error which we just want to ignore. @@ -565,6 +548,15 @@ FFmpegDecoder::decode_and_process_video_packet (AVPacket* packet) throw DecodeError (N_("avcodec_receive_frame"), N_("FFmpeg::decode_and_process_video_packet"), r); } + process_video_frame (); + + return true; +} + + +void +FFmpegDecoder::process_video_frame () +{ /* We assume we'll only get one frame here, which I think is safe */ boost::mutex::scoped_lock lm (_filter_graphs_mutex); @@ -572,21 +564,21 @@ FFmpegDecoder::decode_and_process_video_packet (AVPacket* packet) shared_ptr graph; auto i = _filter_graphs.begin(); - while (i != _filter_graphs.end() && !(*i)->can_process (dcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)) { + while (i != _filter_graphs.end() && !(*i)->can_process(dcp::Size(_video_frame->width, _video_frame->height), (AVPixelFormat) _video_frame->format)) { ++i; } if (i == _filter_graphs.end ()) { dcp::Fraction vfr (lrint(_ffmpeg_content->video_frame_rate().get() * 1000), 1000); - graph = make_shared(dcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format, vfr); + graph = make_shared(dcp::Size(_video_frame->width, _video_frame->height), (AVPixelFormat) _video_frame->format, vfr); graph->setup (_ffmpeg_content->filters ()); _filter_graphs.push_back (graph); - LOG_GENERAL (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format); + LOG_GENERAL (N_("New graph for %1x%2, pixel format %3"), _video_frame->width, _video_frame->height, _video_frame->format); } else { graph = *i; } - auto images = graph->process (_frame); + auto images = graph->process (_video_frame); for (auto const& i: images) { @@ -604,8 +596,6 @@ FFmpegDecoder::decode_and_process_video_packet (AVPacket* packet) LOG_WARNING_NC ("Dropping frame without PTS"); } } - - return true; }