Commit 83572f1315 for ffmpeg

commit 83572f1315b97a6b1f1a77dfb224a54bc80ccf1b
Author: llyyr <llyyr.public@gmail.com>
Date:   Tue Oct 27 13:48:29 2026 +0530

    avfilter/vf_libplacebo: expose pl_color_map_params.tone_constants

    Replace the deprecated pl_tone_map_params.param field with
    pl_color_map_params.tone_constants

    This allows configuring each tonemapping algorithm independently, rather
    than relying on a single algorithm-specific parameter.

    Update the documentation to describe the new options and their defaults.

    Also deprecate the vf_libplacebo tonemapping_param option as well.

diff --git a/doc/filters.texi b/doc/filters.texi
index ff3f636804..e2f2d38f67 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -17652,14 +17652,13 @@ is adjusted based on the ratio between the targeted and actual display peak
 luminances.
 @item st2094-10
 EETF from SMPTE ST 2094-10 Annex B.2, which takes into account the input signal
-average luminance in addition to the maximum/minimum. The configurable contrast
-parameter influences the slope of the linear output segment, defaulting to
-@code{1.0} for no increase/decrease in contrast. Note that this does not
+average luminance in addition to the maximum/minimum. Note that this does not
 currently include the subjective gain/offset/gamma controls defined in Annex
 B.3.
 @item bt.2390
 EETF from the ITU-R Report BT.2390, a hermite spline roll-off with linear
-segment. The knee point offset is configurable. Note that this parameter
+segment. The knee point offset is configurable using
+@code{tonemapping_knee_offset}. Note that this parameter
 defaults to @code{1.0}, rather than the value of @code{0.5} from the ITU-R
 spec.
 @item bt.2446a
@@ -17668,24 +17667,26 @@ sources. Can be used for both forward and inverse tone mapping. Not
 configurable.
 @item spline
 Simple spline consisting of two polynomials, joined by a single pivot point.
-The parameter gives the pivot point (in PQ space), defaulting to @code{0.30}.
+The knee point is determined from the source scene average brightness,
+falling back to @code{tonemapping_knee_default} (defaulting to @code{0.4}).
 Can be used for both forward and inverse tone mapping.
 @item reinhard
-Simple non-linear, global tone mapping algorithm. The parameter specifies the
-local contrast coefficient at the display peak. Essentially, a parameter of
-@code{0.5} implies that the reference white will be about half as bright as
-when clipping. Defaults to @code{0.5}, which results in the simplest
-formulation of this function.
+Simple non-linear, global tone mapping algorithm. The
+@code{tonemapping_reinhard_contrast} option specifies the local contrast
+coefficient at the display peak. Essentially, a value of @code{0.5} implies
+that the reference white will be about half as bright as when clipping.
+Defaults to @code{0.5}, which results in the simplest formulation of this
+function.
 @item mobius
 Generalization of the reinhard tone mapping algorithm to support an additional
-linear slope near black. The tone mapping parameter indicates the trade-off
-between the linear section and the non-linear section. Essentially, for a given
-parameter @var{x}, every color value below @var{x} will be mapped linearly,
-while higher values get non-linearly tone-mapped. Values near @code{1.0} make
-this curve behave like @code{clip}, while values near @code{0.0} make this
-curve behave like @code{reinhard}. The default value is @code{0.3}, which
-provides a good balance between colorimetric accuracy and preserving
-out-of-gamut details.
+linear slope near black. The @code{tonemapping_linear_knee} option indicates
+the trade-off between the linear section and the non-linear section.
+Essentially, for a given parameter @var{x}, every color value below @var{x}
+will be mapped linearly, while higher values get non-linearly tone-mapped.
+Values near @code{1.0} make this curve behave like @code{clip}, while values
+near @code{0.0} make this curve behave like @code{reinhard}. The default value
+is @code{0.3}, which provides a good balance between colorimetric accuracy
+and preserving out-of-gamut details.
 @item hable
 Piece-wise, filmic tone-mapping algorithm developed by John Hable for use in
 Uncharted 2, inspired by a similar tone-mapping algorithm used by Kodak.
@@ -17697,20 +17698,83 @@ average brightness quite significantly. This is sort of similar to
 Fits a gamma (power) function to transfer between the source and target color
 spaces, effectively resulting in a perceptual hard-knee joining two roughly
 linear sections. This preserves details at all scales fairly accurately, but
-can result in an image with a muted or dull appearance. The parameter is used
-as the cutoff point, defaulting to @code{0.5}.
+can result in an image with a muted or dull appearance. The
+@code{tonemapping_linear_knee} option is used as the cutoff point, defaulting
+to @code{0.3}.
 @item linear
 Linearly stretches the input range to the output range, in PQ space. This will
 preserve all details accurately, but results in a significantly different
 average brightness. Can be used for inverse tone-mapping in addition to regular
