This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit d6820fb8b3b49a7b2cc3fb5d3b379745ebcc97b9
Author:     Niklas Haas <[email protected]>
AuthorDate: Mon Aug 17 12:29:59 2026 +0200
Commit:     Niklas Haas <[email protected]>
CommitDate: Tue Sep 1 13:15:06 2026 +0200

    avfilter/vf_colordetect: add support for full range alpha offset
    
    This allows us to add a threshold for alpha comparisons to the full range
    path as well.
    
    The AArch64 changes were LLM-assisted, since I'm not familiar with that
    architecture. However, the logic checks out to me.
    
    Also adjusts the checkasm test to make sure there are no rounding 
differences
    between the C and assembly implementations. Tested correct across 100k seeds
    on x86.
    
    checkasm:
     - CPU: AMD Ryzen 9 9950X3D 16-Core Processor (00B40F40)
     - Timing source: x86 (rdtsc)
     - Bench duration: 100000 µs per function (432788090 cycles)
     - Random seed: 4076092999
    
    Benchmark results: (old)
      name                              cycles (vs ref)
      detect_alpha_8_full_c:            4670.7
      detect_alpha_8_full_avx2:          856.6 ( 5.45x)
      detect_alpha_8_full_avx512icl:     667.5 ( 7.00x)
      detect_alpha_16_full_c:           2705.7
      detect_alpha_16_full_avx2:         693.1 ( 3.90x)
      detect_alpha_16_full_avx512icl:    546.4 ( 4.94x)
    
    Benchmark results: (new)
      name                              cycles (vs ref)
      detect_alpha_8_full_c:            7988.5
      detect_alpha_8_full_avx2:         1078.0 ( 7.41x)
      detect_alpha_8_full_avx512icl:     876.7 ( 9.11x)
      detect_alpha_16_full_c:           3734.7
      detect_alpha_16_full_avx2:         814.6 ( 4.58x)
      detect_alpha_16_full_avx512icl:    613.8 ( 6.08x)
    
    Sponsored-by: nxtedition AB
    Signed-off-by: Niklas Haas <[email protected]>
---
 libavfilter/aarch64/vf_colordetect_neon.S | 12 ++++++++++++
 libavfilter/vf_colordetect.c              |  6 +++++-
 libavfilter/vf_colordetectdsp.h           |  4 ++--
 libavfilter/x86/vf_colordetect.asm        |  2 ++
 tests/checkasm/vf_colordetect.c           | 25 +++++++++++++++++++------
 5 files changed, 40 insertions(+), 9 deletions(-)

diff --git a/libavfilter/aarch64/vf_colordetect_neon.S 
b/libavfilter/aarch64/vf_colordetect_neon.S
index f3cca16fed..ada21d4ba4 100644
--- a/libavfilter/aarch64/vf_colordetect_neon.S
+++ b/libavfilter/aarch64/vf_colordetect_neon.S
@@ -177,13 +177,17 @@ endfunc
  * x4: ptrdiff_t width,
  * x5: ptrdiff_t height,
  * w6: int alpha_max,
+ * w7: int mpeg_range (unused)
+ * [sp]: int offset
  */
 function ff_detect_alpha_full_neon, export=1
+        ldr             w13, [sp]
         ands            x7, x4, #15             // width % 16
         bic             x8, x4, #15             // width / 16 * 16
         movi            v0.16b, #0
         movi            v1.16b, #255
         dup             v2.16b, w6              // alpha_max
+        dup             v18.16b, w13            // offset
         sub             x1, x1, x8              // color_stride - aligned_width
         sub             x3, x3, x8              // alpha_stride - aligned_width
         b.eq            1f
@@ -197,6 +201,7 @@ function ff_detect_alpha_full_neon, export=1
         ldr             q5, [x0], #16
         ldr             q6, [x2], #16
         subs            x12, x12, #16
