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 F0F1F4C5D8 for ; Fri, 7 Feb 2025 14:54:19 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id BAE2768BA3B; Fri, 7 Feb 2025 16:54:15 +0200 (EET) Received: from mail-qk1-f182.google.com (mail-qk1-f182.google.com [209.85.222.182]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 91A8368B116 for ; Fri, 7 Feb 2025 16:54:08 +0200 (EET) Received: by mail-qk1-f182.google.com with SMTP id af79cd13be357-7b6fc3e9e4aso187185285a.2 for ; Fri, 07 Feb 2025 06:54:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738940047; x=1739544847; darn=ffmpeg.org; h=content-transfer-encoding:in-reply-to:autocrypt:from :content-language:references:to:subject:user-agent:mime-version:date :message-id:from:to:cc:subject:date:message-id:reply-to; bh=DWRMqphkPmfhqrNmf1ThEgpJmwVUgRC5HVvhKsLFWIY=; b=kwoKvoToerrxrEzFl+7cE19E2dQ5dVCx+ALEq4x2+i8it5KDYYMKH8NYavVvBhV14V Vk3P8Q4W50UKnE9ph2Y71OfzIkOFZjaJnAYRTEhclVMmP2D3cjf+GpC3KVeyfC00Tcw7 hnIxpV58iqWl/+jxLpVATI2gdWEVwnqILYtOVk8upECaF4K5qQweRHF29fCCnx+5oQC4 DOrUtUHKkynxxGwcsubPdGChwzXuwtwTr5WFq04Yr1kTbl8R232L/lzktPBvwq+kb1m0 68iP5ICv8vDLEKCSTAPG8DPyfKJIIeM/u5hHuw2WiBN3W99c2b2UQfcHiXb5oZXBDT+q V6mQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738940047; x=1739544847; h=content-transfer-encoding:in-reply-to:autocrypt:from :content-language:references:to:subject:user-agent:mime-version:date :message-id:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=DWRMqphkPmfhqrNmf1ThEgpJmwVUgRC5HVvhKsLFWIY=; b=EwOe8MAzIFMcTovVCmW3VWCyf+aoi96o95Rk1qyla1qQHL5VSTJ+G3dbejnO1Smg28 5RWDcUXcjGgly+uyDXstVaSg60r7ZJXIjkzdcNT2X1RNtPVjXMozdcOZPbS7ey68Ccmg BcqxO+p1cDdB8prTgXFFTte2QBPSD221O/kdxmUbr8q4E8d5ITyYNkCmJicOPO0QsDlr eQRIHZUUCDzYC14ofuOy65WKhD5IFLse36B1gxikHl/UuJNIFAZKVVQJo3Y1SpyXFWda rHzkLRJiUL4hwZivC1poN2vB1ldk7OvcUpq8hoof96eLuutoMw9f43zwN1iq+K5WVX8D Y5BA== X-Gm-Message-State: AOJu0Yyavq8nlI07KBLj9r2d/77D0DhYHOyvZ93KlCpQWpTW68HglSDD YtWYdM2kXzK3uj0dwcnW6w3DrPk5ohxKBQjaN4H7AGvUJFi3o4q6UgUg5VKk X-Gm-Gg: ASbGncv/Si1SfhD8CE57/HSw3LnBge7XmCYUauQ3l6dsfzUQC79Bl9qTH5rfubN7L96 meHJeOFDEgqc97H/1Wnw28QBnjv6cYYOIOSHGR/pLnvhfabAjMt6AMpfeFNgaVVSTXjJt3b7861 gKx8kCkfFAPMYhnYWfWBKX6xE+hPUXUyAXI2nLYxyxYByR305EIvNhcX/rpYYCyZguc6OXzj57G HUsHXdYAuxUmEM9vyvs/JOw+2N3bYH+Xr4NGNEFQB/04XZbFc7boLi3MAzelqQ8B4R2FcWyI0F3 ZDEdDv+/KFAUKxNS0qFxs2skbtETT0qYTOTZsgGkAfHu4puRmHuWtkibCAo50x5z4GFEUGU= X-Google-Smtp-Source: AGHT+IG+5ym7vii0TU5C0nr3S4e6JKMzMcKIeBFD+VNeBVrUahEhxfyr/FhiINpJPfBxgihyEMFCvw== X-Received: by 2002:a05:620a:290c:b0:7b6:dc4f:8872 with SMTP id af79cd13be357-7c047c46215mr633219285a.56.1738940046822; Fri, 07 Feb 2025 06:54:06 -0800 (PST) Received: from [192.168.1.35] (104-184-204-59.lightspeed.livnmi.sbcglobal.net. [104.184.204.59]) by smtp.gmail.com with ESMTPSA id af79cd13be357-7c041e1388asm197608585a.61.2025.02.07.06.54.05 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 07 Feb 2025 06:54:06 -0800 (PST) Message-ID: <0d4797fe-3acf-4134-a23e-38b864783584@gmail.com> Date: Fri, 7 Feb 2025 09:54:05 -0500 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird To: ffmpeg-devel@ffmpeg.org References: <20250131130015.7150-1-ffmpeg@gyani.pro> Content-Language: en-US-large From: Leo Izen Autocrypt: addr=leo.izen@gmail.com; keydata= xjMEZZw8HxYJKwYBBAHaRw8BAQdAgcfI+LbtjWarA7LQu6/WAPlKkn9tn4HalmHgGVhMUdzN KkxlbyBJemVuIChUcmFuZXB0b3JhKSA8bGVvLml6ZW5AZ21haWwuY29tPsKTBBMWCgA7FiEE HYMKC85GcJ4gOyb8dk5I6kgiGDMFAmWcPB8CGwMFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcC F4AACgkQdk5I6kgiGDOnGAEA+oJFwblAblnhK+T5a5EuEbXMTZG4FkYTYz0VmjJ0NHIA/Rn9 ZE9+EEsH8fmT0hRJSiM3+zbkwQJA9gVVYAek9kMKzjgEZZw8HxIKKwYBBAGXVQEFAQEHQDes 4thejF9AU2rkGuDuut3CQYwB4SVpI4EzU8uvPJgfAwEIB8J4BBgWCgAgFiEEHYMKC85GcJ4g Oyb8dk5I6kgiGDMFAmWcPB8CGwwACgkQdk5I6kgiGDOv3QD+PLXrL0Ihk675Ip5FG+VJOodN 6e+5n3iYC6wJ75eqG3EA/1nCywoGXlCYuzXgq3el6NOn+8awwaXcTVJFzZCRbe8M In-Reply-To: <20250131130015.7150-1-ffmpeg@gyani.pro> 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 1/31/25 8:00 AM, 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. > --- > 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 Documentation should probably state that if force_original_aspect_ratio is set, but width and height expressions are unset, that the width of the input is modified, but not the height. This way a user with, say, a 16:9 rip of a DVD will know that the height will be preserved. > > 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; Nit: you've initialized it as 1.0 everywhere else. > 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};\ This doesn't compile on MSVC (for some reason). use av_make_q(1, 1); (MSVC doesn't support compound initializers pre 2013, and MSVCPP has never supported them and likely will never. I don't know why.) > + 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; I believe you want to check if the denominator is nonzero here, not the numerator. Otherwise this gives infinity. > + > 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}; Same comment about compound literals. > + } 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}; Same here. > + 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; > + Same comment. > 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; Overall looks fine. However, here's one possible issue I forsee happening: A user has an NTSC DVD which is 720x480 and 16:9 DAR, or 32:27 SAR. That user does something simple like: ffmpeg -i dvdrip.mpg -vf scale=reset_sar=1 -c:v libx264 ... Then, it will scale the video to 853x480, which will then fail to encode in libx264 because it requires an even width with yuv420p. Then, the user will change it to scale=reset_sar=1:force_divisible_by=2 and it still won't work because force_original_aspect_ratio is unset. I don't know if this is possibly a user issue cause the solution here is to use reset_sar=1:force_original_aspect_ratio=1:force_divisible_by=2 In either case, it may be a good idea to automatically enable force_original_aspect_ratio if the width and height expressions are unset, but reset_sar is set. - Leo Izen (Traneptora) _______________________________________________ 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".