PR #24124 opened by jiangjie URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24124 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24124.patch
Clip integer expression results in the double domain before storing them. This keeps high-bit-depth samples within their declared range and gives NaN and infinities defined behavior while preserving float formats. Fixes issue #24121. # Summary of changes Briefly describe what this PR does and why. <!-- If this PR requires new FATE test samples, attach them to the PR and list their target paths below (relative to the fate-suite root). Attached filenames must match the sample's filename: ```fate-samples # e.g. vorbis/new-sample.ogg ``` --> >From f6b7048be2316b47cf9c7c0b82da8a98a9ea0ebf Mon Sep 17 00:00:00 2001 From: jiangjie <[email protected]> Date: Thu, 13 Aug 2026 18:31:31 +0800 Subject: [PATCH] avfilter/blend: clip expression output to pixel depth Clip integer expression results in the double domain before storing them. This keeps high-bit-depth samples within their declared range and gives NaN and infinities defined behavior while preserving float formats. Fixes issue #24121. --- libavfilter/blend.h | 1 + libavfilter/vf_blend.c | 13 ++++++++----- tests/fate/filter-video.mak | 3 +++ tests/ref/fate/filter-blend-expr-clipping | 6 ++++++ 4 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 tests/ref/fate/filter-blend-expr-clipping diff --git a/libavfilter/blend.h b/libavfilter/blend.h index e6636839db..5c4044e0e6 100644 --- a/libavfilter/blend.h +++ b/libavfilter/blend.h @@ -78,6 +78,7 @@ typedef struct SliceParams { typedef struct FilterParams { enum BlendMode mode; double opacity; + unsigned max_value; AVExpr **e; char *expr_str; void (*blend)(const uint8_t *top, ptrdiff_t top_linesize, diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c index 21f4b19091..5e345f8153 100644 --- a/libavfilter/vf_blend.c +++ b/libavfilter/vf_blend.c @@ -129,7 +129,7 @@ static const AVOption blend_options[] = { FRAMESYNC_DEFINE_CLASS(blend, BlendContext, fs); -#define DEFINE_BLEND_EXPR(type, name, div) \ +#define DEFINE_BLEND_EXPR(type, name, div, clip) \ static void blend_expr_## name(const uint8_t *_top, ptrdiff_t top_linesize, \ const uint8_t *_bottom, ptrdiff_t bottom_linesize, \ uint8_t *_dst, ptrdiff_t dst_linesize, \ @@ -153,7 +153,8 @@ static void blend_expr_## name(const uint8_t *_top, ptrdiff_t top_linesize, values[VAR_X] = x; \ values[VAR_TOP] = values[VAR_A] = top[x]; \ values[VAR_BOTTOM] = values[VAR_B] = bottom[x]; \ - dst[x] = av_expr_eval(e, values, NULL); \ + double value = av_expr_eval(e, values, NULL); \ + dst[x] = clip ? av_clipd(value, 0, param->max_value) : value; \ } \ dst += dst_linesize; \ top += top_linesize; \ @@ -161,9 +162,9 @@ static void blend_expr_## name(const uint8_t *_top, ptrdiff_t top_linesize, } \ } -DEFINE_BLEND_EXPR(uint8_t, 8bit, 1) -DEFINE_BLEND_EXPR(uint16_t, 16bit, 2) -DEFINE_BLEND_EXPR(float, 32bit, 4) +DEFINE_BLEND_EXPR(uint8_t, 8bit, 1, 1) +DEFINE_BLEND_EXPR(uint16_t, 16bit, 2, 1) +DEFINE_BLEND_EXPR(float, 32bit, 4, 0) static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { @@ -306,6 +307,8 @@ static int config_params(AVFilterContext *ctx) for (int plane = 0; plane < FF_ARRAY_ELEMS(s->params); plane++) { FilterParams *param = &s->params[plane]; + param->max_value = s->depth < 32 ? (1U << s->depth) - 1 : 0; + if (s->all_mode >= 0) param->mode = s->all_mode; if (s->all_opacity < 1) diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 6f6a3c7391..08f806253c 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -382,6 +382,9 @@ FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_SWAPRECT_FILTER) += $(FATE_SWAPRECT) FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_TBLEND_FILTER) += fate-filter-tblend fate-filter-tblend: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf tblend=all_mode=difference128 +FATE_FILTER-$(call FILTERFRAMECRC, BLEND FORMAT NULLSRC SPLIT) += fate-filter-blend-expr-clipping +fate-filter-blend-expr-clipping: CMD = framecrc -lavfi "nullsrc=s=4x2:d=1:r=1,format=yuv422p10le,split[a][b];[a][b]blend=all_expr=if(eq(X\,0)\,-1\,if(eq(X\,1)\,2048\,if(eq(X\,2)\,1/0\,0/0)))" + FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_TELECINE_FILTER) += fate-filter-telecine fate-filter-telecine: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf telecine diff --git a/tests/ref/fate/filter-blend-expr-clipping b/tests/ref/fate/filter-blend-expr-clipping new file mode 100644 index 0000000000..563591706c --- /dev/null +++ b/tests/ref/fate/filter-blend-expr-clipping @@ -0,0 +1,6 @@ +#tb 0: 1/1 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 4x2 +#sar 0: 1/1 +0, 0, 0, 1, 32, 0x84f00810 -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
