1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-10-06 05:47:18 +02:00

avfilter/vf_libplacebo: introduce fit_sense option

This allows choosing whether the `fit_mode` merely controls the placement
of the image within the output resolution, or whether the output resolution
is also adjusted according to the given `fit_mode`.
This commit is contained in:
Niklas Haas
2025-09-23 20:49:07 +02:00
committed by Niklas Haas
parent 12d696cff4
commit b80f28fcbc
2 changed files with 43 additions and 3 deletions

View File

@@ -16449,7 +16449,8 @@ will be performed.
@item force_original_aspect_ratio
@item force_divisible_by
Work the same as the identical @ref{scale} filter options.
Work the same as the identical @ref{scale} filter options. Note that
@option{force_divisible_by} also works with @code{fit_sense=constraint}.
@item reset_sar
If enabled, output frames will always have a pixel aspect ratio of 1:1. If
@@ -16503,6 +16504,22 @@ to either @code{contain} or @code{none}, depending on whether the input is
larger than the output or not.
@end table
@item fit_sense
When @option{fit_mode} is in use, this option controls how the fit strategy
is applied against the specified output resolution. Mutually exclusive with
@option{force_original_aspect_ratio}. Valid values are:
@table @samp
@item target
The computed output resolution is taken as the exact size of the output frame.
This is the default behavior.
@item constraint
The computed output resolution is a size reference against which the fit mode
is applied, enlarging or decreasing the true frame size as needed to fit the
content.
@end table
@item fillcolor
Set the color used to fill the output area not covered by the output image, for
example as a result of @option{normalize_sar}. For the general syntax of this

View File

@@ -161,6 +161,12 @@ enum fit_mode {
FIT_MODE_NB,
};
enum fit_sense {
FIT_TARGET,
FIT_CONSTRAINT,
FIT_SENSE_NB,
};
typedef struct LibplaceboContext {
/* lavfi vulkan*/
FFVulkanContext vkctx;
@@ -206,6 +212,7 @@ typedef struct LibplaceboContext {
int reset_sar;
int normalize_sar;
int fit_mode;
int fit_sense;
int apply_filmgrain;
int apply_dovi;
int colorspace;
@@ -1452,11 +1459,24 @@ static int libplacebo_config_output(AVFilterLink *outlink)
double sar_in = inlink->sample_aspect_ratio.num ?
av_q2d(inlink->sample_aspect_ratio) : 1.0;
int force_oar = s->force_original_aspect_ratio;
if (!force_oar && s->fit_sense == FIT_CONSTRAINT) {
if (s->fit_mode == FIT_CONTAIN || s->fit_mode == FIT_SCALE_DOWN) {
force_oar = SCALE_FORCE_OAR_DECREASE;
} else if (s->fit_mode == FIT_COVER) {
force_oar = SCALE_FORCE_OAR_INCREASE;
}
}
ff_scale_adjust_dimensions(inlink, &outlink->w, &outlink->h,
s->force_original_aspect_ratio,
s->force_divisible_by,
force_oar, s->force_divisible_by,
s->reset_sar ? sar_in : 1.0);
if (s->fit_mode == FIT_SCALE_DOWN && s->fit_sense == FIT_CONSTRAINT) {
int w_adj = s->reset_sar ? sar_in * inlink->w : inlink->w;
outlink->w = FFMIN(outlink->w, w_adj);
outlink->h = FFMIN(outlink->h, inlink->h);
}
if (s->nb_inputs > 1 && !s->disable_fbos) {
/* Create a separate renderer and composition texture */
@@ -1586,6 +1606,9 @@ static const AVOption libplacebo_options[] = {
{ "none", "Keep input unscaled, padding and cropping as needed", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_NONE }, 0, 0, STATIC, .unit = "fit_mode" },
{ "place", "Keep input unscaled, padding and cropping as needed", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_NONE }, 0, 0, STATIC, .unit = "fit_mode" },
{ "scale_down", "Downscale only if larger, padding to preserve aspect", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_SCALE_DOWN }, 0, 0, STATIC, .unit = "fit_mode" },
{ "fit_sense", "Output size strategy (for the base layer only)", OFFSET(fit_sense), AV_OPT_TYPE_INT, {.i64 = FIT_TARGET }, 0, FIT_SENSE_NB - 1, STATIC, .unit = "fit_sense" },
{ "target", "Computed resolution is the exact output size", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_TARGET }, 0, 0, STATIC, .unit = "fit_sense" },
{ "constraint", "Computed resolution constrains the output size", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_CONSTRAINT }, 0, 0, STATIC, .unit = "fit_sense" },
{ "fillcolor", "Background fill color", OFFSET(fillcolor), AV_OPT_TYPE_COLOR, {.str = "black@0"}, .flags = DYNAMIC },
{ "corner_rounding", "Corner rounding radius", OFFSET(corner_rounding), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 1.0, .flags = DYNAMIC },
{ "lut", "Path to custom LUT file to apply", OFFSET(lut_filename), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = STATIC },