From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 531614C426 for ; Fri, 7 Feb 2025 04:00:21 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 0F21068BA9D; Fri, 7 Feb 2025 06:00:19 +0200 (EET) Received: from mout-p-103.mailbox.org (mout-p-103.mailbox.org [80.241.56.161]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7566F68BA00 for ; Fri, 7 Feb 2025 06:00:11 +0200 (EET) Received: from smtp102.mailbox.org (smtp102.mailbox.org [IPv6:2001:67c:2050:b231:465::102]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-103.mailbox.org (Postfix) with ESMTPS id 4Yq0c829gnz9slL for ; Fri, 7 Feb 2025 05:00:08 +0100 (CET) Message-ID: <5382b745-3edb-4a70-87b8-11b00f2e4007@gyani.pro> Date: Fri, 7 Feb 2025 09:30:05 +0530 MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org References: <20250131130015.7150-1-ffmpeg@gyani.pro> Content-Language: en-US From: Gyan Doshi In-Reply-To: <20250131130015.7150-1-ffmpeg@gyani.pro> X-Rspamd-Queue-Id: 4Yq0c829gnz9slL Subject: Re: [FFmpeg-devel] [PATCH] avfilter/scale*: add option reset_sar X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="us-ascii"; Format="flowed" Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: On 2025-01-31 06:30 pm, Gyan Doshi wrote: > For anamorphic videos, enabling this option leads to adjustment of > output dimensions to obtain square pixels when the user requests > proportional scaling through either of the w/h expressions or > force_original_aspect_ratio. > > Output SAR is always reset to 1. > > Option added to scale, scale_cuda, scale_npp & scale_vaapi. > > libplacebo already has a similar option with different semantics, > scale_vt and scale_vulkan don't implement force_oar, so for these > three filters, I've made minimal changes needed to not break building > or change output. Plan to push on Monday. Regards, Gyan > --- > doc/filters.texi | 21 +++++++++++++++++++++ > libavfilter/scale_eval.c | 13 +++++++------ > libavfilter/scale_eval.h | 5 ++++- > libavfilter/vf_libplacebo.c | 2 +- > libavfilter/vf_scale.c | 13 +++++++++++-- > libavfilter/vf_scale_cuda.c | 25 +++++++++++++++++++------ > libavfilter/vf_scale_npp.c | 13 +++++++++++-- > libavfilter/vf_scale_vaapi.c | 13 +++++++++++-- > libavfilter/vf_scale_vt.c | 2 +- > libavfilter/vf_scale_vulkan.c | 2 +- > 10 files changed, 87 insertions(+), 22 deletions(-) > > diff --git a/doc/filters.texi b/doc/filters.texi > index a14c7e7e77..71de1ab2dc 100644 > --- a/doc/filters.texi > +++ b/doc/filters.texi > @@ -21285,6 +21285,13 @@ This option can be handy if you need to have a video fit within or exceed > a defined resolution using @option{force_original_aspect_ratio} but also have > encoder restrictions on width or height divisibility. > > +@item reset_sar > +For anamorphic videos, enabling this option leads to adjustment of output dimensions > +to obtain square pixels when the user requests proportional scaling through either of > +the width or height expressions or through force_original_aspect_ratio. > +Output SAR is always reset to 1. > +Default is false. > + > @end table > > The values of the @option{w} and @option{h} options are expressions > @@ -21538,6 +21545,13 @@ Affects the curves of the bicubic algorithm. > @item force_divisible_by > Work the same as the identical @ref{scale} filter options. > > +@item reset_sar > +For anamorphic videos, enabling this option leads to adjustment of output dimensions > +to obtain square pixels when the user requests proportional scaling through either of > +the width or height expressions or through force_original_aspect_ratio. > +Output SAR is always reset to 1. > +Default is false. > + > @end table > > @subsection Examples > @@ -21641,6 +21655,13 @@ This option can be handy if you need to have a video fit within or exceed > a defined resolution using @option{force_original_aspect_ratio} but also have > encoder restrictions on width or height divisibility. > > +@item reset_sar > +For anamorphic videos, enabling this option leads to adjustment of output dimensions > +to obtain square pixels when the user requests proportional scaling through either of > +the width or height expressions or through force_original_aspect_ratio. > +Output SAR is always reset to 1. > +Default is false. > + > @item eval > Specify when to evaluate @var{width} and @var{height} expression. It accepts the following values: > > diff --git a/libavfilter/scale_eval.c b/libavfilter/scale_eval.c > index dc8d522b1e..53f5e22b0e 100644 > --- a/libavfilter/scale_eval.c > +++ b/libavfilter/scale_eval.c > @@ -112,7 +112,8 @@ fail: > > int ff_scale_adjust_dimensions(AVFilterLink *inlink, > int *ret_w, int *ret_h, > - int force_original_aspect_ratio, int force_divisible_by) > + int force_original_aspect_ratio, int force_divisible_by, > + double w_adj) > { > int64_t w, h; > int factor_w, factor_h; > @@ -132,7 +133,7 @@ int ff_scale_adjust_dimensions(AVFilterLink *inlink, > } > > if (w < 0 && h < 0) { > - w = inlink->w; > + w = inlink->w * w_adj; > h = inlink->h; > } > > @@ -140,18 +141,18 @@ int ff_scale_adjust_dimensions(AVFilterLink *inlink, > * earlier. If no factor was set, nothing will happen as the default > * factor is 1 */ > if (w < 0) > - w = av_rescale(h, inlink->w, inlink->h * factor_w) * factor_w; > + w = av_rescale(h, inlink->w * w_adj, inlink->h * factor_w) * factor_w; > if (h < 0) > - h = av_rescale(w, inlink->h, inlink->w * factor_h) * factor_h; > + h = av_rescale(w, inlink->h, inlink->w * w_adj * factor_h) * factor_h; > > /* Note that force_original_aspect_ratio may overwrite the previous set > * dimensions so that it is not divisible by the set factors anymore > * unless force_divisible_by is defined as well */ > if (force_original_aspect_ratio) { > // Including force_divisible_by here rounds to the nearest multiple of it. > - int64_t tmp_w = av_rescale(h, inlink->w, inlink->h * (int64_t)force_divisible_by) > + int64_t tmp_w = av_rescale(h, inlink->w * w_adj, inlink->h * (int64_t)force_divisible_by) > * force_divisible_by; > - int64_t tmp_h = av_rescale(w, inlink->h, inlink->w * (int64_t)force_divisible_by) > + int64_t tmp_h = av_rescale(w, inlink->h, inlink->w * w_adj * (int64_t)force_divisible_by) > * force_divisible_by; > > if (force_original_aspect_ratio == 1) { > diff --git a/libavfilter/scale_eval.h b/libavfilter/scale_eval.h > index b489528404..6cab623e1c 100644 > --- a/libavfilter/scale_eval.h > +++ b/libavfilter/scale_eval.h > @@ -40,10 +40,13 @@ int ff_scale_eval_dimensions(void *ctx, > * or both of the evaluated values are of the form '-n' or if > * force_original_aspect_ratio is set. force_divisible_by is used only when > * force_original_aspect_ratio is set and must be at least 1. > + * w_adj is the input SAR when the output dimensions are intended to be square > + * pixels, else should be 1. > * > * Returns negative error code on error or non negative on success > */ > int ff_scale_adjust_dimensions(AVFilterLink *inlink, > int *ret_w, int *ret_h, > - int force_original_aspect_ratio, int force_divisible_by); > + int force_original_aspect_ratio, int force_divisible_by, > + double w_adj); > #endif > diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c > index c884c621c8..e1c6629f6d 100644 > --- a/libavfilter/vf_libplacebo.c > +++ b/libavfilter/vf_libplacebo.c > @@ -1201,7 +1201,7 @@ static int libplacebo_config_output(AVFilterLink *outlink) > > ff_scale_adjust_dimensions(inlink, &outlink->w, &outlink->h, > s->force_original_aspect_ratio, > - s->force_divisible_by); > + s->force_divisible_by, 1.f); > > if (s->normalize_sar || s->nb_inputs > 1) { > /* SAR is normalized, or we have multiple inputs, set out to 1:1 */ > diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c > index 14ce1fbbd8..2eae981b57 100644 > --- a/libavfilter/vf_scale.c > +++ b/libavfilter/vf_scale.c > @@ -176,6 +176,7 @@ typedef struct ScaleContext { > > int force_original_aspect_ratio; > int force_divisible_by; > + int reset_sar; > > int eval_mode; ///< expression evaluation mode > > @@ -645,6 +646,7 @@ static int config_props(AVFilterLink *outlink) > outlink->src->inputs[0]; > ScaleContext *scale = ctx->priv; > uint8_t *flags_val = NULL; > + double w_adj = 1; > int ret; > > if ((ret = scale_eval_dimensions(ctx)) < 0) > @@ -653,9 +655,13 @@ static int config_props(AVFilterLink *outlink) > outlink->w = scale->w; > outlink->h = scale->h; > > + if (scale->reset_sar) > + w_adj = IS_SCALE2REF(ctx) ? scale->var_values[VAR_S2R_MAIN_SAR] : > + scale->var_values[VAR_SAR]; > + > ret = ff_scale_adjust_dimensions(inlink, &outlink->w, &outlink->h, > scale->force_original_aspect_ratio, > - scale->force_divisible_by); > + scale->force_divisible_by, w_adj); > > if (ret < 0) > goto fail; > @@ -668,7 +674,9 @@ static int config_props(AVFilterLink *outlink) > > /* TODO: make algorithm configurable */ > > - if (inlink0->sample_aspect_ratio.num){ > + if (scale->reset_sar) > + outlink->sample_aspect_ratio = (AVRational){1, 1}; > + else if (inlink0->sample_aspect_ratio.num){ > outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink0->w, outlink->w * inlink0->h}, inlink0->sample_aspect_ratio); > } else > outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; > @@ -1175,6 +1183,7 @@ static const AVOption scale_options[] = { > { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, .unit = "force_oar" }, > { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, .unit = "force_oar" }, > { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1}, 1, 256, FLAGS }, > + { "reset_sar", "scale output frame to have square pixels", OFFSET(reset_sar), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS }, > { "param0", "Scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX }, -DBL_MAX, DBL_MAX, FLAGS }, > { "param1", "Scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX }, -DBL_MAX, DBL_MAX, FLAGS }, > { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_INIT}, 0, EVAL_MODE_NB-1, FLAGS, .unit = "eval" }, > diff --git a/libavfilter/vf_scale_cuda.c b/libavfilter/vf_scale_cuda.c > index 5f9fd59118..de1883a1df 100644 > --- a/libavfilter/vf_scale_cuda.c > +++ b/libavfilter/vf_scale_cuda.c > @@ -96,6 +96,7 @@ typedef struct CUDAScaleContext { > > int force_original_aspect_ratio; > int force_divisible_by; > + int reset_sar; > > CUcontext cu_ctx; > CUmodule cu_module; > @@ -355,6 +356,7 @@ static av_cold int cudascale_config_props(AVFilterLink *outlink) > AVHWFramesContext *frames_ctx; > AVCUDADeviceContext *device_hwctx; > int w, h; > + double w_adj = 1.0; > int ret; > > if ((ret = ff_scale_eval_dimensions(s, > @@ -363,8 +365,12 @@ static av_cold int cudascale_config_props(AVFilterLink *outlink) > &w, &h)) < 0) > goto fail; > > + if (s->reset_sar) > + w_adj = inlink->sample_aspect_ratio.num ? > + (double)inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; > + > ff_scale_adjust_dimensions(inlink, &w, &h, > - s->force_original_aspect_ratio, s->force_divisible_by); > + s->force_original_aspect_ratio, s->force_divisible_by, w_adj); > > if (((int64_t)h * inlink->w) > INT_MAX || > ((int64_t)w * inlink->h) > INT_MAX) > @@ -383,7 +389,9 @@ static av_cold int cudascale_config_props(AVFilterLink *outlink) > s->hwctx = device_hwctx; > s->cu_stream = s->hwctx->stream; > > - if (inlink->sample_aspect_ratio.num) { > + if (s->reset_sar) > + outlink->sample_aspect_ratio = (AVRational){1, 1}; > + else if (inlink->sample_aspect_ratio.num) { > outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h*inlink->w, > outlink->w*inlink->h}, > inlink->sample_aspect_ratio); > @@ -574,10 +582,14 @@ static int cudascale_filter_frame(AVFilterLink *link, AVFrame *in) > if (ret < 0) > goto fail; > > - av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, > - (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, > - (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, > - INT_MAX); > + if (s->reset_sar) { > + out->sample_aspect_ratio = (AVRational){1, 1}; > + } else { > + av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, > + (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, > + (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, > + INT_MAX); > + } > > av_frame_free(&in); > return ff_filter_frame(outlink, out); > @@ -614,6 +626,7 @@ static const AVOption options[] = { > { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, .unit = "force_oar" }, > { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, .unit = "force_oar" }, > { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 256, FLAGS }, > + { "reset_sar", "scale output frame to have square pixels", OFFSET(reset_sar), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS }, > { NULL }, > }; > > diff --git a/libavfilter/vf_scale_npp.c b/libavfilter/vf_scale_npp.c > index ec3267801b..5274158f1b 100644 > --- a/libavfilter/vf_scale_npp.c > +++ b/libavfilter/vf_scale_npp.c > @@ -160,6 +160,7 @@ typedef struct NPPScaleContext { > > int force_original_aspect_ratio; > int force_divisible_by; > + int reset_sar; > > int interp_algo; > > @@ -650,14 +651,19 @@ static int config_props(AVFilterLink *outlink) > outlink->src->inputs[1] : > outlink->src->inputs[0]; > NPPScaleContext *s = ctx->priv; > + double w_adj = 1.0; > int ret; > > if ((ret = nppscale_eval_dimensions(ctx)) < 0) > goto fail; > > + if (s->reset_sar) > + w_adj = IS_SCALE2REF(ctx) ? s->var_values[VAR_S2R_MAIN_SAR] : > + s->var_values[VAR_SAR]; > + > ff_scale_adjust_dimensions(inlink, &s->w, &s->h, > s->force_original_aspect_ratio, > - s->force_divisible_by); > + s->force_divisible_by, w_adj); > > if (s->w > INT_MAX || s->h > INT_MAX || > (s->h * inlink->w) > INT_MAX || > @@ -674,7 +680,9 @@ static int config_props(AVFilterLink *outlink) > av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d -> w:%d h:%d\n", > inlink->w, inlink->h, outlink->w, outlink->h); > > - if (inlink->sample_aspect_ratio.num) > + if (s->reset_sar) > + outlink->sample_aspect_ratio = (AVRational){1, 1}; > + else if (inlink->sample_aspect_ratio.num) > outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h*inlink->w, > outlink->w*inlink->h}, > inlink->sample_aspect_ratio); > @@ -1019,6 +1027,7 @@ static const AVOption options[] = { > { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, .unit = "force_oar" }, > { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, .unit = "force_oar" }, > { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 256, FLAGS }, > + { "reset_sar", "scale output frame to have square pixels", OFFSET(reset_sar), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS }, > { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, { .i64 = EVAL_MODE_INIT }, 0, EVAL_MODE_NB-1, FLAGS, .unit = "eval" }, > { "init", "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, { .i64 = EVAL_MODE_INIT }, 0, 0, FLAGS, .unit = "eval" }, > { "frame", "eval expressions during initialization and per-frame", 0, AV_OPT_TYPE_CONST, { .i64 = EVAL_MODE_FRAME }, 0, 0, FLAGS, .unit = "eval" }, > diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c > index 0f2d617996..ab95d41e0e 100644 > --- a/libavfilter/vf_scale_vaapi.c > +++ b/libavfilter/vf_scale_vaapi.c > @@ -39,6 +39,7 @@ typedef struct ScaleVAAPIContext { > > int force_original_aspect_ratio; > int force_divisible_by; > + int reset_sar; > > char *colour_primaries_string; > char *colour_transfer_string; > @@ -73,6 +74,7 @@ static int scale_vaapi_config_output(AVFilterLink *outlink) > AVFilterContext *avctx = outlink->src; > VAAPIVPPContext *vpp_ctx = avctx->priv; > ScaleVAAPIContext *ctx = avctx->priv; > + double w_adj = 1.0; > int err; > > if ((err = ff_scale_eval_dimensions(ctx, > @@ -81,8 +83,12 @@ static int scale_vaapi_config_output(AVFilterLink *outlink) > &vpp_ctx->output_width, &vpp_ctx->output_height)) < 0) > return err; > > + if (ctx->reset_sar) > + w_adj = inlink->sample_aspect_ratio.num ? > + (double)inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; > + > ff_scale_adjust_dimensions(inlink, &vpp_ctx->output_width, &vpp_ctx->output_height, > - ctx->force_original_aspect_ratio, ctx->force_divisible_by); > + ctx->force_original_aspect_ratio, ctx->force_divisible_by, w_adj); > > if (inlink->w == vpp_ctx->output_width && inlink->h == vpp_ctx->output_height && > (vpp_ctx->input_frames->sw_format == vpp_ctx->output_format || > @@ -98,7 +104,9 @@ static int scale_vaapi_config_output(AVFilterLink *outlink) > if (err < 0) > return err; > > - if (inlink->sample_aspect_ratio.num) > + if (ctx->reset_sar) > + outlink->sample_aspect_ratio = (AVRational){1, 1}; > + else if (inlink->sample_aspect_ratio.num) > outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink->w, outlink->w * inlink->h}, inlink->sample_aspect_ratio); > else > outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; > @@ -274,6 +282,7 @@ static const AVOption scale_vaapi_options[] = { > { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, .unit = "force_oar" }, > { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, .unit = "force_oar" }, > { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1}, 1, 256, FLAGS }, > + { "reset_sar", "scale output frame to have square pixels", OFFSET(reset_sar), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS }, > > { NULL }, > }; > diff --git a/libavfilter/vf_scale_vt.c b/libavfilter/vf_scale_vt.c > index 162ea8fcec..c024717bc2 100644 > --- a/libavfilter/vf_scale_vt.c > +++ b/libavfilter/vf_scale_vt.c > @@ -248,7 +248,7 @@ static int scale_vt_config_output(AVFilterLink *outlink) > if (err < 0) > return err; > > - ff_scale_adjust_dimensions(inlink, &s->output_width, &s->output_height, 0, 1); > + ff_scale_adjust_dimensions(inlink, &s->output_width, &s->output_height, 0, 1, 1.f); > > outlink->w = s->output_width; > outlink->h = s->output_height; > diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c > index 6f99769d81..1d6492e213 100644 > --- a/libavfilter/vf_scale_vulkan.c > +++ b/libavfilter/vf_scale_vulkan.c > @@ -336,7 +336,7 @@ static int scale_vulkan_config_output(AVFilterLink *outlink) > if (err < 0) > return err; > > - ff_scale_adjust_dimensions(inlink, &vkctx->output_width, &vkctx->output_height, 0, 1); > + ff_scale_adjust_dimensions(inlink, &vkctx->output_width, &vkctx->output_height, 0, 1, 1.f); > > outlink->w = vkctx->output_width; > outlink->h = vkctx->output_height; _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".