Fix errors when seeking FFmpeg for some formats.
authorCarl Hetherington <cth@carlh.net>
Thu, 3 Jun 2021 20:55:44 +0000 (22:55 +0200)
committerCarl Hetherington <cth@carlh.net>
Fri, 4 Jun 2021 20:31:07 +0000 (22:31 +0200)
The comments discuss this in a bit more depth, but basically we see
errors from avcodec_send_packet after seek.  ffplay etc. seem basically
to ignore all errors from avcodec_send_packet, and I can't find a
"proper" fix, so here's a half-way house hack: ignore some errors
after seek.  Nasty.

src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
test/ffmpeg_decoder_seek_test.cc

index c5c41fdac86b09608fc09cf4be32c7af4b5cec20..31fbde773b3ab86df610edb9eb801141a48e9a11 100644 (file)
@@ -427,6 +427,12 @@ FFmpegDecoder::seek (ContentTime time, bool accurate)
        for (auto& i: _next_time) {
                i.second = boost::optional<dcpomatic::ContentTime>();
        }
        for (auto& i: _next_time) {
                i.second = boost::optional<dcpomatic::ContentTime>();
        }
+
+       /* 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;
 }
 
 
 }
 
 
@@ -513,6 +519,12 @@ FFmpegDecoder::decode_and_process_audio_packet (AVPacket* packet)
                /* 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.
                 */
                /* 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);
        }
 
                throw DecodeError (N_("avcodec_send_packet"), N_("FFmpegDecoder::decode_and_process_audio_packet"), r);
        }
 
index fce3fcae92230da92b955000e8ffdfe4b9498c89..def824feb042d73f78282bf0466fafe67a86b9e7 100644 (file)
@@ -79,6 +79,9 @@ private:
        /** true if we have a subtitle which has not had emit_stop called for it yet */
        bool _have_current_subtitle = false;
 
        /** true if we have a subtitle which has not had emit_stop called for it yet */
        bool _have_current_subtitle = false;
 
+       /** number of errors from avcodec_send_packet to ignore */
+       int _errors_to_ignore = 0;
+
        std::shared_ptr<Image> _black_image;
 
        std::map<std::shared_ptr<FFmpegAudioStream>, boost::optional<dcpomatic::ContentTime>> _next_time;
        std::shared_ptr<Image> _black_image;
 
        std::map<std::shared_ptr<FFmpegAudioStream>, boost::optional<dcpomatic::ContentTime>> _next_time;
index f8ce256cf4f97b8ae6fcbd7e6367c1beda89bfb4..4dceae86ba6f6416e7add63be7c0093265fad6e8 100644 (file)
@@ -100,4 +100,5 @@ BOOST_AUTO_TEST_CASE (ffmpeg_decoder_seek_test)
        test ("boon_telly.mkv", frames);
        test ("Sintel_Trailer1.480p.DivX_Plus_HD.mkv", frames);
        test ("prophet_long_clip.mkv", { 15, 42, 999, 15 });
        test ("boon_telly.mkv", frames);
        test ("Sintel_Trailer1.480p.DivX_Plus_HD.mkv", frames);
        test ("prophet_long_clip.mkv", { 15, 42, 999, 15 });
+       test ("dolby_aurora.vob", { 0, 125, 250, 41 });
 }
 }