+        uqsub           v5.16b, v5.16b, v18.16b // color - offset
         cmhi            v7.16b, v5.16b, v6.16b
         cmeq            v16.16b, v6.16b, v2.16b
         orr             v0.16b, v0.16b, v7.16b
@@ -207,6 +212,7 @@ function ff_detect_alpha_full_neon, export=1
         // handle loop tail
         ldr             q5, [x0]
         ldr             q6, [x2]
+        uqsub           v5.16b, v5.16b, v18.16b // color - offset
         cmhi            v7.16b, v5.16b, v6.16b
         cmeq            v16.16b, v6.16b, v2.16b
         and             v7.16b, v7.16b, v3.16b
@@ -242,13 +248,17 @@ endfunc
  * x4: ptrdiff_t width,
  * x5: ptrdiff_t height,
  * w6: int alpha_max,
+ * w7: int mpeg_range (unused)
+ * [sp]: int offset
  */
 function ff_detect_alpha16_full_neon, export=1
+        ldr             w13, [sp]
         ands            x7, x4, #7              // width % 8
         bic             x8, x4, #7              // width / 8 * 8
         movi            v0.8h, #0
         movi            v1.16b, #255
         dup             v2.8h, w6               // alpha_max
+        dup             v18.8h, w13             // offset
         sub             x1, x1, x8, lsl #1      // color_stride - 
(aligned_width * 2)
         sub             x3, x3, x8, lsl #1      // alpha_stride - 
(aligned_width * 2)
         b.eq            1f
@@ -262,6 +272,7 @@ function ff_detect_alpha16_full_neon, export=1
         ldr             q5, [x0], #16
         ldr             q6, [x2], #16
         subs            x12, x12, #8
+        uqsub           v5.8h, v5.8h, v18.8h    // color - offset
         cmhi            v7.8h, v5.8h, v6.8h
         cmeq            v16.8h, v6.8h, v2.8h
         orr             v0.16b, v0.16b, v7.16b
@@ -272,6 +283,7 @@ function ff_detect_alpha16_full_neon, export=1
         // handle loop tail
         ldr             q5, [x0]
         ldr             q6, [x2]
+        uqsub           v5.8h, v5.8h, v18.8h    // color - offset
         cmhi            v7.8h, v5.8h, v6.8h
         cmeq            v16.8h, v6.8h, v2.8h
         and             v7.16b, v7.16b, v3.16b
