[Bf-blender-cvs] [71f2229b0d8] master: Fix T68091: Adding a corrupt video crashes/confuses Blender

Sybren A. Stüvel noreply at git.blender.org
Thu Sep 19 15:13:18 CEST 2019


Commit: 71f2229b0d8241ba153abebcc1e0d0e92e877574
Author: Sybren A. Stüvel
Date:   Thu Sep 19 13:55:44 2019 +0200
Branches: master
https://developer.blender.org/rB71f2229b0d8241ba153abebcc1e0d0e92e877574

Fix T68091: Adding a corrupt video crashes/confuses Blender

The problematic video from T68091 clearly has an invalid stream duration
(it would be 55 centuries long if interpreted at 30 FPS, and given that
it was recorded with an Android 9 device, it's unlikely that recording
started that long ago). I've added a heuristic to check the stream
duration against the container duration; if the stream is more than 4x
longer than the container, Blender now falls back to the container
duration.

We could use MIN(stream duration, container duration), but there might
be video files out there where the container duration is less precise
than the stream duration; they are measured in different units of time
(microseconds for the container vs. frames for the stream).

Includes a unit test for the above heuristic.

Reviewed by: jbakker

Differential revision: https://developer.blender.org/D5853

===================================================================

M	source/blender/imbuf/intern/anim_movie.c
M	tests/python/ffmpeg_tests.py

===================================================================

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'),



More information about the Bf-blender-cvs mailing list