Fix T95683: FFmpeg seeking is broken

According to information I gathered, ffmpeg seeks internally using DTS
values instead of PTS. In some files DTS and PTS values are offset and
ffmpeg fails to seek correctly to keyframe located before requested PTS.

This issue become evident after hardcoded preseek of 25 frames was
removed and effort went into more precise seeking to improve
performance. It was thought, that this is bug in ffmpeg code, but
after reading some discussions, I don't think it is considered as such
by their developers, see below:
http://ffmpeg.org/pipermail/ffmpeg-devel/2018-March/226354.html
https://trac.ffmpeg.org/ticket/1189

Best solution seems to be to add small preseek value possibly at
detriment of performance, so 3 frames of preseek are applied. Number 3
was chosen experimentally.

Performance impact seems to be insignificant with this change.

Reviewed By: zeddb

Differential Revision: https://developer.blender.org/D15847
This commit is contained in:
Richard Antalik 2022-10-12 20:00:20 +02:00
parent a1bc05b200
commit bcc56253e2
Notes: blender-bot 2023-02-14 01:35:49 +01:00
Referenced by commit a67876103a, Fix T101981: Incorrect playback of AVI files
Referenced by issue #100749, Blender LTS: Maintenance Task 3.3
Referenced by issue #101981, The video sequencer does not correctly decode an AVI file
Referenced by issue #95683, FFmpeg seeking is broken
1 changed files with 7 additions and 5 deletions

View File

@ -1093,12 +1093,14 @@ static int ffmpeg_seek_by_byte(AVFormatContext *pFormatCtx)
static int64_t ffmpeg_get_seek_pts(struct anim *anim, int64_t pts_to_search)
{
/* Step back half a frame position to make sure that we get the requested
* frame and not the one after it. This is a workaround as ffmpeg will
* sometimes not seek to a frame after the requested pts even if
* AVSEEK_FLAG_BACKWARD is specified.
/* FFmpeg seeks internally using DTS values instead of PTS. In some files DTS and PTS values are
* offset and sometimes ffmpeg fails to take this into account when seeking.
* Therefore we need to seek backwards a certain offset to make sure the frame we want is in
* front of us. It is not possible to determine the exact needed offset, this value is determined
* experimentally. Note: Too big offset can impact performance. Current 3 frame offset has no
* measurable impact.
*/
return pts_to_search - (ffmpeg_steps_per_frame_get(anim) / 2);
return pts_to_search - (ffmpeg_steps_per_frame_get(anim) * 3);
}
/* This gives us an estimate of which pts our requested frame will have.