PR #22906 opened by R-Camacho
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22906
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22906.patch

The first commit moves ff_limiter_init into a header file so checkasm does not 
depend on vf_limiter.o.
The second implements the actual test, using ff_limiter_init.


>From 97035c2c335e52411a4df7bf190035fe8e1d2174 Mon Sep 17 00:00:00 2001
From: Rodrigo Camacho <[email protected]>
Date: Thu, 23 Apr 2026 23:49:13 +0100
Subject: [PATCH 1/2] avfilter/vf_limiter: Move ff_limiter_init into a header

This change allows ff_limiter_init to be inlined
without depending on vf_limiter.o

Signed-off-by: Rodrigo Camacho <[email protected]>
---
 libavfilter/limiter.h         | 14 ++++++++
 libavfilter/vf_limiter.c      | 48 ++------------------------
 libavfilter/vf_limiter_init.h | 65 +++++++++++++++++++++++++++++++++++
 tests/fate/checkasm.mak       |  1 +
 4 files changed, 82 insertions(+), 46 deletions(-)
 create mode 100644 libavfilter/vf_limiter_init.h

diff --git a/libavfilter/limiter.h b/libavfilter/limiter.h
index 54d423d1f4..7c978a35ad 100644
--- a/libavfilter/limiter.h
+++ b/libavfilter/limiter.h
@@ -21,6 +21,7 @@
 
 #include <stddef.h>
 #include <stdint.h>
+#include "avfilter.h"
 
 typedef struct LimiterDSPContext {
     void (*limiter)(const uint8_t *src, uint8_t *dst,
@@ -28,6 +29,19 @@ typedef struct LimiterDSPContext {
                     int w, int h, int min, int max);
 } LimiterDSPContext;
 
+typedef struct LimiterContext {
+    const AVClass *class;
+    int min;
+    int max;
+    int planes;
+    int nb_planes;
+    int linesize[4];
+    int width[4];
+    int height[4];
+
+    LimiterDSPContext dsp;
+} LimiterContext;
+
 void ff_limiter_init_x86(LimiterDSPContext *dsp, int bpp);
 
 #endif /* AVFILTER_LIMITER_H */
diff --git a/libavfilter/vf_limiter.c b/libavfilter/vf_limiter.c
index 4f50ace386..4adfa48078 100644
--- a/libavfilter/vf_limiter.c
+++ b/libavfilter/vf_limiter.c
@@ -16,6 +16,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavfilter/vf_limiter_init.h"
 #include "libavutil/attributes.h"
 #include "libavutil/common.h"
 #include "libavutil/imgutils.h"
@@ -31,19 +32,6 @@ typedef struct ThreadData {
     AVFrame *out;
 } ThreadData;
 
-typedef struct LimiterContext {
-    const AVClass *class;
-    int min;
-    int max;
-    int planes;
-    int nb_planes;
-    int linesize[4];
-    int width[4];
-    int height[4];
-
-    LimiterDSPContext dsp;
-} LimiterContext;
-
 #define OFFSET(x) offsetof(LimiterContext, x)
 #define FLAGS 
AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
 
@@ -87,30 +75,6 @@ static const enum AVPixelFormat pix_fmts[] = {
     AV_PIX_FMT_NONE
 };
 
-#define LIMITER(n, type)                                        \
-static void limiter##n(const uint8_t *ssrc, uint8_t *ddst,      \
-                       ptrdiff_t slinesize, ptrdiff_t dlinesize,\
-                       int w, int h, int min, int max)          \
-{                                                               \
-    const type *src = (const type *)ssrc;                       \
-    type *dst = (type *)ddst;                                   \
-                                                                \
-    dlinesize /= sizeof(type);                                  \
-    slinesize /= sizeof(type);                                  \
-                                                                \
-    for (int y = 0; y < h; y++) {                               \
-        for (int x = 0; x < w; x++) {                           \
-            dst[x] = av_clip(src[x], min, max);                 \
-        }                                                       \
-                                                                \
-        dst += dlinesize;                                       \
-        src += slinesize;                                       \
-    }                                                           \
-}
-
-LIMITER(8,  uint8_t)
-LIMITER(16, uint16_t)
-
 static int config_input(AVFilterLink *inlink)
 {
     AVFilterContext *ctx = inlink->dst;
@@ -134,15 +98,7 @@ static int config_input(AVFilterLink *inlink)
     s->max = FFMIN(s->max, (1 << depth) - 1);
     s->min = FFMIN(s->min, (1 << depth) - 1);
 
-    if (depth == 8) {
-        s->dsp.limiter = limiter8;
-    } else {
-        s->dsp.limiter = limiter16;
-    }
-
-#if ARCH_X86 && HAVE_X86ASM
-    ff_limiter_init_x86(&s->dsp, desc->comp[0].depth);
-#endif
+    ff_limiter_init(s, depth);
 
     return 0;
 }
