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
This commit is contained in:
parent
fba35aa8c5
commit
71f2229b0d
Notes:
blender-bot
2023-02-14 09:17:57 +01:00
Referenced by issue #71052, Eyedropper for props does not work in dialog boxes Referenced by issue #70080, Newly created objects not visible when using local collections Referenced by issue #68091, Adding a corrupt video crashes/confuses Blender
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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'),
|
||||
|
|
Loading…
Reference in New Issue