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

Git pushed a commit to branch master
in repository ffmpeg.

commit 4bf82ad8df504cd73373f0c2e1fa1129a792c997
Author:     Niklas Haas <[email protected]>
AuthorDate: Sat Aug 29 15:24:18 2026 +0200
Commit:     Niklas Haas <[email protected]>
CommitDate: Tue Sep 1 13:15:06 2026 +0200

    avfilter/x86/vf_colordetect: split into offset and non-offset variants
    
    This partially addresses a a performance regression otherwise introduced by
    f37b9a3f, which matters especially for 8-bit content where the default
    threshold value rounds down to an offset of 0.
    
    The numbers are still slower than before because the scalar tail handling
    code is slower by ~200 cycles, since we benchmark across an unaligned
    width.
    
    checkasm:
     - CPU: AMD Ryzen 9 9950X3D 16-Core Processor (00B40F40)
     - Timing source: x86 (rdtsc)
     - Bench duration: 100000 µs per function (460518890 cycles)
     - Random seed: 2935750295
    
    Benchmark results:
      name                                  cycles (vs ref)
      detect_alpha_8_full_c:                7877.4
      detect_alpha_8_full_avx2:             1063.4 ( 7.41x)
      detect_alpha_8_full_avx512icl:         872.1 ( 9.03x)
      detect_alpha_8_full_off_c:            7890.3
      detect_alpha_8_full_off_avx2:         1085.5 ( 7.27x)
      detect_alpha_8_full_off_avx512icl:     873.0 ( 9.04x)
      detect_alpha_16_full_c:               3700.9
      detect_alpha_16_full_avx2:             797.7 ( 4.64x)
      detect_alpha_16_full_avx512icl:        612.1 ( 6.05x)
      detect_alpha_16_full_off_c:           3701.8
      detect_alpha_16_full_off_avx2:         801.2 ( 4.62x)
      detect_alpha_16_full_off_avx512icl:    684.8 ( 5.41x)
    
    Sponsored-by: nxtedition AB
    Signed-off-by: Niklas Haas <[email protected]>
---
 libavfilter/vf_colordetect.c          |  2 +-
 libavfilter/vf_colordetectdsp.h       |  6 ++---
 libavfilter/x86/vf_colordetect.asm    | 44 +++++++++++++++++++++--------------
 libavfilter/x86/vf_colordetect_init.c | 22 ++++++++++++------
 tests/checkasm/vf_colordetect.c       | 22 +++++++++++-------
 5 files changed, 59 insertions(+), 37 deletions(-)

diff --git a/libavfilter/vf_colordetect.c b/libavfilter/vf_colordetect.c
index 4fffaa4968..f98905b6c6 100644
--- a/libavfilter/vf_colordetect.c
+++ b/libavfilter/vf_colordetect.c
@@ -163,7 +163,7 @@ static int config_input(AVFilterLink *inlink)
         atomic_init(&s->detected_alpha, FF_ALPHA_NONE);
     }
 
-    ff_color_detect_dsp_init(&s->dsp, depth, inlink->color_range);
+    ff_color_detect_dsp_init(&s->dsp, depth, s->offset, inlink->color_range);
     return 0;
 }
 
