diff options
-rw-r--r-- | source/blender/imbuf/intern/anim_movie.c | 18 | ||||
-rwxr-xr-x | tests/python/ffmpeg_tests.py | 9 |
2 files changed, 26 insertions, 1 deletions
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 5bfcca22fae..a5fa55479dd 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -570,10 +570,26 @@ static int startffmpeg(struct anim *anim) } frame_rate = av_guess_frame_rate(pFormatCtx, video_stream, NULL); + anim->duration = 0; + + /* Take from the stream if we can. */ if (video_stream->nb_frames != 0) { anim->duration = video_stream->nb_frames; + + /* Sanity check on the detected duration. This is to work around corruption like reported in + * T68091. */ + if (frame_rate.den != 0 && pFormatCtx->duration > 0) { + double stream_sec = anim->duration * av_q2d(frame_rate); + double container_sec = pFormatCtx->duration / (double)AV_TIME_BASE; + if (stream_sec > 4.0 * container_sec) { + /* The stream is significantly longer than the container duration, which is + * suspicious. */ + anim->duration = 0; + } + } } - else { + /* Fall back to the container. */ + if (anim->duration == 0) { anim->duration = (int)(pFormatCtx->duration * av_q2d(frame_rate) / AV_TIME_BASE + 0.5f); } diff --git a/tests/python/ffmpeg_tests.py b/tests/python/ffmpeg_tests.py index d6e7127c35a..92734b5bc7d 100755 --- a/tests/python/ffmpeg_tests.py +++ b/tests/python/ffmpeg_tests.py @@ -86,6 +86,15 @@ class FPSDetectionTest(AbstractFFmpegSequencerTest): 1.0, places=2) + def test_T68091(self): + self.assertAlmostEqual( + self.get_movie_file_fps('T68091-invalid-nb_frames-at-10fps.mp4'), + 10.0, + places=2) + self.assertEqual( + self.get_movie_file_duration('T68091-invalid-nb_frames-at-10fps.mp4'), + 10) + def test_T54834(self): self.assertEqual( self.get_movie_file_duration('T54834.ogg'), |