1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-10-06 05:47:18 +02:00

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 <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt
2025-10-01 07:56:49 +02:00
parent 8fad52bd57
commit ea346a23de
2 changed files with 12 additions and 20 deletions

View File

@@ -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; \
} \
}

View File

@@ -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; \
} \
}