diff options
author | Richard Antalik <richardantalik@gmail.com> | 2022-01-28 01:15:03 +0300 |
---|---|---|
committer | Fabian Schempp <fabianschempp@googlemail.com> | 2022-04-11 01:28:41 +0300 |
commit | 9a30868ffc1f6d3bea7f35ae9b50e08e1cf00dfd (patch) | |
tree | 58446292a105ee1a29d2f1091fa8659dfa5ea156 /source/blender/imbuf/intern/anim_movie.c | |
parent | bbe43f593dfe0883ddbddf6747fc75476f7527d9 (diff) |
Fix T93328: Movie seeking doesn't work.
Caused by integer overflow in `steps_per_frame` calculation.
Diffstat (limited to 'source/blender/imbuf/intern/anim_movie.c')
-rw-r--r-- | source/blender/imbuf/intern/anim_movie.c | 32 |
1 files changed, 11 insertions, 21 deletions
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 17e82fc79c9..38dbb9bfc47 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -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. */ |