diff --git a/libavfilter/vf_limiter_init.h b/libavfilter/vf_limiter_init.h
new file mode 100644
index 0000000000..f8e0a3319d
--- /dev/null
+++ b/libavfilter/vf_limiter_init.h
@@ -0,0 +1,65 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFILTER_LIMITER_INIT_H
+#define AVFILTER_LIMITER_INIT_H
+
+#include "config.h"
+#include "libavutil/attributes.h"
+#include "libavutil/common.h"
+#include "limiter.h"
+
+#define LIMITER(n, type)                                        \
+static void limiter##n(const uint8_t *ssrc, uint8_t *ddst,      \
+                       ptrdiff_t slinesize, ptrdiff_t dlinesize,\
+                       int w, int h, int min, int max)          \
+{                                                               \
+    const type *src = (const type *)ssrc;                       \
+    type *dst = (type *)ddst;                                   \
+                                                                \
+    dlinesize /= sizeof(type);                                  \
+    slinesize /= sizeof(type);                                  \
+                                                                \
+    for (int y = 0; y < h; y++) {                               \
+        for (int x = 0; x < w; x++) {                           \
+            dst[x] = av_clip(src[x], min, max);                 \
+        }                                                       \
+                                                                \
+        dst += dlinesize;                                       \
+        src += slinesize;                                       \
+    }                                                           \
+}
+
+LIMITER(8,  uint8_t)
+LIMITER(16, uint16_t)
+
+static av_unused void ff_limiter_init(LimiterContext *s, int depth)
+{
+    if (depth == 8) {
+        s->dsp.limiter = limiter8;
+    } else {
+        s->dsp.limiter = limiter16;
+    }
+
+#if ARCH_X86 && HAVE_X86ASM
+    ff_limiter_init_x86(&s->dsp, depth);
+#endif
+
+}
+
+#endif /* AVFILTER_LIMITER_INIT_H */
diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak
index b7392fa745..9c513bca55 100644
--- a/tests/fate/checkasm.mak
+++ b/tests/fate/checkasm.mak
@@ -82,6 +82,7 @@ FATE_CHECKASM = fate-checkasm-aacencdsp                       
          \
                 fate-checkasm-vf_gblur                                  \
                 fate-checkasm-vf_hflip                                  \
                 fate-checkasm-vf_idet                                   \
+                               fate-checkasm-vf_limiter                        
        \
                 fate-checkasm-vf_nlmeans                                \
                 fate-checkasm-vf_threshold                              \
                 fate-checkasm-vf_sobel                                  \
-- 
2.52.0


>From a2e55d84c998e10687451ae0d407aaea075ebbdb Mon Sep 17 00:00:00 2001
From: Rodrigo Camacho <[email protected]>
Date: Thu, 23 Apr 2026 23:56:17 +0100
Subject: [PATCH 2/2] tests/checkasm: add test for vf_limiter

Signed-off-by: Rodrigo Camacho <[email protected]>
---
 tests/checkasm/Makefile     |  1 +
 tests/checkasm/checkasm.c   |  3 ++
 tests/checkasm/checkasm.h   |  1 +
 tests/checkasm/vf_limiter.c | 75 +++++++++++++++++++++++++++++++++++++
 4 files changed, 80 insertions(+)
 create mode 100644 tests/checkasm/vf_limiter.c

diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile
index 55d2527047..4a23c16578 100644
--- a/tests/checkasm/Makefile
+++ b/tests/checkasm/Makefile
@@ -76,6 +76,7 @@ AVFILTEROBJS-$(CONFIG_FSPP_FILTER)       += vf_fspp.o
 AVFILTEROBJS-$(CONFIG_GBLUR_FILTER)      += vf_gblur.o
 AVFILTEROBJS-$(CONFIG_HFLIP_FILTER)      += vf_hflip.o
 AVFILTEROBJS-$(CONFIG_IDET_FILTER)       += vf_idet.o
