From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 11C634BC2C for ; Wed, 1 Oct 2025 07:02:21 +0000 (UTC) Authentication-Results: ffbox; dkim=fail (body hash mismatch (got b'wCsoConrt2oIjmL+gl9kekbToLzgqVX3dqNoVWtTwU0=', expected b'cSGc5G6CeBey+AKJTt8IoaEwAx11SscyUBAtAptBOBs=')) header.d=ffmpeg.org header.i=@ffmpeg.org header.a=rsa-sha256 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1759302118; h=mime-version : to : date : message-id : reply-to : subject : list-id : list-archive : list-archive : list-help : list-owner : list-post : list-subscribe : list-unsubscribe : from : cc : content-type : content-transfer-encoding : from; bh=wCsoConrt2oIjmL+gl9kekbToLzgqVX3dqNoVWtTwU0=; b=ZrtyGpZTXyCqrL5zdWD7LHXm870uDNacMwfFHGZ4KVHTiV68El9Ttr8T7376NGxMJ8uBC pnG4NaP0j0ufb0qKTVopRHfcK5qcjV4vl534ghyXqs/16uLe6On7JihzTxLUYPcyPQYw0A/ HeqqdSHH+LINEvS5L7xTZBfkwtaYhftZxj6jzCdRzerirFjrmPbCLOPtsKhJoGziOei4B7g dBPMzpzfRrBp/fct8QO7+ZIOifu7IKHPmP+faMBnKg3SW/Fx27UXyt5woBKP5oC/wDxUwtw xW9CoADXTOPNyjh8nA0BLqYfOBqah16tYn3/bPMnP/iX5tPkQxZJd76KHvkA== Received: from [172.19.0.2] (unknown [172.19.0.2]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id B9AAE68EF59; Wed, 1 Oct 2025 10:01:58 +0300 (EEST) ARC-Seal: i=1; cv=none; a=rsa-sha256; d=ffmpeg.org; s=arc; t=1759302103; b=PgM5PznenK0OYdkZizqMmugGQB9cVB4rVE5Yq3WrD4epo62nce2M+spzvq44Vf4pbuc1R vFfQAoq1G5sSb+WKKLG7YnsP8G075L7lNxlLL2009Nmwyx2TfuqYkanWH8utLsidlOYCgM7 NPBVJoMJuJW/l3/+TOWZSYRb6fFrErD6I2bS/kwdVJHn8+bmBSygU/2kU+0S/VxBDVyLnrT K/RLA914K8Hfpw7E+v7Guusufzmjssg3OZbHsW8Dra9gUujCMyJF1pv6/HMz4jqc3N0evIM RXT5wR17jwz4Wiap9I4hurwnrGxb+Tfe7cj2HYWw8vf2WylszSfKBd3K+2Bg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=ffmpeg.org; s=arc; t=1759302103; h=from : sender : reply-to : subject : date : message-id : to : cc : mime-version : content-type : content-transfer-encoding : content-id : content-description : resent-date : resent-from : resent-sender : resent-to : resent-cc : resent-message-id : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; bh=SQCDkd+IpWeHeqkOmAz5SWGLkuqCv9O4+FbAbXW0FH4=; b=ciDONscewW/oMy1Cg1sInBVLHFHEDFCDWMrgOkeBu/vik0Braz0+SQS+a+Fg4MqwACOKq BcATFw66OBT3Vg+tFkLzMZB/vj6MTqAYkikCVoPecS9jdpAQmJKVMcNPb4GpeTY1ICwJ6OB 6Qr894JeGutfYplXG9UAVTWjPSkB3ZpWLSOxXCr9DN+x/a0ikga182K0N4tndh2xMzJNDY9 IpmCIKzZukKK85E9wcSPfDuXW/lFSV7xK1JEdrybEg7eSC/bljybvTNFA6E1H9uhY8p038O ySXZ2OfWyKflFGVzpEv88xtGNTzWLgxCb/2j3JWGgZ8ZIupjtXO5kdPNlQnQ== ARC-Authentication-Results: i=1; ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none; dmarc=pass header.from=ffmpeg.org policy.dmarc=quarantine Authentication-Results: ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none (Message is not ARC signed); dmarc=pass (Used From Domain Record) header.from=ffmpeg.org policy.dmarc=quarantine DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1759302094; h=content-type : mime-version : content-transfer-encoding : from : to : reply-to : subject : date : from; bh=cSGc5G6CeBey+AKJTt8IoaEwAx11SscyUBAtAptBOBs=; b=vXy6xrIogO2zDOCPZAuNzTV0hUDMALfaTUT5m4g+ISN7R88cmzrjPSVcG1ay4epdkTLXu uL2Y78RmXqVOWNu5qkFpG9Vii9QfGt6hic9dHZFDRz9uoVt3pMLvNzhyA1a5MoBqKHcoZyP 8Q15vArCKPCkET5+ln2c3NzOS501634m1NVx+Nq4FfKEesigWoWkWn+sv2iPWND3A2BRzQN UGenoywOZLUSQvTKSasXrpfZ4toHrVWGemjRfPtDrrkCNcCgHqJLrPhYO7AWvPArl2nD2kp KMU3qFPJkT5RPMQzUykfKxnfOn+xFU6FYYRjmhIuYhdDw4vjuTIqNZjMZ+bQ== Received: from 13289e625de8 (code.ffmpeg.org [188.245.149.3]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id DD77F68EAB6 for ; Wed, 1 Oct 2025 10:01:34 +0300 (EEST) MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Date: Wed, 01 Oct 2025 07:01:34 -0000 Message-ID: <175930209507.69.2371366508694199932@bf249f23a2c8> Message-ID-Hash: N23NIKZFEEF2PWQGUKOCTCKKN4422A4P X-Message-ID-Hash: N23NIKZFEEF2PWQGUKOCTCKKN4422A4P X-MailFrom: code@ffmpeg.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-ffmpeg-devel.ffmpeg.org-0; header-match-ffmpeg-devel.ffmpeg.org-1; header-match-ffmpeg-devel.ffmpeg.org-2; header-match-ffmpeg-devel.ffmpeg.org-3; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list Reply-To: FFmpeg development discussions and patches Subject: [FFmpeg-devel] [PATCH] vf_blend (PR #20634) List-Id: FFmpeg development discussions and patches Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: mkver via ffmpeg-devel Cc: mkver Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Archived-At: List-Archive: List-Post: PR #20634 opened by mkver URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20634 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20634.patch >>From f2717889b4bff014ad8d00a98dc94761ed56c325 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 1 Oct 2025 07:56:49 +0200 Subject: [PATCH 1/2] 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 --- libavfilter/blend_modes.c | 16 ++++++---------- libavfilter/vf_blend_init.h | 16 ++++++---------- 2 files changed, 12 insertions(+), 20 deletions(-) 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; \ } \ } -- 2.49.1 >>From 5c4166f5a2def849a19d698d463af5f8a403f822 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Wed, 1 Oct 2025 08:27:14 +0200 Subject: [PATCH 2/2] 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 --- libavfilter/blend_modes.c | 29 +++++++++++++++++++---------- libavfilter/vf_blend_init.h | 20 ++++++++++---------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/libavfilter/blend_modes.c b/libavfilter/blend_modes.c index 35e365996c..fff9864a04 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 \ No newline at end of file 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; \ -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org