diff --git a/libavfilter/vf_colordetectdsp.h b/libavfilter/vf_colordetectdsp.h
index 5dbbcd1e98..ef81559a6d 100644
--- a/libavfilter/vf_colordetectdsp.h
+++ b/libavfilter/vf_colordetectdsp.h
@@ -52,7 +52,7 @@ typedef struct FFColorDetectDSPContext {
 void ff_color_detect_dsp_init_aarch64(FFColorDetectDSPContext *dsp, int depth,
                                       enum AVColorRange color_range);
 void ff_color_detect_dsp_init_x86(FFColorDetectDSPContext *dsp, int depth,
-                                  enum AVColorRange color_range);
+                                  int offset, enum AVColorRange color_range);
 
 static inline int ff_detect_range_impl_c(const uint8_t *data, ptrdiff_t stride,
                                     ptrdiff_t width, ptrdiff_t height,
@@ -196,7 +196,7 @@ ff_detect_alpha16_limited_c(const uint8_t *color, ptrdiff_t 
color_stride,
 }
 
 static av_cold inline void
-ff_color_detect_dsp_init(FFColorDetectDSPContext *dsp, int depth,
+ff_color_detect_dsp_init(FFColorDetectDSPContext *dsp, int depth, int offset,
                          enum AVColorRange color_range)
 {
     dsp->detect_range = depth > 8 ? ff_detect_range16_c : ff_detect_range_c;
@@ -209,7 +209,7 @@ ff_color_detect_dsp_init(FFColorDetectDSPContext *dsp, int 
depth,
 #if ARCH_AARCH64
     ff_color_detect_dsp_init_aarch64(dsp, depth, color_range);
 #elif ARCH_X86 && HAVE_X86ASM
-    ff_color_detect_dsp_init_x86(dsp, depth, color_range);
+    ff_color_detect_dsp_init_x86(dsp, depth, offset, color_range);
 #endif
 }
 
diff --git a/libavfilter/x86/vf_colordetect.asm 
b/libavfilter/x86/vf_colordetect.asm
index f0e4508c63..593159c35e 100644
--- a/libavfilter/x86/vf_colordetect.asm
+++ b/libavfilter/x86/vf_colordetect.asm
@@ -71,7 +71,7 @@ cglobal detect_range%1, 4, 7, 5, data, stride, width, height, 
mpeg_min, mpeg_max
 
 %define FF_ALPHA_STRAIGHT 0x3
 
-%macro detect_alpha_fn 3 ; suffix, hsuffix, range
+%macro detect_alpha_fn 3 ; suffix, hsuffix, mode
 %if ARCH_X86_64
 cglobal detect_alpha%1_%3, 6, 8, 7, color, color_stride, alpha, alpha_stride, 
width, height, ret, x
 %else
@@ -92,32 +92,36 @@ 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
+    %ifidn %3, full_off
+        vpbroadcast%1 m4, r8m ; offset
+    %endif
 %endif
     mova m6, m3
     xor retd, retd
 .lineloop:
     mov xq, widthq
     .loop:
-    %ifidn %3, full
-        movu m1, [colorq + xq]
-        movu m2, [alphaq + xq]
-        pand m6, m2
-        psubus%1 m1, m4
-        pmaxu%1 m1, m2
-    %else
+    %ifidn %3, limited
         pmovzx%1%2 m1, [colorq + xq]
         pmovzx%1%2 m2, [alphaq + xq]
         pand m6, m2
         pmull%2 m1, m3
         pmull%2 m2, m4
-    %ifidn %1, b
-        psubusw m1, m5
-    %else
-        pmaxud m1, m5
-        psubd m1, m5
-    %endif
+        %ifidn %1, b
+            psubusw m1, m5
+        %else
+            pmaxud m1, m5
+            psubd m1, m5
+        %endif
         pmaxu%2 m1, m2
+    %else
+        movu m1, [colorq + xq]
+        movu m2, [alphaq + xq]
+        pand m6, m2
+        %ifidn %3, full_off
+            psubus%1 m1, m4
+        %endif
+        pmaxu%1 m1, m2
     %endif
     %if cpuflag(avx512)
         vpternlogq m0, m1, m2, 0xF6 ; m0 |= m1 ^ m2
@@ -125,10 +129,10 @@ cglobal detect_alpha%1_%3, 1, 6, 7, color, ret, alpha, x, 
width, height
         pxor m1, m2
         por m0, m1
     %endif
-    %ifidn %3, full
-        add xq, mmsize
-    %else
+    %ifidn %3, limited
         add xq, mmsize >> 1
+    %else
+        add xq, mmsize
     %endif
         jl .loop
 
@@ -171,6 +175,8 @@ detect_range_fn b
 detect_range_fn w
 detect_alpha_fn b, w, full
 detect_alpha_fn w, d, full
+detect_alpha_fn b, w, full_off
+detect_alpha_fn w, d, full_off
 detect_alpha_fn b, w, limited
 detect_alpha_fn w, d, limited
 %endif
@@ -181,6 +187,8 @@ detect_range_fn b
 detect_range_fn w
 detect_alpha_fn b, w, full
 detect_alpha_fn w, d, full
+detect_alpha_fn b, w, full_off
+detect_alpha_fn w, d, full_off
 detect_alpha_fn b, w, limited
 detect_alpha_fn w, d, limited
 %endif
diff --git a/libavfilter/x86/vf_colordetect_init.c 
b/libavfilter/x86/vf_colordetect_init.c
index 4bff4471a1..d763cfa800 100644
--- a/libavfilter/x86/vf_colordetect_init.c
+++ b/libavfilter/x86/vf_colordetect_init.c
@@ -63,6 +63,8 @@ DETECT_RANGE_FUNC(detect_range_avx512icl,   
ff_detect_rangeb_avx512icl, ff_detec
 DETECT_RANGE_FUNC(detect_range16_avx512icl, ff_detect_rangew_avx512icl, 
ff_detect_range16_c, 1, 64)
 DETECT_ALPHA_FUNC(detect_alpha_full_avx512icl,   
ff_detect_alphab_full_avx512icl, ff_detect_alpha_full_c,   0, 64)
 DETECT_ALPHA_FUNC(detect_alpha16_full_avx512icl, 
ff_detect_alphaw_full_avx512icl, ff_detect_alpha16_full_c, 1, 64)
+DETECT_ALPHA_FUNC(detect_alpha_full_off_avx512icl,   
ff_detect_alphab_full_off_avx512icl, ff_detect_alpha_full_c,   0, 64)
+DETECT_ALPHA_FUNC(detect_alpha16_full_off_avx512icl, 
ff_detect_alphaw_full_off_avx512icl, ff_detect_alpha16_full_c, 1, 64)
 DETECT_ALPHA_FUNC(detect_alpha_limited_avx512icl,   
ff_detect_alphab_limited_avx512icl, ff_detect_alpha_limited_c,   0, 64)
 DETECT_ALPHA_FUNC(detect_alpha16_limited_avx512icl, 
ff_detect_alphaw_limited_avx512icl, ff_detect_alpha16_limited_c, 1, 64)
 #endif
@@ -71,31 +73,37 @@ DETECT_RANGE_FUNC(detect_range_avx2,   
ff_detect_rangeb_avx2, ff_detect_range_c,
 DETECT_RANGE_FUNC(detect_range16_avx2, ff_detect_rangew_avx2, 
ff_detect_range16_c, 1, 32)
 DETECT_ALPHA_FUNC(detect_alpha_full_avx2,   ff_detect_alphab_full_avx2, 
ff_detect_alpha_full_c,   0, 32)
 DETECT_ALPHA_FUNC(detect_alpha16_full_avx2, ff_detect_alphaw_full_avx2, 
ff_detect_alpha16_full_c, 1, 32)
+DETECT_ALPHA_FUNC(detect_alpha_full_off_avx2,   
ff_detect_alphab_full_off_avx2, ff_detect_alpha_full_c,   0, 32)
+DETECT_ALPHA_FUNC(detect_alpha16_full_off_avx2, 
ff_detect_alphaw_full_off_avx2, ff_detect_alpha16_full_c, 1, 32)
 DETECT_ALPHA_FUNC(detect_alpha_limited_avx2,   ff_detect_alphab_limited_avx2, 
ff_detect_alpha_limited_c,   0, 32)
 DETECT_ALPHA_FUNC(detect_alpha16_limited_avx2, ff_detect_alphaw_limited_avx2, 
ff_detect_alpha16_limited_c, 1, 32)
 #endif
 
 av_cold void ff_color_detect_dsp_init_x86(FFColorDetectDSPContext *dsp, int 
depth,
-                                          enum AVColorRange color_range)
+                                          int offset, enum AVColorRange 
color_range)
 {
     int cpu_flags = av_get_cpu_flags();
 #if HAVE_AVX2_EXTERNAL
     if (EXTERNAL_AVX2_FAST(cpu_flags)) {
         dsp->detect_range = depth > 8 ? detect_range16_avx2 : 
detect_range_avx2;
-        if (color_range == AVCOL_RANGE_JPEG) {
-            dsp->detect_alpha = depth > 8 ? detect_alpha16_full_avx2 : 
detect_alpha_full_avx2;
-        } else {
+        if (color_range != AVCOL_RANGE_JPEG) {
             dsp->detect_alpha = depth > 8 ? detect_alpha16_limited_avx2 : 
detect_alpha_limited_avx2;
+        } else if (offset) {
+            dsp->detect_alpha = depth > 8 ? detect_alpha16_full_off_avx2 : 
detect_alpha_full_off_avx2;
+        } else {
+            dsp->detect_alpha = depth > 8 ? detect_alpha16_full_avx2 : 
detect_alpha_full_avx2;
         }
     }
 #endif
 #if HAVE_AVX512ICL_EXTERNAL
     if (EXTERNAL_AVX512ICL(cpu_flags)) {
         dsp->detect_range = depth > 8 ? detect_range16_avx512icl : 
detect_range_avx512icl;
-        if (color_range == AVCOL_RANGE_JPEG) {
-            dsp->detect_alpha = depth > 8 ? detect_alpha16_full_avx512icl : 
detect_alpha_full_avx512icl;
-        } else {
+        if (color_range != AVCOL_RANGE_JPEG) {
             dsp->detect_alpha = depth > 8 ? detect_alpha16_limited_avx512icl : 
detect_alpha_limited_avx512icl;
+        } else if (offset) {
+            dsp->detect_alpha = depth > 8 ? detect_alpha16_full_off_avx512icl 
: detect_alpha_full_off_avx512icl;
+        } else {
+            dsp->detect_alpha = depth > 8 ? detect_alpha16_full_avx512icl : 
detect_alpha_full_avx512icl;
         }
     }
 #endif
diff --git a/tests/checkasm/vf_colordetect.c b/tests/checkasm/vf_colordetect.c
index f5739c6567..d16526090f 100644
--- a/tests/checkasm/vf_colordetect.c
+++ b/tests/checkasm/vf_colordetect.c
@@ -32,7 +32,7 @@ static void check_range_detect(int depth)
     const int mpeg_max = 235 << (depth - 8);
 
     FFColorDetectDSPContext dsp = {0};
-    ff_color_detect_dsp_init(&dsp, depth, AVCOL_RANGE_UNSPECIFIED);
+    ff_color_detect_dsp_init(&dsp, depth, 0, AVCOL_RANGE_UNSPECIFIED);
 
     declare_func(int, const uint8_t *, ptrdiff_t, ptrdiff_t, ptrdiff_t, int, 
int);
 
@@ -69,7 +69,7 @@ static void check_range_detect(int depth)
     }
 }
 
-static void check_alpha_detect(int depth, enum AVColorRange range)
+static void check_alpha_detect(int depth, enum AVColorRange range, int offset)
 {
     const int mpeg_min =  16 << (depth - 8);
     const int mpeg_max = 235 << (depth - 8);
@@ -77,16 +77,15 @@ static void check_alpha_detect(int depth, enum AVColorRange 
range)
     const int mpeg_range = mpeg_max - mpeg_min;
     int res_ref, res_new;
 
-    int offset;
     int threshold = checkasm_rand() % FFMIN(HEIGHT, mpeg_min);
     if (range == AVCOL_RANGE_JPEG) {
-        offset = threshold;
+        offset = offset ? FFMAX(threshold, 1) : 0;
     } else {
         offset = alpha_max * (mpeg_min + threshold) + (1 << (depth - 1));
     }
 
     FFColorDetectDSPContext dsp = {0};
-    ff_color_detect_dsp_init(&dsp, depth, range);
+    ff_color_detect_dsp_init(&dsp, depth, offset, range);
 
     declare_func(int, const uint8_t *, ptrdiff_t, const uint8_t *, ptrdiff_t,
                       ptrdiff_t, ptrdiff_t, int p, int q, int k);
@@ -125,7 +124,13 @@ static void check_alpha_detect(int depth, enum 
AVColorRange range)
     if (depth > 8)
         w /= 2;
 
-    if (check_func(dsp.detect_alpha, "detect_alpha_%d_%s", depth, range == 
AVCOL_RANGE_JPEG ? "full" : "limited")) {
+    const char *name;
+    if (range == AVCOL_RANGE_JPEG)
+        name = offset ? "full_off" : "full";
+    else
+        name = "limited";
+
+    if (check_func(dsp.detect_alpha, "detect_alpha_%d_%s", depth, name)) {
         /* Test increasing height, to ensure we hit the placed 0 eventually */
         for (int h = 1; h <= HEIGHT; h++) {
             res_ref = call_ref(luma, STRIDE, alpha, STRIDE, w, h, alpha_max, 
mpeg_range, offset);
@@ -151,8 +156,9 @@ void checkasm_check_colordetect(void)
         check_range_detect(depth);
         report("detect_range_%d", depth);
 
-        check_alpha_detect(depth, AVCOL_RANGE_JPEG);
-        check_alpha_detect(depth, AVCOL_RANGE_MPEG);
+        check_alpha_detect(depth, AVCOL_RANGE_JPEG, 0);
+        check_alpha_detect(depth, AVCOL_RANGE_JPEG, 1);
+        check_alpha_detect(depth, AVCOL_RANGE_MPEG, 1);
         report("detect_alpha_%d", depth);
     }
 }

-- 
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