+AVFILTEROBJS-$(CONFIG_LIMITER_FILTER)    += vf_limiter.o
 AVFILTEROBJS-$(CONFIG_THRESHOLD_FILTER)  += vf_threshold.o
 AVFILTEROBJS-$(CONFIG_NLMEANS_FILTER)    += vf_nlmeans.o
 AVFILTEROBJS-$(CONFIG_SOBEL_FILTER)      += vf_convolution.o
diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index e863ff6eed..99fb6130da 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -342,6 +342,9 @@ static const struct {
     #if CONFIG_NLMEANS_FILTER
         { "vf_nlmeans", checkasm_check_nlmeans },
     #endif
+    #if CONFIG_LIMITER_FILTER
+        { "vf_limiter", checkasm_check_vf_limiter },
+    #endif
     #if CONFIG_THRESHOLD_FILTER
         { "vf_threshold", checkasm_check_vf_threshold },
     #endif
diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h
index 72a1404163..6dd09b8939 100644
--- a/tests/checkasm/checkasm.h
+++ b/tests/checkasm/checkasm.h
@@ -162,6 +162,7 @@ void checkasm_check_vf_eq(void);
 void checkasm_check_vf_fspp(void);
 void checkasm_check_vf_gblur(void);
 void checkasm_check_vf_hflip(void);
+void checkasm_check_vf_limiter(void);
 void checkasm_check_vf_threshold(void);
 void checkasm_check_vf_sobel(void);
 void checkasm_check_vp3dsp(void);
diff --git a/tests/checkasm/vf_limiter.c b/tests/checkasm/vf_limiter.c
new file mode 100644
index 0000000000..e191bb9614
--- /dev/null
+++ b/tests/checkasm/vf_limiter.c
@@ -0,0 +1,75 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "checkasm.h"
+#include "libavfilter/limiter.h"
+#include "libavfilter/vf_limiter_init.h"
+#include "libavutil/mem_internal.h"
+#include <stddef.h>
+#include <stdint.h>
+
+#define WIDTH  256
+#define HEIGHT 16
+#define WIDTH_PADDED (WIDTH + 32)
+
+static void check_limiter(int depth)
+{
+    LOCAL_ALIGNED_32(uint8_t, src,     [HEIGHT * WIDTH_PADDED]);
+    LOCAL_ALIGNED_32(uint8_t, dst_ref, [HEIGHT * WIDTH_PADDED]);
+    LOCAL_ALIGNED_32(uint8_t, dst_new, [HEIGHT * WIDTH_PADDED]);
+    
+    declare_func(void, const uint8_t *, uint8_t *,
+                 ptrdiff_t, ptrdiff_t, int, int, int, int);
+    
+    memset(dst_ref, 0, HEIGHT * WIDTH_PADDED);
+    memset(dst_new, 0, HEIGHT * WIDTH_PADDED);
+    memset(src, 0, HEIGHT * WIDTH_PADDED);
+    for (int y = 0; y < HEIGHT; y++) {
+        for (int x = 0; x < WIDTH; x++)
+            src[y * WIDTH_PADDED + x] = rnd() & 0xFF;
+    }
+
+    const int min =  16 << (depth - 8);
+    const int max = 235 << (depth - 8);
+
+    int w = WIDTH;
+    if (depth == 16)
+        w /= 2;
+
+    LimiterContext s;
+    ff_limiter_init(&s, depth);
+
+    if (check_func(s.dsp.limiter, "limiter%d", depth)) {
+        call_ref(src, dst_ref, WIDTH_PADDED, WIDTH_PADDED, w, HEIGHT, min, 
max);
+        call_new(src, dst_new, WIDTH_PADDED, WIDTH_PADDED, w, HEIGHT, min, 
max);
+
+        if (memcmp(dst_ref, dst_new, HEIGHT * WIDTH_PADDED))
+            fail();
+
+        bench_new(src, dst_new, WIDTH_PADDED, WIDTH_PADDED, w, HEIGHT, min, 
max);
+    }
+}
+
+void checkasm_check_vf_limiter(void)
+{
+    check_limiter(8);
+    report("limiter8");
+
+    check_limiter(16);
+    report("limiter16");
+}
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to