diff --git a/libavfilter/vf_colordetect.c b/libavfilter/vf_colordetect.c
index 397e278110..140ff73666 100644
--- a/libavfilter/vf_colordetect.c
+++ b/libavfilter/vf_colordetect.c
@@ -170,10 +170,14 @@ static int detect_alpha(AVFilterContext *ctx, void *arg,
      *
      * We subtract an additional offset of (1 << (depth - 1)) to account for
      * rounding errors in the value of `x`.
+     *
+     * For full range input this degenerates to `x > a`, so the offset is 0.
      */
     const int alpha_max = (1 << s->depth) - 1;
     const int mpeg_range = s->mpeg_max - s->mpeg_min;
-    const int offset = alpha_max * s->mpeg_min + (1 << (s->depth - 1));
+    int offset = alpha_max * s->mpeg_min + (1 << (s->depth - 1));
+    if (ctx->inputs[0]->color_range == AVCOL_RANGE_JPEG)
+        offset = 0;
 
     int ret = 0;
     for (int i = 0; i < nb_planes; i++) {
diff --git a/libavfilter/vf_colordetectdsp.h b/libavfilter/vf_colordetectdsp.h
index ca4727b589..5dbbcd1e98 100644
--- a/libavfilter/vf_colordetectdsp.h
+++ b/libavfilter/vf_colordetectdsp.h
@@ -119,7 +119,7 @@ ff_detect_alpha_full_c(const uint8_t *color, ptrdiff_t 
color_stride,
     while (height--) {
         uint8_t straight = 0;
         for (int x = 0; x < width; x++) {
-            straight  |= color[x] > alpha[x];
+            straight |= color[x] > alpha[x] + offset;
             transparent |= alpha[x] != alpha_max;
         }
         if (straight)
@@ -163,7 +163,7 @@ ff_detect_alpha16_full_c(const uint8_t *color, ptrdiff_t 
color_stride,
         const uint16_t *alpha16 = (const uint16_t *) alpha;
         uint8_t straight = 0;
         for (int x = 0; x < width; x++) {
-            straight  |= color16[x] > alpha16[x];
+            straight |= color16[x] > alpha16[x] + offset;
             transparent |= alpha16[x] != alpha_max;
         }
         if (straight)
diff --git a/libavfilter/x86/vf_colordetect.asm 
b/libavfilter/x86/vf_colordetect.asm
index 7a96b6933c..f0e4508c63 100644
--- a/libavfilter/x86/vf_colordetect.asm
+++ b/libavfilter/x86/vf_colordetect.asm
@@ -92,6 +92,7 @@ cglobal detect_alpha%1_%3, 1, 6, 7, color, ret, alpha, x, 
width, height
     vpbroadcast%2 m5, r8m ; offset
 %else
     vpbroadcast%1 m3, r6m ; alpha_max
+    vpbroadcast%1 m4, r8m ; offset
 %endif
     mova m6, m3
     xor retd, retd
@@ -102,6 +103,7 @@ cglobal detect_alpha%1_%3, 1, 6, 7, color, ret, alpha, x, 
width, height
         movu m1, [colorq + xq]
         movu m2, [alphaq + xq]
         pand m6, m2
+        psubus%1 m1, m4
         pmaxu%1 m1, m2
     %else
         pmovzx%1%2 m1, [colorq + xq]
diff --git a/tests/checkasm/vf_colordetect.c b/tests/checkasm/vf_colordetect.c
index 471f77fcc7..f5739c6567 100644
--- a/tests/checkasm/vf_colordetect.c
+++ b/tests/checkasm/vf_colordetect.c
@@ -75,9 +75,16 @@ static void check_alpha_detect(int depth, enum AVColorRange 
range)
     const int mpeg_max = 235 << (depth - 8);
     const int alpha_max = (1 << depth) - 1;
     const int mpeg_range = mpeg_max - mpeg_min;
-    const int offset = alpha_max * mpeg_min + (1 << (depth - 1));
     int res_ref, res_new;
 
+    int offset;
+    int threshold = checkasm_rand() % FFMIN(HEIGHT, mpeg_min);
+    if (range == AVCOL_RANGE_JPEG) {
+        offset = threshold;
+    } else {
+        offset = alpha_max * (mpeg_min + threshold) + (1 << (depth - 1));
+    }
+
     FFColorDetectDSPContext dsp = {0};
     ff_color_detect_dsp_init(&dsp, depth, range);
 
@@ -89,13 +96,19 @@ static void check_alpha_detect(int depth, enum AVColorRange 
range)
     memset(luma,  0x80, HEIGHT * STRIDE);
     memset(alpha, 0xF0, HEIGHT * STRIDE);
 
-    /* Try and force overflow */
+    /* Try and force overflow and edge cases */
     if (depth > 8 && range == AVCOL_RANGE_MPEG) {
-        ((uint16_t *) luma)[0] = 235 << (depth - 8);
-        ((uint16_t *) luma)[1] =  16 << (depth - 8);
+        for (int i = 0; i < threshold; i++) {
+            uint16_t *line = (uint16_t *) (luma + i * STRIDE);
+            line[0] = (235 << (depth - 8)) + i;
+            line[1] = ( 16 << (depth - 8)) - i;
+        }
     } else {
-        luma[0] = 235;
-        luma[1] = 16;
+        for (int i = 0; i < threshold; i++) {
+            uint8_t *line = luma + i * STRIDE;
+            line[0] = 235 + i;
+            line[1] = 16 - i;
+        }
     }
 
     /* Place an out-of-range value in a random position near the center */

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to