Forward-port avcodec_decode_audio4 error handling patch from v1.
authorCarl Hetherington <cth@carlh.net>
Sun, 2 Nov 2014 23:03:41 +0000 (23:03 +0000)
committerCarl Hetherington <cth@carlh.net>
Mon, 3 Nov 2014 09:48:33 +0000 (09:48 +0000)
ChangeLog
src/lib/ffmpeg_decoder.cc

index 07519688ea730b17ab7e23dc878cad973cb86da3..ff2b607e9dd2b0b90c993226a34dbcbe4dd21baa 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
 2014-10-30  Carl Hetherington  <cth@carlh.net>
 
        * Version 2.0.19 released.
 2014-10-26  Carl Hetherington  <cth@carlh.net>
 
        * Version 2.0.17 released.
+=======
+2014-11-02  Carl Hetherington  <cth@carlh.net>
+
+       * Be more tolerant of some FFmpeg audio decoding errors;
+       should fix #352.
+>>>>>>> fc8fb8f... Process decoded audio even if avcodec_decode_audio4 returns an error, as there are cases where it produces good data and then returns an error.
 
 2014-10-26  Carl Hetherington  <cth@carlh.net>
 
index 15443c346b3d302cce263165588044e641879160..d1b65cbc2846b56014f8dbc6a1bd108ab9408501 100644 (file)
@@ -50,7 +50,8 @@ extern "C" {
 
 #define LOG_GENERAL(...) _video_content->film()->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
 #define LOG_ERROR(...) _video_content->film()->log()->log (String::compose (__VA_ARGS__), Log::TYPE_ERROR);
-#define LOG_WARNING(...) _video_content->film()->log()->log (__VA_ARGS__, Log::TYPE_WARNING);
+#define LOG_WARNING_NC(...) _video_content->film()->log()->log (__VA_ARGS__, Log::TYPE_WARNING);
+#define LOG_WARNING(...) _video_content->film()->log()->log (String::compose (__VA_ARGS__), Log::TYPE_WARNING);
 
 using std::cout;
 using std::string;
@@ -331,11 +332,24 @@ FFmpegDecoder::decode_audio_packet ()
        while (copy_packet.size > 0) {
 
                int frame_finished;
-               int const decode_result = avcodec_decode_audio4 (audio_codec_context(), _frame, &frame_finished, &copy_packet);
-
+               int decode_result = avcodec_decode_audio4 (audio_codec_context(), _frame, &frame_finished, &copy_packet);
                if (decode_result < 0) {
-                       LOG_ERROR ("avcodec_decode_audio4 failed (%1)", decode_result);
-                       return;
+                       /* avcodec_decode_audio4 can sometimes return an error even though it has decoded
+                          some valid data; for example dca_subframe_footer can return AVERROR_INVALIDDATA
+                          if it overreads the auxiliary data.  ffplay carries on if frame_finished is true,
+                          even in the face of such an error, so I think we should too.
+
+                          Returning from the method here caused mantis #352.
+                       */
+                       
+                       shared_ptr<const Film> film = _film.lock ();
+                       assert (film);
+                       LOG_WARNING ("avcodec_decode_audio4 failed (%1)", decode_result);
+
+                       /* Fudge decode_result so that we come out of the while loop when
+                          we've processed this data.
+                       */
+                       decode_result = copy_packet.size;
                }
 
                if (frame_finished) {
@@ -394,7 +408,7 @@ FFmpegDecoder::decode_video_packet ()
                                rint (pts * _ffmpeg_content->video_frame_rate ())
                                );
                } else {
-                       LOG_WARNING ("Dropping frame without PTS");
+                       LOG_WARNING_NC ("Dropping frame without PTS");
                }
        }