Hi Drew,

On Mon, Aug 18, 2025 at 11:55 AM Drew Dunne via ffmpeg-devel <
ffmpeg-devel@ffmpeg.org> wrote:

> Add a new flag to the vf_colorspace filter which provides the user an
> option to clamp the linear and delinear transfer characteristics LUT
> values to the [0, 1] represented range. This helps constrain the
> potential value range when converting between colorspaces.
>
> Signed-off-by: Drew Dunne <asdu...@google.com>
> ---
>  doc/filters.texi            |  3 +++
>  libavfilter/vf_colorspace.c | 14 ++++++++++++--
>  2 files changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/doc/filters.texi b/doc/filters.texi
> index 908c98a3cf..cb09d73f62 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -10403,6 +10403,9 @@ von Kries whitepoint adaptation
>  identity whitepoint adaptation (i.e. no whitepoint adaptation)
>  @end table
>
> +@item clamptrc
> +Clamps the linear and delinear transfer characteristics LUT values to the
> [0, 1] represented range.
> +
>  @item iall
>  Override all input properties at once. Same accepted values as @ref{all}.
>
> diff --git a/libavfilter/vf_colorspace.c b/libavfilter/vf_colorspace.c
> index e1f4725f63..15b4858b24 100644
> --- a/libavfilter/vf_colorspace.c
> +++ b/libavfilter/vf_colorspace.c
> @@ -123,6 +123,7 @@ typedef struct ColorSpaceContext {
>      int fast_mode;
>      enum DitherMode dither;
>      enum WhitepointAdaptation wp_adapt;
> +    int clamp_trc;
>
>      int16_t *rgb[3];
>      ptrdiff_t rgb_stride;
> @@ -215,7 +216,9 @@ static int fill_gamma_table(ColorSpaceContext *s)
>          } else {
>              d = out_alpha * pow(v, out_gamma) - (out_alpha - 1.0);
>          }
> -        s->delin_lut[n] = av_clip_int16(lrint(d * 28672.0));
> +        long d_rounded = lrint(d * 28672.0);
> +        s->delin_lut[n] = s->clamp_trc ? av_clip64(d_rounded, 0, 28672)
> +                                       : av_clip_int16(d_rounded);
>
>          // linearize
>          if (v <= -in_beta * in_delta) {
> @@ -225,7 +228,9 @@ static int fill_gamma_table(ColorSpaceContext *s)
>          } else {
>              l = pow((v + in_alpha - 1.0) * in_ialpha, in_igamma);
>          }
> -        s->lin_lut[n] = av_clip_int16(lrint(l * 28672.0));
> +        long l_rounded = lrint(l * 28672.0);
> +        s->lin_lut[n] = s->clamp_trc ? av_clip64(l_rounded, 0, 28672)
> +                                     : av_clip_int16(l_rounded);
>      }
>
>      return 0;
> @@ -1000,6 +1005,11 @@ static const AVOption colorspace_options[] = {
>      ENUM("vonkries", WP_ADAPT_VON_KRIES, "wpadapt"),
>      ENUM("identity", WP_ADAPT_IDENTITY, "wpadapt"),
>
> +    { "clamptrc",
> +      "Clamps the linear and delinear LUT output values to the range [0,
> 1].",
> +      OFFSET(clamp_trc), AV_OPT_TYPE_BOOL,  { .i64 = 0    },
> +      0, 1, FLAGS },
> +
>      { "iall",       "Set all input color properties together",
>        OFFSET(user_iall),   AV_OPT_TYPE_INT, { .i64 = CS_UNSPECIFIED },
>        CS_UNSPECIFIED, CS_NB - 1, FLAGS, .unit = "all" },
> --
> 2.51.0.rc1.163.g2494970778-goog


Can you provide an example where this is relevant? I'm trying to understand
the three components here: changing from int to long, clipping in 64bit
instead of 16bit, and adding positive+negative range clamp. I'm wondering
which of these you've observed, and what type of minimal fix would be
sufficient.

(Part of the question here is that we might not want this to be an
AVOption, but to be always-on.)

Thanks,
Ronald
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to