From 1ccd2f6243b3d9336fb361018d83cbf9ce0ae1b9 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sun, 11 Jan 2026 16:48:32 +0530 Subject: [PATCH] avcodec/bsf/setts: rescale TS when changing TB The setts bsf has an option to change TB. However the filter only changed the TB and did not rescale the ts and duration, so it effectively and silently stretched or squeezed the stream. The pts, dts and duration are now rescaled to maintain temporal fidelity. --- libavcodec/bsf/setts.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libavcodec/bsf/setts.c b/libavcodec/bsf/setts.c index 9c27b24a39..ab206598c5 100644 --- a/libavcodec/bsf/setts.c +++ b/libavcodec/bsf/setts.c @@ -88,6 +88,7 @@ typedef struct SetTSContext { char *duration_str; AVRational time_base; + int user_outtb; int64_t frame_number; @@ -142,8 +143,13 @@ static int setts_init(AVBSFContext *ctx) } } - if (s->time_base.num > 0 && s->time_base.den > 0) + if (s->time_base.num > 0 && s->time_base.den > 0) { ctx->time_base_out = s->time_base; + s->user_outtb = 1; + } else if (s->time_base.num || !s->time_base.den) { + av_log(ctx, AV_LOG_ERROR, "Invalid value %d/%d specified for output timebase\n", s->time_base.num, s->time_base.den); + return AVERROR_INVALIDDATA; + } s->frame_number= 0; s->var_values[VAR_STARTPTS] = AV_NOPTS_VALUE; @@ -219,6 +225,12 @@ static int setts_filter(AVBSFContext *ctx, AVPacket *pkt) if (ret < 0) return ret; + if (s->user_outtb) { + new_pts = av_rescale_q(new_pts, ctx->time_base_in, ctx->time_base_out); + new_dts = av_rescale_q(new_dts, ctx->time_base_in, ctx->time_base_out); + new_duration = av_rescale_q(new_duration, ctx->time_base_in, ctx->time_base_out); + } + pkt->pts = new_pts; pkt->dts = new_dts; pkt->duration = new_duration;