The branch, master has been updated
via e05f8acabff468c1382277c1f31fa8e9d90c3202 (commit)
via ea346a23de428930fcd9cc0666150f35e04cb902 (commit)
from 8fad52bd57d5bcedce8dc4ae3166c1a50f895690 (commit)
- Log -----------------------------------------------------------------
commit e05f8acabff468c1382277c1f31fa8e9d90c3202
Author: Andreas Rheinhardt <[email protected]>
AuthorDate: Wed Oct 1 08:27:14 2025 +0200
Commit: Andreas Rheinhardt <[email protected]>
CommitDate: Sat Oct 4 17:49:08 2025 +0200
avfilter/blend_modes: Don't build duplicate functions
Some of the blend mode functions only depend on the underlying type
and therefore need only one version for 9, 10, 12, 14, 16 bits.
This saved 35104B with GCC and 26880B with Clang.
Signed-off-by: Andreas Rheinhardt <[email protected]>
diff --git a/libavfilter/blend_modes.c b/libavfilter/blend_modes.c
index 35e365996c..981c15a025 100644
--- a/libavfilter/blend_modes.c
+++ b/libavfilter/blend_modes.c
@@ -34,16 +34,21 @@
#define MAX 255
#define HALF 128
#define CLIP(x) (av_clip_uint8(x))
+#define BUILD_TYPE_SPECIFIC_FUNCS
#elif DEPTH == 32
#define PIXEL float
#define MAX 1.f
#define HALF 0.5f
#define CLIP(x) (x)
+#define BUILD_TYPE_SPECIFIC_FUNCS
#else
#define PIXEL uint16_t
#define MAX ((1 << DEPTH) - 1)
#define HALF (1 << (DEPTH - 1))
#define CLIP(x) ((int)av_clip_uintp2(x, DEPTH))
+#if DEPTH == 16
+#define BUILD_TYPE_SPECIFIC_FUNCS
+#endif
#endif
#undef MULTIPLY
@@ -109,13 +114,10 @@ static void fn0(NAME)(const uint8_t *_top, ptrdiff_t
top_linesize, \
fn(addition, FFMIN(MAX, A + B))
fn(grainmerge, CLIP(A + B - HALF))
-fn(average, (A + B) / 2)
-fn(subtract, FFMAX(0, A - B))
fn(multiply, MULTIPLY(1, A, B))
fn(multiply128,CLIP((A - HALF) * B / MDIV + HALF))
fn(negation, MAX - FFABS(MAX - A - B))
fn(extremity, FFABS(MAX - A - B))
-fn(difference, FFABS(A - B))
fn(grainextract, CLIP(HALF + A - B))
fn(screen, SCREEN(1, A, B))
fn(overlay, (A < HALF) ? MULTIPLY(2, A, B) : SCREEN(2, A, B))
@@ -123,8 +125,6 @@ fn(hardlight, (B < HALF) ? MULTIPLY(2, B, A) : SCREEN(2,
B, A))
fn(hardmix, (A < (MAX - B)) ? 0: MAX)
fn(heat, (A == 0) ? 0 : MAX - FFMIN(((MAX - B) * (MAX - B)) / A, MAX))
fn(freeze, (B == 0) ? 0 : MAX - FFMIN(((MAX - A) * (MAX - A)) / B, MAX))
-fn(darken, FFMIN(A, B))
-fn(lighten, FFMAX(A, B))
fn(divide, CLIP(B == 0 ? MAX : MAX * A / B))
fn(dodge, DODGE(A, B))
fn(burn, BURN(A, B))
@@ -134,15 +134,24 @@ fn(pinlight, (B < HALF) ? FFMIN(A, 2 * B) : FFMAX(A, 2
* (B - HALF)))
fn(phoenix, FFMIN(A, B) - FFMAX(A, B) + MAX)
fn(reflect, (B == MAX) ? B : FFMIN(MAX, (A * A / (MAX - B))))
fn(glow, (A == MAX) ? A : FFMIN(MAX, (B * B / (MAX - A))))
-fn(and, INT2FLOAT(FLOAT2INT(A) & FLOAT2INT(B)))
-fn(or, INT2FLOAT(FLOAT2INT(A) | FLOAT2INT(B)))
-fn(xor, INT2FLOAT(FLOAT2INT(A) ^ FLOAT2INT(B)))
fn(vividlight, (A < HALF) ? BURN(2 * A, B) : DODGE(2 * (A - HALF), B))
fn(linearlight,CLIP((B < HALF) ? B + 2 * A - MAX : B + 2 * (A - HALF)))
fn(softdifference,CLIP((A > B) ? (B == MAX) ? 0 : (A - B) * MAX / (MAX - B) :
(B == 0) ? 0 : (B - A) * MAX / B))
-fn(geometric, GEOMETRIC(A, B))
-fn(harmonic, A == 0 && B == 0 ? 0 : 2LL * A * B / (A + B))
fn(bleach, (MAX - B) + (MAX - A) - MAX)
fn(stain, 2 * MAX - A - B)
fn(interpolate,LRINTF(MAX * (2 - cosf(A * M_PI / MAX) - cosf(B * M_PI / MAX))
* 0.25f))
fn(hardoverlay,A == MAX ? MAX : FFMIN(MAX, MAX * B / (2 * MAX - 2 * A) * (A >
HALF) + 2 * A * B / MAX * (A <= HALF)))
+
+#ifdef BUILD_TYPE_SPECIFIC_FUNCS
+fn(average, (A + B) / 2)
+fn(subtract, FFMAX(0, A - B))
+fn(difference, FFABS(A - B))
+fn(darken, FFMIN(A, B))
+fn(lighten, FFMAX(A, B))
+fn(and, INT2FLOAT(FLOAT2INT(A) & FLOAT2INT(B)))
+fn(or, INT2FLOAT(FLOAT2INT(A) | FLOAT2INT(B)))
+fn(xor, INT2FLOAT(FLOAT2INT(A) ^ FLOAT2INT(B)))
+fn(geometric, GEOMETRIC(A, B))
+fn(harmonic, A == 0 && B == 0 ? 0 : 2LL * A * B / (A + B))
+#undef BUILD_TYPE_SPECIFIC_FUNCS
+#endif
diff --git a/libavfilter/vf_blend_init.h b/libavfilter/vf_blend_init.h
index 7f66796e3e..297ca0514f 100644
--- a/libavfilter/vf_blend_init.h
+++ b/libavfilter/vf_blend_init.h
@@ -107,11 +107,11 @@ static av_cold void
init_blend_func_##depth##_##nbits##bit(FilterParams *param)
switch (param->mode) {
\
case BLEND_ADDITION: param->blend = blend_addition_##depth##bit;
break; \
case BLEND_GRAINMERGE: param->blend = blend_grainmerge_##depth##bit;
break; \
- case BLEND_AND: param->blend = blend_and_##depth##bit;
break; \
- case BLEND_AVERAGE: param->blend = blend_average_##depth##bit;
break; \
+ case BLEND_AND: param->blend = blend_and_##nbits##bit;
break; \
+ case BLEND_AVERAGE: param->blend = blend_average_##nbits##bit;
break; \
case BLEND_BURN: param->blend = blend_burn_##depth##bit;
break; \
- case BLEND_DARKEN: param->blend = blend_darken_##depth##bit;
break; \
- case BLEND_DIFFERENCE: param->blend = blend_difference_##depth##bit;
break; \
+ case BLEND_DARKEN: param->blend = blend_darken_##nbits##bit;
break; \
+ case BLEND_DIFFERENCE: param->blend = blend_difference_##nbits##bit;
break; \
case BLEND_GRAINEXTRACT: param->blend = blend_grainextract_##depth##bit;
break; \
case BLEND_DIVIDE: param->blend = blend_divide_##depth##bit;
break; \
case BLEND_DODGE: param->blend = blend_dodge_##depth##bit;
break; \
@@ -122,25 +122,25 @@ static av_cold void
init_blend_func_##depth##_##nbits##bit(FilterParams *param)
case BLEND_HARDLIGHT: param->blend = blend_hardlight_##depth##bit;
break; \
case BLEND_HARDMIX: param->blend = blend_hardmix_##depth##bit;
break; \
case BLEND_HEAT: param->blend = blend_heat_##depth##bit;
break; \
- case BLEND_LIGHTEN: param->blend = blend_lighten_##depth##bit;
break; \
+ case BLEND_LIGHTEN: param->blend = blend_lighten_##nbits##bit;
break; \
case BLEND_LINEARLIGHT: param->blend = blend_linearlight_##depth##bit;
break; \
case BLEND_MULTIPLY: param->blend = blend_multiply_##depth##bit;
break; \
case BLEND_MULTIPLY128: param->blend = blend_multiply128_##depth##bit;
break; \
case BLEND_NEGATION: param->blend = blend_negation_##depth##bit;
break; \
case BLEND_NORMAL: param->blend = blend_normal_##nbits##bit;
break; \
- case BLEND_OR: param->blend = blend_or_##depth##bit;
break; \
+ case BLEND_OR: param->blend = blend_or_##nbits##bit;
break; \
case BLEND_OVERLAY: param->blend = blend_overlay_##depth##bit;
break; \
case BLEND_PHOENIX: param->blend = blend_phoenix_##depth##bit;
break; \
case BLEND_PINLIGHT: param->blend = blend_pinlight_##depth##bit;
break; \
case BLEND_REFLECT: param->blend = blend_reflect_##depth##bit;
break; \
case BLEND_SCREEN: param->blend = blend_screen_##depth##bit;
break; \
case BLEND_SOFTLIGHT: param->blend = blend_softlight_##depth##bit;
break; \
- case BLEND_SUBTRACT: param->blend = blend_subtract_##depth##bit;
break; \
+ case BLEND_SUBTRACT: param->blend = blend_subtract_##nbits##bit;
break; \
case BLEND_VIVIDLIGHT: param->blend = blend_vividlight_##depth##bit;
break; \
- case BLEND_XOR: param->blend = blend_xor_##depth##bit;
break; \
+ case BLEND_XOR: param->blend = blend_xor_##nbits##bit;
break; \
case
BLEND_SOFTDIFFERENCE:param->blend=blend_softdifference_##depth##bit;break; \
- case BLEND_GEOMETRIC: param->blend = blend_geometric_##depth##bit;
break; \
- case BLEND_HARMONIC: param->blend = blend_harmonic_##depth##bit;
break; \
+ case BLEND_GEOMETRIC: param->blend = blend_geometric_##nbits##bit;
break; \
+ case BLEND_HARMONIC: param->blend = blend_harmonic_##nbits##bit;
break; \
case BLEND_BLEACH: param->blend = blend_bleach_##depth##bit;
break; \
case BLEND_STAIN: param->blend = blend_stain_##depth##bit;
break; \
case BLEND_INTERPOLATE: param->blend = blend_interpolate_##depth##bit;
break; \
commit ea346a23de428930fcd9cc0666150f35e04cb902
Author: Andreas Rheinhardt <[email protected]>
AuthorDate: Wed Oct 1 07:56:49 2025 +0200
Commit: Andreas Rheinhardt <[email protected]>
CommitDate: Sat Oct 4 17:49:08 2025 +0200
avfilter/blend_modes: Use stride in bytes
The blend functions currently convert strides from bytes to elements
of the type by using the stride /= sizeof(pixel) idiom. Yet this has
several drawbacks:
1. It invokes undefined behavior that happens to work when stride is
negative: size_t is typically the unsigned type of ptrdiff_t and
therefore the division will be performed as size_t, i.e. use logical
right shifts, making stride very big when sizeof(pixel) is > 1. This
works, because pointer to pixel for accesses entails an implicit
factor of sizeof(pixel) so that everything is correct modulo SIZE_MAX.
Yet this is UB and UBSan complains about it.
2. It makes the compiler emit actual shifts/ands to discard the low bits
shifted away.
3. There may be systems where alignof(uint16_t) or alignof(float) is
strictly smaller than their sizeof, so that the stride (in bytes) is
not guaranteed to be multiple of these sizeofs. In this case, dividing
by sizeof(pixel) is simply wrong.
Signed-off-by: Andreas Rheinhardt <[email protected]>
diff --git a/libavfilter/blend_modes.c b/libavfilter/blend_modes.c
index 9b1e78b146..35e365996c 100644
--- a/libavfilter/blend_modes.c
+++ b/libavfilter/blend_modes.c
@@ -92,22 +92,18 @@ static void fn0(NAME)(const uint8_t *_top, ptrdiff_t
top_linesize, \
ptrdiff_t width, ptrdiff_t height, \
FilterParams *param, SliceParams *sliceparam) \
{
\
- const PIXEL *top = (const PIXEL *)_top;
\
- const PIXEL *bottom = (const PIXEL *)_bottom;
\
- PIXEL *dst = (PIXEL *)_dst;
\
const float opacity = param->opacity;
\
\
- dst_linesize /= sizeof(PIXEL);
\
- top_linesize /= sizeof(PIXEL);
\
- bottom_linesize /= sizeof(PIXEL);
\
-
\
for (int i = 0; i < height; i++) {
\
+ const PIXEL *top = (const PIXEL *)_top;
\
+ const PIXEL *bottom = (const PIXEL *)_bottom;
\
+ PIXEL *dst = (PIXEL *)_dst;
\
for (int j = 0; j < width; j++) {
\
dst[j] = top[j] + ((EXPR)-top[j]) * opacity;
\
}
\
- dst += dst_linesize;
\
- top += top_linesize;
\
- bottom += bottom_linesize;
\
+ _dst += dst_linesize;
\
+ _top += top_linesize;
\
+ _bottom += bottom_linesize;
\
}
\
}
diff --git a/libavfilter/vf_blend_init.h b/libavfilter/vf_blend_init.h
index 98d440fe67..7f66796e3e 100644
--- a/libavfilter/vf_blend_init.h
+++ b/libavfilter/vf_blend_init.h
@@ -82,22 +82,18 @@ static void blend_normal_##name(const uint8_t *_top,
ptrdiff_t top_linesize,
ptrdiff_t width, ptrdiff_t height,
\
FilterParams *param, SliceParams *sliceparam)
\
{
\
- const type *top = (const type*)_top;
\
- const type *bottom = (const type*)_bottom;
\
- type *dst = (type*)_dst;
\
const float opacity = param->opacity;
\
\
- dst_linesize /= sizeof(type);
\
- top_linesize /= sizeof(type);
\
- bottom_linesize /= sizeof(type);
\
-
\
for (int i = 0; i < height; i++) {
\
+ const type *top = (const type*)_top;
\
+ const type *bottom = (const type*)_bottom;
\
+ type *dst = (type*)_dst;
\
for (int j = 0; j < width; j++) {
\
dst[j] = top[j] * opacity + bottom[j] * (1.f - opacity);
\
}
\
- dst += dst_linesize;
\
- top += top_linesize;
\
- bottom += bottom_linesize;
\
+ _dst += dst_linesize;
\
+ _top += top_linesize;
\
+ _bottom += bottom_linesize;
\
}
\
}
-----------------------------------------------------------------------
Summary of changes:
libavfilter/blend_modes.c | 45 +++++++++++++++++++++++++--------------------
libavfilter/vf_blend_init.h | 36 ++++++++++++++++--------------------
2 files changed, 41 insertions(+), 40 deletions(-)
hooks/post-receive
--
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]