Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Antalik <richardantalik@gmail.com>2022-01-28 01:15:03 +0300
committerRichard Antalik <richardantalik@gmail.com>2022-01-28 01:21:45 +0300
commitf2b24272dd7c8dd0ed13604b082247fda970e069 (patch)
tree73eb271e14ed6d6321481bbb4ac16b94061a3884
parentda848b7440ab8878b350f764dfbf70729e43021d (diff)
Fix T93328: Movie seeking doesn't work.
Caused by integer overflow in `steps_per_frame` calculation.
-rw-r--r--source/blender/imbuf/intern/anim_movie.c32
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. */