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]
