Fix T93328: Movie seeking doesn't work.
Caused by integer overflow in `steps_per_frame` calculation.
This commit is contained in:
parent
da848b7440
commit
f2b24272dd
Notes:
blender-bot
2023-02-14 09:38:57 +01:00
Referenced by issue #95606, Crash on clicking in viewport with active GN workspace Referenced by issue #95611, Regression: Capture Attribute in Face Corner mode produces garbage data Referenced by issue #95278, 3.1 does not launch Referenced by issue #95093, VSE: Variable framerate videos cause proxies to mismatch Referenced by issue #93328, Blender VSE preview showing different result than Render
|
@ -993,21 +993,23 @@ static int ffmpeg_seek_by_byte(AVFormatContext *pFormatCtx)
|
|||
return false;
|
||||
}
|
||||
|
||||
static int64_t ffmpeg_get_seek_pts(struct anim *anim, int64_t pts_to_search)
|
||||
static double ffmpeg_steps_per_frame_get(struct anim *anim)
|
||||
{
|
||||
AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
|
||||
AVRational frame_rate = v_st->r_frame_rate;
|
||||
AVRational time_base = v_st->time_base;
|
||||
double steps_per_frame = (double)(frame_rate.den * time_base.den) /
|
||||
(double)(frame_rate.num * time_base.num);
|
||||
AVRational frame_rate = av_guess_frame_rate(anim->pFormatCtx, v_st, NULL);
|
||||
return av_q2d(av_inv_q(av_mul_q(frame_rate, time_base)));
|
||||
;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
int64_t pts = pts_to_search - (steps_per_frame / 2);
|
||||
|
||||
return pts;
|
||||
return pts_to_search - (ffmpeg_steps_per_frame_get(anim) / 2);
|
||||
}
|
||||
|
||||
/* This gives us an estimate of which pts our requested frame will have.
|
||||
|
@ -1026,13 +1028,8 @@ static int64_t ffmpeg_get_pts_to_search(struct anim *anim,
|
|||
else {
|
||||
AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
|
||||
int64_t start_pts = v_st->start_time;
|
||||
AVRational frame_rate = v_st->r_frame_rate;
|
||||
AVRational time_base = v_st->time_base;
|
||||
|
||||
double steps_per_frame = (double)(frame_rate.den * time_base.den) /
|
||||
(double)(frame_rate.num * time_base.num);
|
||||
|
||||
pts_to_search = round(position * steps_per_frame);
|
||||
pts_to_search = round(position * ffmpeg_steps_per_frame_get(anim));
|
||||
|
||||
if (start_pts != AV_NOPTS_VALUE) {
|
||||
pts_to_search += start_pts;
|
||||
|
@ -1122,13 +1119,6 @@ static int ffmpeg_generic_seek_workaround(struct anim *anim,
|
|||
int64_t *requested_pts,
|
||||
int64_t pts_to_search)
|
||||
{
|
||||
AVStream *v_st = anim->pFormatCtx->streams[anim->videoStream];
|
||||
AVRational frame_rate = v_st->r_frame_rate;
|
||||
AVRational time_base = v_st->time_base;
|
||||
|
||||
double steps_per_frame = (double)(frame_rate.den * time_base.den) /
|
||||
(double)(frame_rate.num * time_base.num);
|
||||
|
||||
int64_t current_pts = *requested_pts;
|
||||
int64_t offset = 0;
|
||||
|
||||
|
@ -1136,7 +1126,7 @@ static int ffmpeg_generic_seek_workaround(struct anim *anim,
|
|||
|
||||
/* Step backward frame by frame until we find the key frame we are looking for. */
|
||||
while (current_pts != 0) {
|
||||
current_pts = *requested_pts - (int64_t)round(offset * steps_per_frame);
|
||||
current_pts = *requested_pts - (int64_t)round(offset * ffmpeg_steps_per_frame_get(anim));
|
||||
current_pts = MAX2(current_pts, 0);
|
||||
|
||||
/* Seek to timestamp. */
|
||||
|
|
Loading…
Reference in New Issue