-tone-mapping. The parameter can be used as an additional linear gain
-coefficient (defaulting to @code{1.0}).
+tone-mapping. The @code{tonemapping_exposure} option can be used as an additional
+linear gain coefficient (defaulting to @code{1.0}).
 @end table

 @item tonemapping_param
 For tunable tone mapping functions, this parameter can be used to fine-tune the
 curve behavior. Refer to the documentation of @code{tonemapping}. The default
-value of @code{0.0} is replaced by the curve's preferred default setting.
+value of @code{0.0} is replaced by the curve's preferred default setting, or by
+@code{tonemapping_*} options below as applicable. This option, if nonzero, takes
+effect over the corresponding values of the other @code{tonemapping_*} options.
+Deprecated, do not use.
+
+@item tonemapping_knee_adaptation
+Controls how strongly the knee point adapts to the source scene average
+brightness, relative to the target average in PQ space. A value of @code{1.0}
+fully adapts the source average to the target average, while @code{0.0}
+disables adaptation. Defaults to @code{0.4}. Affects @code{st2094-40},
+@code{st2094-10} and @code{spline}.
+
+@item tonemapping_knee_minimum
+Sets the minimum knee point as a fraction of the PQ luminance range.
+Limits how low the automatically determined knee point can be.
+Defaults to @code{0.1}.
+
+@item tonemapping_knee_maximum
+Sets the maximum knee point as a fraction of the PQ luminance range.
+Limits how high the automatically determined knee point can be.
+Defaults to @code{0.8}.
+
+@item tonemapping_knee_default
+Sets the fallback knee point used when source scene average brightness
+metadata is unavailable. Normally, the knee point is determined from
+the source scene average instead. The value should be between
+@code{tonemapping_knee_minimum} and @code{tonemapping_knee_maximum}.
+Defaults to @code{0.4}.
+
+@item tonemapping_knee_offset
+Sets the knee point offset for @code{bt.2390}. The ITU-R specification
+defines @code{0.5} as the default, but libplacebo uses @code{1.0}.
+Defaults to @code{1.0}.
+
+@item tonemapping_slope_tuning
+Controls how the slope of the @code{spline} curve is adjusted based on
+the difference between source and target peaks. The tuning aims to
+preserve a slope closer to @code{1.0} for small differences and approach
+linear mapping for larger differences. Defaults to @code{1.5}.
+
+@item tonemapping_slope_offset
+Controls the slope adjustment of the @code{spline} curve, together with
+@code{tonemapping_slope_tuning}. Defaults to @code{0.2}.
+
+@item tonemapping_spline_contrast
+Controls the contrast of the @code{spline} curve. Higher values produce
+a steeper curve, preserving midtone contrast at the cost of shadow and
+highlight detail. Lower values produce a shallower curve, preserving
+highlights at the cost of midtone contrast. Values above @code{1.0}
+can increase contrast beyond that of the source. Defaults to @code{0.5}.
+
+@item tonemapping_reinhard_contrast
+Sets the local contrast coefficient at the display peak for @code{reinhard}.
+A value of @code{0.5} makes reference white approximately half as bright
+as when clipping. Defaults to @code{0.5}.
+
+@item tonemapping_linear_knee
+Sets the knee point for the legacy @code{mobius} and @code{gamma} curves,
+which operate on linear light. Defaults to @code{0.3}.
+
+@item tonemapping_exposure
+Sets the linear exposure or gain applied by the @code{linear} tone-mapping
+method. Defaults to @code{1.0}.

 @item inverse_tonemapping
 If enabled, this filter will also attempt stretching SDR signals to fill HDR
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 161119bbc9..0d84730f4a 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -262,6 +262,7 @@ typedef struct LibplaceboContext {
     int gamut_mode;
     int tonemapping;
     float tonemapping_param;
+    struct pl_tone_map_constants tone_constants;
     int inverse_tonemapping;
     int tonemapping_lut_size;
     float contrast_recovery;
@@ -434,10 +435,39 @@ static int update_settings(AVFilterContext *ctx)
         .percentile = s->percentile,
     };

