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".