From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 0E0324E051 for ; Sun, 11 Jan 2026 13:25:00 +0000 (UTC) Authentication-Results: ffbox; dkim=fail (body hash mismatch (got b'YxDbaCuwqCUrh88Lhk1zu/cHKAhmDdoSxa5QKM0qd30=', expected b'5NA6TdAQW/1T20f0uaxL2Kyc8H7PnFXiVS5Yal0l45I=')) header.d=ffmpeg.org header.i=@ffmpeg.org header.a=rsa-sha256 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1768137876; h=mime-version : to : date : message-id : reply-to : subject : list-id : list-archive : list-archive : list-help : list-owner : list-post : list-subscribe : list-unsubscribe : from : cc : content-type : content-transfer-encoding : from; bh=YxDbaCuwqCUrh88Lhk1zu/cHKAhmDdoSxa5QKM0qd30=; b=LZ5nueMGhH39VAXOqG8drJ6RDXRZu1qFaisikWUbWKZKTWZqt9gWOY852/ILkF92oenzr 0X/OlZBwj3lHewvPNyHE0hW2TpOx7kq+lfYusniAE64LWuYEJzUZUtFsXMANIX4ImMhs8h8 B588fbOmkET2Z1RtvShnXQVKQIMIz7xfzFJEFHFbBDSLzkch6rRPPPHZcUUDNJ6jvYRNyPm 9UjE0paEpaxUcGX908FcsJc0c3cfbcCUYFFtCUrw9waegC8TsUqHhV7klshSi1VzqdTZ58G kfAzv1JdyJUmEer6IDrL7eWDAVByzs6jnmo7fW9myLtjxozBbmIB48/g+E/w== Received: from [172.20.0.4] (unknown [172.20.0.4]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id 8E842690E21; Sun, 11 Jan 2026 15:24:36 +0200 (EET) ARC-Seal: i=1; cv=none; a=rsa-sha256; d=ffmpeg.org; s=arc; t=1768137859; b=Ypm8DycjlDU06kozMNQqEhvvJeduX/UAMvjN4jUAvrE9KxzepFt6pgnEUaMXMwyVHRSWH RGFCkaZhj+vtdLNB7uAT4ChW+rVRAOA2gYqiJzT83bQjf4ABZSDkXAXFg7BmoQVyvPlmkIo 1xWpAUJuvsmYK4xJDCW3BA7hn7ZMKh9H4IodZe9GmccopPipTKo7efUjR2wR2rwsgc+0nJF gcl1iHxjuKgWM9JVlu8+gjI+25RG5zmtZ4t9ZUiKHn6rze2w8K9HHPSo77jG7TcpUlkJCmp XtUfvSjX4sxMnzbxvyga/l5+LYmNJDyY3E9d+gXfNwONS0ykUBzRNLovQ6iw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=ffmpeg.org; s=arc; t=1768137859; h=from : sender : reply-to : subject : date : message-id : to : cc : mime-version : content-type : content-transfer-encoding : content-id : content-description : resent-date : resent-from : resent-sender : resent-to : resent-cc : resent-message-id : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; bh=fxa32QnR3g+mUqEqNLzw1k7VxwwQpXC237zbksdXQrk=; b=grI8RDiirAkX1STzG3hsOdDQarK7WtiveivJlUPt3qJy+j0lt0dTBgH7ouuk9G2B4PALO egDKUt/TPN8PYVIs2UHnjuYYzNHMPdZ9evIVCg/Q9/eLVa+crA5XzvqhrLE/naF+kKBvrR+ qgETOLmj98mqvqUEoXpaGNSp1IQTUX3swm6flYSOchUzgLnFShDk2TtG3TmMeRHyAD4+uq3 Srq+2/fFHkgnjbY4LUq9GRAIPUwzpq9IRgEuwVFfunyJm8zM88EsEVZ+q4Uf1Be//XZz9Rh TaiOX+cRxwV3Tptx4aIvIbiPEE1NK4Yta2bU8jAolzJ1A0O9qB/DEbBCu0xA== ARC-Authentication-Results: i=1; ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none; dmarc=pass header.from=ffmpeg.org policy.dmarc=quarantine Authentication-Results: ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none (Message is not ARC signed); dmarc=pass (Used From Domain Record) header.from=ffmpeg.org policy.dmarc=quarantine DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1768137849; h=content-type : mime-version : content-transfer-encoding : from : to : reply-to : subject : date : from; bh=5NA6TdAQW/1T20f0uaxL2Kyc8H7PnFXiVS5Yal0l45I=; b=hxwfcK9C1OKm6bKOtEDhbTZ6GwKUEAD2avhQ5To0K2aBp/7bSKaXLHsbAK9Co9HmkP8VQ XwFqKi73x6aoRNDsYL9KxVc2SMss/9HePCk+vrutll1YHXehowBcDUQIZttrnLHd9JTab0F fl+WugcGGYkIRrV/hiXNakV9/rur+Y85/76244ZUPWM/HC260MYrggdAxLWjFZ25MIsXVa3 jsvZNAnYNXB2lSFYcHFmUM9khyXjphY0uti+igVKKZb+5P68/GneDF1ZViBsWgE1wq0m8YK a5SkhhTPgP/ykeeZCxDIcbR4c3sS8FPnsCOBaJTtdKtrxEpIeRAF1gCAl0Kw== Received: from f7c34508609e (code.ffmpeg.org [188.245.149.3]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id 5F213690D9D for ; Sun, 11 Jan 2026 15:24:09 +0200 (EET) MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Date: Sun, 11 Jan 2026 13:24:09 -0000 Message-ID: <176813784962.25.4052586008031771920@4457048688e7> Message-ID-Hash: 2NUG72RVHWRVNLKT2DKDPGLQHQAT7JVU X-Message-ID-Hash: 2NUG72RVHWRVNLKT2DKDPGLQHQAT7JVU X-MailFrom: code@ffmpeg.org X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-ffmpeg-devel.ffmpeg.org-0; header-match-ffmpeg-devel.ffmpeg.org-1; header-match-ffmpeg-devel.ffmpeg.org-2; header-match-ffmpeg-devel.ffmpeg.org-3; emergency; member-moderation X-Mailman-Version: 3.3.10 Precedence: list Reply-To: FFmpeg development discussions and patches Subject: [FFmpeg-devel] [PR] setts bsf: output tb changes (PR #21431) List-Id: FFmpeg development discussions and patches Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Gyan Doshi via ffmpeg-devel Cc: Gyan Doshi Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Archived-At: List-Archive: List-Post: PR #21431 opened by Gyan Doshi (GyanD) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21431 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21431.patch Rescale time fields wrt output tb and add option for adjustment order >>From eff1d612e28164067333d07e75bb3e6b0884dec9 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sun, 11 Jan 2026 16:48:32 +0530 Subject: [PATCH 1/2] 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 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/bsf/setts.c b/libavcodec/bsf/setts.c index 9c27b24a39..86d6aafdf8 100644 --- a/libavcodec/bsf/setts.c +++ b/libavcodec/bsf/setts.c @@ -219,6 +219,12 @@ static int setts_filter(AVBSFContext *ctx, AVPacket *pkt) if (ret < 0) return ret; + if (ctx->time_base_out.den) { + 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; -- 2.49.1 >>From 8c31e09029d7538fe51bf37d7e1955c93a98a5c8 Mon Sep 17 00:00:00 2001 From: Gyan Doshi Date: Sun, 11 Jan 2026 18:05:33 +0530 Subject: [PATCH 2/2] avcodec/bsf/setts: add option prescale When prescale is enabled, time fields are converted to the output timebase before expression evaluation. This allows option specification even if the input timebase is unknown. --- doc/bitstream_filters.texi | 7 ++--- libavcodec/bsf/setts.c | 57 +++++++++++++++++++++++++------------- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index fb31ca7380..549ca9ec45 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -913,6 +913,8 @@ Set expressions for PTS, DTS or both. Set expression for duration. @item time_base Set output time base. +@item prescale +Set whether to convert time fields to output time base before evaluation of expressions. Defaults to 0. @end table The expressions are evaluated through the eval API and can contain the following @@ -973,10 +975,7 @@ The next input PTS. The next input duration. @item TB -The timebase of stream packet belongs. - -@item TB_OUT -The output timebase. +The timebase in which time fields are denominated. The output timebase if prescale is enabled, else the input timebase. @item SR The sample rate of stream packet belongs. diff --git a/libavcodec/bsf/setts.c b/libavcodec/bsf/setts.c index 86d6aafdf8..cbaec01f35 100644 --- a/libavcodec/bsf/setts.c +++ b/libavcodec/bsf/setts.c @@ -48,7 +48,6 @@ static const char *const var_names[] = { "STARTPTS", ///< PTS at start of movie "STARTDTS", ///< DTS at start of movie "TB", ///< input timebase of the stream - "TB_OUT", ///< output timebase of the stream "SR", ///< sample rate of the stream "NOPTS", ///< The AV_NOPTS_VALUE constant NULL @@ -73,7 +72,6 @@ enum var_name { VAR_STARTPTS, VAR_STARTDTS, VAR_TB, - VAR_TB_OUT, VAR_SR, VAR_NOPTS, VAR_VARS_NB @@ -88,6 +86,7 @@ typedef struct SetTSContext { char *duration_str; AVRational time_base; + int prescale; int64_t frame_number; @@ -144,15 +143,23 @@ static int setts_init(AVBSFContext *ctx) if (s->time_base.num > 0 && s->time_base.den > 0) ctx->time_base_out = s->time_base; + 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; + } else + s->prescale = 0; s->frame_number= 0; s->var_values[VAR_STARTPTS] = AV_NOPTS_VALUE; s->var_values[VAR_STARTDTS] = AV_NOPTS_VALUE; s->var_values[VAR_NOPTS] = AV_NOPTS_VALUE; - s->var_values[VAR_TB] = ctx->time_base_in.den ? av_q2d(ctx->time_base_in) : 0; - s->var_values[VAR_TB_OUT]= ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0; s->var_values[VAR_SR] = ctx->par_in->sample_rate; + if (s->prescale) + s->var_values[VAR_TB] = av_q2d(ctx->time_base_out); + else + s->var_values[VAR_TB] = ctx->time_base_in.den ? av_q2d(ctx->time_base_in) : 0; + return 0; } @@ -160,6 +167,7 @@ static int setts_filter(AVBSFContext *ctx, AVPacket *pkt) { SetTSContext *s = ctx->priv_data; int64_t new_ts, new_pts, new_dts, new_duration; + int64_t prev_pts, prev_dts, prev_duration, cur_pts, cur_dts, cur_duration, next_pts, next_dts, next_duration; int ret; ret = ff_bsf_get_packet_ref(ctx, pkt); @@ -171,40 +179,50 @@ static int setts_filter(AVBSFContext *ctx, AVPacket *pkt) return AVERROR(EAGAIN); } + prev_pts = s->prescale ? av_rescale_q(s->prev_inpkt->pts, ctx->time_base_in, ctx->time_base_out) : s->prev_inpkt->pts; + prev_dts = s->prescale ? av_rescale_q(s->prev_inpkt->dts, ctx->time_base_in, ctx->time_base_out) : s->prev_inpkt->dts; + prev_duration = s->prescale ? av_rescale_q(s->prev_inpkt->duration, ctx->time_base_in, ctx->time_base_out) : s->prev_inpkt->duration; + cur_pts = s->prescale ? av_rescale_q(s->cur_pkt->pts, ctx->time_base_in, ctx->time_base_out) : s->cur_pkt->pts; + cur_dts = s->prescale ? av_rescale_q(s->cur_pkt->dts, ctx->time_base_in, ctx->time_base_out) : s->cur_pkt->dts; + cur_duration = s->prescale ? av_rescale_q(s->cur_pkt->duration, ctx->time_base_in, ctx->time_base_out) : s->cur_pkt->duration; + next_pts = s->prescale ? av_rescale_q(pkt->pts, ctx->time_base_in, ctx->time_base_out) : pkt->pts; + next_dts = s->prescale ? av_rescale_q(pkt->dts, ctx->time_base_in, ctx->time_base_out) : pkt->dts; + next_duration = s->prescale ? av_rescale_q(pkt->duration, ctx->time_base_in, ctx->time_base_out) : pkt->duration; + if (s->var_values[VAR_STARTPTS] == AV_NOPTS_VALUE) - s->var_values[VAR_STARTPTS] = s->cur_pkt->pts; + s->var_values[VAR_STARTPTS] = cur_pts; if (s->var_values[VAR_STARTDTS] == AV_NOPTS_VALUE) - s->var_values[VAR_STARTDTS] = s->cur_pkt->dts; + s->var_values[VAR_STARTDTS] = cur_dts; s->var_values[VAR_N] = s->frame_number++; - s->var_values[VAR_TS] = s->cur_pkt->dts; + s->var_values[VAR_TS] = cur_dts; s->var_values[VAR_POS] = s->cur_pkt->pos; - s->var_values[VAR_PTS] = s->cur_pkt->pts; - s->var_values[VAR_DTS] = s->cur_pkt->dts; - s->var_values[VAR_DURATION] = s->cur_pkt->duration; - s->var_values[VAR_PREV_INPTS] = s->prev_inpkt->pts; - s->var_values[VAR_PREV_INDTS] = s->prev_inpkt->dts; - s->var_values[VAR_PREV_INDUR] = s->prev_inpkt->duration; + s->var_values[VAR_PTS] = cur_pts; + s->var_values[VAR_DTS] = cur_dts; + s->var_values[VAR_DURATION] = cur_duration; + s->var_values[VAR_PREV_INPTS] = prev_pts; + s->var_values[VAR_PREV_INDTS] = prev_dts; + s->var_values[VAR_PREV_INDUR] = prev_duration; s->var_values[VAR_PREV_OUTPTS] = s->prev_outpkt->pts; s->var_values[VAR_PREV_OUTDTS] = s->prev_outpkt->dts; s->var_values[VAR_PREV_OUTDUR] = s->prev_outpkt->duration; - s->var_values[VAR_NEXT_PTS] = pkt->pts; - s->var_values[VAR_NEXT_DTS] = pkt->dts; - s->var_values[VAR_NEXT_DUR] = pkt->duration; + s->var_values[VAR_NEXT_PTS] = next_pts; + s->var_values[VAR_NEXT_DTS] = next_dts; + s->var_values[VAR_NEXT_DUR] = next_duration; new_ts = llrint(av_expr_eval(s->ts_expr, s->var_values, NULL)); new_duration = llrint(av_expr_eval(s->duration_expr, s->var_values, NULL)); if (s->pts_str) { - s->var_values[VAR_TS] = s->cur_pkt->pts; + s->var_values[VAR_TS] = cur_pts; new_pts = llrint(av_expr_eval(s->pts_expr, s->var_values, NULL)); } else { new_pts = new_ts; } if (s->dts_str) { - s->var_values[VAR_TS] = s->cur_pkt->dts; + s->var_values[VAR_TS] = cur_dts; new_dts = llrint(av_expr_eval(s->dts_expr, s->var_values, NULL)); } else { new_dts = new_ts; @@ -219,7 +237,7 @@ static int setts_filter(AVBSFContext *ctx, AVPacket *pkt) if (ret < 0) return ret; - if (ctx->time_base_out.den) { + if (ctx->time_base_out.den && !s->prescale) { 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); @@ -263,6 +281,7 @@ static const AVOption options[] = { { "dts", "set expression for packet DTS", OFFSET(dts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, { "duration", "set expression for packet duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str="DURATION"}, 0, 0, FLAGS }, { "time_base", "set output timebase", OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS }, + { "prescale", "convert to output timebase before evaluation", OFFSET(prescale), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { NULL }, }; -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org