+    struct pl_tone_map_constants tone_constants = s->tone_constants;
+    if (s->tonemapping_param) {
+        switch (s->tonemapping) {
+        case TONE_MAP_ST2094_40:
+        case TONE_MAP_ST2094_10:
+            tone_constants.knee_adaptation = s->tonemapping_param;
+            break;
+        case TONE_MAP_BT2390:
+            tone_constants.knee_offset = s->tonemapping_param;
+            break;
+        case TONE_MAP_AUTO:
+        case TONE_MAP_SPLINE:
+            tone_constants.spline_contrast = s->tonemapping_param;
+            break;
+        case TONE_MAP_REINHARD:
+            tone_constants.reinhard_contrast = s->tonemapping_param;
+            break;
+        case TONE_MAP_MOBIUS:
+        case TONE_MAP_GAMMA:
+            tone_constants.linear_knee = s->tonemapping_param;
+            break;
+        case TONE_MAP_LINEAR:
+            tone_constants.exposure = s->tonemapping_param;
+            break;
+        default:
+            break;
+        }
+    }
+
     opts->color_map_params = (struct pl_color_map_params) {
         PL_COLOR_MAP_DEFAULTS
         .tone_mapping_function = get_tonemapping_func(s->tonemapping),
-        .tone_mapping_param = s->tonemapping_param,
+        .tone_constants = tone_constants,
         .inverse_tone_mapping = s->inverse_tonemapping,
         .lut_size = s->tonemapping_lut_size,
         .contrast_recovery = s->contrast_recovery,
@@ -1891,7 +1921,18 @@ static const AVOption libplacebo_options[] = {
         { "hable", "Filmic tone-mapping (Hable)", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_HABLE}, 0, 0, STATIC, .unit = "tonemap" },
         { "gamma", "Gamma function with knee", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_GAMMA}, 0, 0, STATIC, .unit = "tonemap" },
         { "linear", "Perceptually linear stretch", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_LINEAR}, 0, 0, STATIC, .unit = "tonemap" },
-    { "tonemapping_param", "Tunable parameter for some tone-mapping functions", OFFSET(tonemapping_param), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 100.0, .flags = DYNAMIC },
+    { "tonemapping_param", "Tunable parameter for some tone-mapping functions; use the corresponding tonemapping_* options instead", OFFSET(tonemapping_param), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 100.0, .flags = DYNAMIC | AV_OPT_FLAG_DEPRECATED },
+    { "tonemapping_knee_adaptation", "Scene-average knee point adaptation", OFFSET(tone_constants.knee_adaptation), AV_OPT_TYPE_FLOAT, {.dbl = 0.4}, 0.0, 1.0, DYNAMIC },
+    { "tonemapping_knee_minimum", "Minimum knee point in PQ space", OFFSET(tone_constants.knee_minimum), AV_OPT_TYPE_FLOAT, {.dbl = 0.1}, 0.0, 0.5, DYNAMIC },
+    { "tonemapping_knee_maximum", "Maximum knee point in PQ space", OFFSET(tone_constants.knee_maximum), AV_OPT_TYPE_FLOAT, {.dbl = 0.8}, 0.5, 1.0, DYNAMIC },
+    { "tonemapping_knee_default", "Fallback knee point without scene average metadata", OFFSET(tone_constants.knee_default), AV_OPT_TYPE_FLOAT, {.dbl = 0.4}, 0.0, 1.0, DYNAMIC },
+    { "tonemapping_knee_offset", "BT.2390 knee point offset", OFFSET(tone_constants.knee_offset), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.5, 2.0, DYNAMIC },
+    { "tonemapping_slope_tuning", "Spline slope tuning", OFFSET(tone_constants.slope_tuning), AV_OPT_TYPE_FLOAT, {.dbl = 1.5}, 0.0, 10.0, DYNAMIC },
+    { "tonemapping_slope_offset", "Spline slope offset", OFFSET(tone_constants.slope_offset), AV_OPT_TYPE_FLOAT, {.dbl = 0.2}, 0.0, 1.0, DYNAMIC },
+    { "tonemapping_spline_contrast", "Spline curve contrast", OFFSET(tone_constants.spline_contrast), AV_OPT_TYPE_FLOAT, {.dbl = 0.5}, 0.0, 1.5, DYNAMIC },
+    { "tonemapping_reinhard_contrast", "Reinhard contrast at the display peak", OFFSET(tone_constants.reinhard_contrast), AV_OPT_TYPE_FLOAT, {.dbl = 0.5}, 0.0, 1.0, DYNAMIC },
+    { "tonemapping_linear_knee", "Linear-light knee point for Mobius and gamma", OFFSET(tone_constants.linear_knee), AV_OPT_TYPE_FLOAT, {.dbl = 0.3}, 0.0, 1.0, DYNAMIC },
+    { "tonemapping_exposure", "Exposure for linear tone mapping", OFFSET(tone_constants.exposure), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 10.0, DYNAMIC },
     { "inverse_tonemapping", "Inverse tone mapping (range expansion)", OFFSET(inverse_tonemapping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC },
     { "tonemapping_lut_size", "Tone-mapping LUT size", OFFSET(tonemapping_lut_size), AV_OPT_TYPE_INT, {.i64 = 256}, 2, 1024, DYNAMIC },
     { "contrast_recovery", "HDR contrast recovery strength", OFFSET(contrast_recovery), AV_OPT_TYPE_FLOAT, {.dbl = 0.30}, 0.0, 3.0, DYNAMIC },