History

lavc/aarch64: motion estimation functions in neon

- ff_pix_abs16_neon - ff_pix_abs16_xy2_neon In direct micro benchmarks of these ff functions verses their C implementations, these functions performed as follows on AWS Graviton 3. ff_pix_abs16_neon: pix_abs_0_0_c: 141.1 pix_abs_0_0_neon: 19.6 ff_pix_abs16_xy2_neon: pix_abs_0_3_c: 269.1 pix_abs_0_3_neon: 39.3 Tested with: ./tests/checkasm/checkasm --test=motion --bench --disable-linux-perf

Swinney, Jonathan committed 4 years ago

Commit c471cc71 parent 20e2aa910 files · +407 −1Browse files

Unified · Split

10 files
  1. libavcodec/aarch64/Makefile +2 −0
  2. libavcodec/aarch64/me_cmp_init_aarch64.c +39 −0
  3. libavcodec/aarch64/me_cmp_neon.S +205 −0
  4. libavcodec/me_cmp.c +3 −1
  5. libavcodec/me_cmp.h +1 −0
  6. tests/checkasm/Makefile +1 −0
  7. tests/checkasm/checkasm.c +3 −0
  8. tests/checkasm/checkasm.h +1 −0
  9. tests/checkasm/motion.c +151 −0
  10. tests/fate/checkasm.mak +1 −0
libavcodec/aarch64/Makefile+2−0
@@ -7,6 +7,7 @@ OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_init.o · 6 unmodified lines
77 OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_init_aarch64.o
88 OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_init_aarch64.o
99 OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_init_aarch64.o
10+OBJS-$(CONFIG_ME_CMP) += aarch64/me_cmp_init_aarch64.o
1011 OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_init.o
1112 OBJS-$(CONFIG_NEON_CLOBBER_TEST) += aarch64/neontest.o
1213 OBJS-$(CONFIG_PIXBLOCKDSP) += aarch64/pixblockdsp_init_aarch64.o
@@ -47,6 +48,7 @@ NEON-OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_neon.o · 34 unmodified lines
4748 NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_neon.o \
4849 aarch64/simple_idct_neon.o
4950 NEON-OBJS-$(CONFIG_MDCT) += aarch64/mdct_neon.o
51+NEON-OBJS-$(CONFIG_ME_CMP) += aarch64/me_cmp_neon.o
5052 NEON-OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_neon.o
5153 NEON-OBJS-$(CONFIG_PIXBLOCKDSP) += aarch64/pixblockdsp_neon.o
5254 NEON-OBJS-$(CONFIG_VC1DSP) += aarch64/vc1dsp_neon.o
libavcodec/aarch64/me_cmp_init_aarch64.c+39−0
@@ -0,0 +1,39 @@
1+/*
2+ * This file is part of FFmpeg.
3+ *
4+ * FFmpeg is free software; you can redistribute it and/or
5+ * modify it under the terms of the GNU Lesser General Public
6+ * License as published by the Free Software Foundation; either
7+ * version 2.1 of the License, or (at your option) any later version.
8+ *
9+ * FFmpeg is distributed in the hope that it will be useful,
10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+ * Lesser General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU Lesser General Public
15+ * License along with FFmpeg; if not, write to the Free Software
16+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17+ */
18+
19+#include <stdint.h>
20+
21+#include "config.h"
22+#include "libavutil/attributes.h"
23+#include "libavutil/aarch64/cpu.h"
24+#include "libavcodec/mpegvideo.h"
25+
26+int ff_pix_abs16_neon(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2,
27+ ptrdiff_t stride, int h);
28+int ff_pix_abs16_xy2_neon(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2,
29+ ptrdiff_t stride, int h);
30+
31+av_cold void ff_me_cmp_init_aarch64(MECmpContext *c, AVCodecContext *avctx)
32+{
33+ int cpu_flags = av_get_cpu_flags();
34+
35+ if (have_neon(cpu_flags)) {
36+ c->pix_abs[0][0] = ff_pix_abs16_neon;
37+ c->pix_abs[0][3] = ff_pix_abs16_xy2_neon;
38+ }
39+}
libavcodec/aarch64/me_cmp_neon.S+205−0
@@ -0,0 +1,205 @@
1+/*
2+ * Copyright (c) 2022 Jonathan Swinney <jswinney@amazon.com>
3+ *
4+ * This file is part of FFmpeg.
5+ *
6+ * FFmpeg is free software; you can redistribute it and/or
7+ * modify it under the terms of the GNU Lesser General Public
8+ * License as published by the Free Software Foundation; either
9+ * version 2.1 of the License, or (at your option) any later version.
10+ *
11+ * FFmpeg is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+ * Lesser General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU Lesser General Public
17+ * License along with FFmpeg; if not, write to the Free Software
18+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19+ */
20+
21+#include "libavutil/aarch64/asm.S"
22+
23+function ff_pix_abs16_neon, export=1
24+ // x0 unused
25+ // x1 uint8_t *pix1
26+ // x2 uint8_t *pix2
27+ // x3 ptrdiff_t stride
28+ // w4 int h
29+ cmp w4, #4 // if h < 4, jump to completion section
30+ movi v18.4S, #0 // clear result accumulator
31+ b.lt 2f
32+1:
33+ ld1 {v0.16b}, [x1], x3 // load pix1
34+ ld1 {v4.16b}, [x2], x3 // load pix2
35+ ld1 {v1.16b}, [x1], x3 // load pix1
36+ ld1 {v5.16b}, [x2], x3 // load pix2
37+ uabdl v16.8h, v0.8b, v4.8b // absolute difference accumulate
38+ uabdl2 v17.8h, v0.16b, v4.16b
39+ ld1 {v2.16b}, [x1], x3 // load pix1
40+ ld1 {v6.16b}, [x2], x3 // load pix2
41+ uabal v16.8h, v1.8b, v5.8b // absolute difference accumulate
42+ uabal2 v17.8h, v1.16b, v5.16b
43+ ld1 {v3.16b}, [x1], x3
44+ ld1 {v7.16b}, [x2], x3
45+ uabal v16.8h, v2.8b, v6.8b
46+ uabal2 v17.8h, v2.16b, v6.16b
47+ sub w4, w4, #4 // h -= 4
48+ uabal v16.8h, v3.8b, v7.8b
49+ uabal2 v17.8h, v3.16b, v7.16b
50+ cmp w4, #4 // if h >= 4, loop
51+ add v16.8h, v16.8h, v17.8h
52+ uaddlv s16, v16.8h // add up everything in v16 accumulator
53+ add d18, d16, d18 // add to the end result register
54+
55+ b.ge 1b
56+ cbnz w4, 2f // if iterations remain, jump to completion section
57+
58+ fmov w0, s18 // copy result to general purpose register
59+ ret
60+
61+2:
62+ ld1 {v0.16b}, [x1], x3 // load pix1
63+ ld1 {v4.16b}, [x2], x3 // load pix2
64+ uabdl v16.8h, v0.8b, v4.8b // absolute difference accumulate
65+ uabal2 v16.8h, v0.16b, v4.16b
66+ subs w4, w4, #1 // h -= 1
67+ addv h16, v16.8h // add up v16
68+ add d18, d16, d18 // add to result
69+ b.ne 2b
70+
71+ fmov w0, s18 // copy result to general purpose register
72+ ret
73+endfunc
74+
75+function ff_pix_abs16_xy2_neon, export=1
76+ // x0 unused
77+ // x1 uint8_t *pix1
78+ // x2 uint8_t *pix2
79+ // x3 ptrdiff_t stride
80+ // w4 int h
81+
82+ add x5, x2, x3 // use x5 to hold uint8_t *pix3
83+ movi v0.2d, #0 // initialize the result register
84+
85+ // Load initial pix2 values for either the unrolled version or completion version.
86+ ldur q4, [x2, #1] // load pix2+1
87+ ldr q3, [x2] // load pix2
88+ uaddl v2.8h, v4.8b, v3.8b // pix2 + pix2+1 0..7
89+ uaddl2 v3.8h, v4.16b, v3.16b // pix2 + pix2+1 8..15
90+ cmp w4, #4 // if h < 4 jump to the completion version
91+ b.lt 2f
92+1:
93+ // This is an unrolled implementation. It completes 4 iterations of the C for each branch.
94+ // In each iteration, pix2[i+1] == pix3[i]. This means we need only three loads per iteration,
95+ // plus two at the beginning to start.
96+ ldur q5, [x5, #1] // load pix3+1
97+ ld1 {v4.16b}, [x5], x3 // load pix3
98+ ld1 {v1.16b}, [x1], x3 // load pix1
99+
100+ ldur q7, [x5, #1] // load pix3+1
101+ ld1 {v6.16b}, [x5], x3 // load pix3
102+ ld1 {v16.16b}, [x1], x3 // load pix1
103+
104+ ldur q19, [x5, #1] // load pix3+1
105+ ld1 {v18.16b}, [x5], x3 // load pix3
106+ ld1 {v17.16b}, [x1], x3 // load pix1
107+
108+ ldur q22, [x5, #1] // load pix3+1
109+ ld1 {v21.16b}, [x5], x3 // load pix3
110+ ld1 {v20.16b}, [x1], x3 // load pix1
111+
112+ // These blocks compute the average: avg(pix2[n], pix2[n+1], pix3[n], pix3[n+1])
113+ uaddl v30.8h, v4.8b, v5.8b // pix3 + pix3+1 0..7
114+ uaddl2 v31.8h, v4.16b, v5.16b // pix3 + pix3+1 8..15
115+ add v23.8h, v2.8h, v30.8h // add up 0..7, using pix2 + pix2+1 values from previous iteration
116+ add v24.8h, v3.8h, v31.8h // add up 8..15, using pix2 + pix2+1 values from previous iteration
117+ rshrn v23.8b, v23.8h, #2 // shift right 2 0..7 (rounding shift right)
118+ rshrn2 v23.16b, v24.8h, #2 // shift right 2 8..15
119+
120+ uaddl v2.8h, v6.8b, v7.8b // pix3 + pix3+1 0..7
121+ uaddl2 v3.8h, v6.16b, v7.16b // pix3 + pix3+1 8..15
122+ add v26.8h, v30.8h, v2.8h // add up 0..7, using pix2 + pix2+1 values from pix3 above
123+ add v27.8h, v31.8h, v3.8h // add up 8..15, using pix2 + pix2+1 values from pix3 above
124+ rshrn v26.8b, v26.8h, #2 // shift right 2 0..7 (rounding shift right)
125+ rshrn2 v26.16b, v27.8h, #2 // shift right 2 8..15
126+
127+ uaddl v4.8h, v18.8b, v19.8b // pix3 + pix3+1 0..7
128+ uaddl2 v5.8h, v18.16b, v19.16b // pix3 + pix3+1 8..15
129+ add v28.8h, v2.8h, v4.8h // add up 0..7, using pix2 + pix2+1 values from pix3 above
130+ add v29.8h, v3.8h, v5.8h // add up 8..15, using pix2 + pix2+1 values from pix3 above
131+ rshrn v28.8b, v28.8h, #2 // shift right 2 0..7 (rounding shift right)
132+ rshrn2 v28.16b, v29.8h, #2 // shift right 2 8..15
133+
134+ uaddl v2.8h, v21.8b, v22.8b // pix3 + pix3+1 0..7
135+ uaddl2 v3.8h, v21.16b, v22.16b // pix3 + pix3+1 8..15
136+ add v30.8h, v4.8h, v2.8h // add up 0..7, using pix2 + pix2+1 values from pix3 above
137+ add v31.8h, v5.8h, v3.8h // add up 8..15, using pix2 + pix2+1 values from pix3 above
138+ rshrn v30.8b, v30.8h, #2 // shift right 2 0..7 (rounding shift right)
139+ rshrn2 v30.16b, v31.8h, #2 // shift right 2 8..15
140+
141+ // Averages are now stored in these registers:
142+ // v23, v16, v28, v30
143+ // pix1 values in these registers:
144+ // v1, v16, v17, v20
145+ // available:
146+ // v4, v5, v7, v18, v19, v24, v25, v27, v29, v31
147+
148+ sub w4, w4, #4 // h -= 4
149+
150+ // Using absolute-difference instructions instead of absolute-difference-accumulate allows
151+ // us to keep the results in 16b vectors instead of widening values with twice the instructions.
152+ // This approach also has fewer data dependencies, allowing better instruction level parallelism.
153+ uabd v4.16b, v1.16b, v23.16b // absolute difference 0..15, i=0
154+ uabd v5.16b, v16.16b, v26.16b // absolute difference 0..15, i=1
155+ uabd v6.16b, v17.16b, v28.16b // absolute difference 0..15, i=2
156+ uabd v7.16b, v20.16b, v30.16b // absolute difference 0..15, i=3
157+
158+ cmp w4, #4 // loop if h >= 4
159+
160+ // Now add up all the values in each vector, v4-v7 with widening adds
161+ uaddl v19.8h, v4.8b, v5.8b
162+ uaddl2 v18.8h, v4.16b, v5.16b
163+ uaddl v4.8h, v6.8b, v7.8b
164+ uaddl2 v5.8h, v6.16b, v7.16b
165+ add v4.8h, v4.8h, v5.8h
166+ add v4.8h, v4.8h, v18.8h
167+ add v4.8h, v4.8h, v19.8h
168+ uaddlv s4, v4.8h // finish adding up accumulated values
169+ add d0, d0, d4 // add the value to the top level accumulator
170+
171+ b.ge 1b
172+ cbnz w4, 2f // if iterations remain jump to completion section
173+
174+ fmov w0, s0 // copy result to general purpose register
175+ ret
176+2:
177+ // v2 and v3 are set either at the end of this loop or at from the unrolled version
178+ // which branches here to complete iterations when h % 4 != 0.
179+ ldur q5, [x5, #1] // load pix3+1
180+ ld1 {v4.16b}, [x5], x3 // load pix3
181+ ld1 {v1.16b}, [x1], x3 // load pix1
182+ subs w4, w4, #1 // decrement h
183+
184+ uaddl v18.8h, v4.8b, v5.8b // pix3 + pix3+1 0..7
185+ uaddl2 v19.8h, v4.16b, v5.16b // pix3 + pix3+1 8..15
186+ add v16.8h, v2.8h, v18.8h // add up 0..7, using pix2 + pix2+1 values from previous iteration
187+ add v17.8h, v3.8h, v19.8h // add up 8..15, using pix2 + pix2+1 values from previous iteration
188+ // divide by 4 to compute the average of values summed above
189+ urshr v16.8h, v16.8h, #2 // shift right by 2 0..7 (rounding shift right)
190+ urshr v17.8h, v17.8h, #2 // shift right by 2 8..15
191+
192+ uxtl2 v8.8h, v1.16b // 8->16 bits pix1 8..15
193+ uxtl v1.8h, v1.8b // 8->16 bits pix1 0..7
194+
195+ uabd v6.8h, v1.8h, v16.8h // absolute difference 0..7
196+ uaba v6.8h, v8.8h, v17.8h // absolute difference accumulate 8..15
197+ mov v2.16b, v18.16b // pix3 -> pix2
198+ mov v3.16b, v19.16b // pix3+1 -> pix2+1
199+ uaddlv s6, v6.8h // add up accumulator in v6
200+ add d0, d0, d6 // add to the final result
201+
202+ b.ne 2b // loop if h > 0
203+ fmov w0, s0 // copy result to general purpose register
204+ ret
205+endfunc
libavcodec/me_cmp.c+3−1
@@ -1061,7 +1061,9 @@ av_cold void ff_me_cmp_init(MECmpContext *c, AVCodecContext *avctx) · 1060 unmodified lines
10611061 ff_dsputil_init_dwt(c);
10621062 #endif
10631063
1064−#if ARCH_ALPHA
1064+#if ARCH_AARCH64
1065+ ff_me_cmp_init_aarch64(c, avctx);
1066+#elif ARCH_ALPHA
10651067 ff_me_cmp_init_alpha(c, avctx);
10661068 #elif ARCH_ARM
10671069 ff_me_cmp_init_arm(c, avctx);
libavcodec/me_cmp.h+1−0
@@ -80,6 +80,7 @@ typedef struct MECmpContext { · 79 unmodified lines
8080 } MECmpContext;
8181
8282 void ff_me_cmp_init(MECmpContext *c, AVCodecContext *avctx);
83+void ff_me_cmp_init_aarch64(MECmpContext *c, AVCodecContext *avctx);
8384 void ff_me_cmp_init_alpha(MECmpContext *c, AVCodecContext *avctx);
8485 void ff_me_cmp_init_arm(MECmpContext *c, AVCodecContext *avctx);
8586 void ff_me_cmp_init_ppc(MECmpContext *c, AVCodecContext *avctx);
tests/checkasm/Makefile+1−0
@@ -12,6 +12,7 @@ AVCODECOBJS-$(CONFIG_H264QPEL) += h264qpel.o · 11 unmodified lines
1212 AVCODECOBJS-$(CONFIG_IDCTDSP) += idctdsp.o
1313 AVCODECOBJS-$(CONFIG_LLVIDDSP) += llviddsp.o
1414 AVCODECOBJS-$(CONFIG_LLVIDENCDSP) += llviddspenc.o
15+AVCODECOBJS-$(CONFIG_ME_CMP) += motion.o
1516 AVCODECOBJS-$(CONFIG_VC1DSP) += vc1dsp.o
1617 AVCODECOBJS-$(CONFIG_VP8DSP) += vp8dsp.o
1718 AVCODECOBJS-$(CONFIG_VIDEODSP) += videodsp.o
tests/checkasm/checkasm.c+3−0
@@ -135,6 +135,9 @@ static const struct { · 134 unmodified lines
135135 #if CONFIG_LLVIDENCDSP
136136 { "llviddspenc", checkasm_check_llviddspenc },
137137 #endif
138+ #if CONFIG_ME_CMP
139+ { "motion", checkasm_check_motion },
140+ #endif
138141 #if CONFIG_OPUS_DECODER
139142 { "opusdsp", checkasm_check_opusdsp },
140143 #endif
tests/checkasm/checkasm.h+1−0
@@ -68,6 +68,7 @@ void checkasm_check_idctdsp(void); · 67 unmodified lines
6868 void checkasm_check_jpeg2000dsp(void);
6969 void checkasm_check_llviddsp(void);
7070 void checkasm_check_llviddspenc(void);
71+void checkasm_check_motion(void);
7172 void checkasm_check_nlmeans(void);
7273 void checkasm_check_opusdsp(void);
7374 void checkasm_check_pixblockdsp(void);
tests/checkasm/motion.c+151−0
@@ -0,0 +1,151 @@
1+/*
2+ *
3+ * This file is part of FFmpeg.
4+ *
5+ * FFmpeg is free software; you can redistribute it and/or modify
6+ * it under the terms of the GNU General Public License as published by
7+ * the Free Software Foundation; either version 2 of the License, or
8+ * (at your option) any later version.
9+ *
10+ * FFmpeg is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+ * GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License along
16+ * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
17+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+ */
19+
20+#include <string.h>
21+
22+#include "libavutil/common.h"
23+#include "libavutil/intreadwrite.h"
24+#include "libavutil/mem_internal.h"
25+
26+#include "libavcodec/me_cmp.h"
27+
28+#include "checkasm.h"
29+
30+static void fill_random(uint8_t *tab, int size)
31+{
32+ int i;
33+ for (i = 0; i < size; i++) {
34+ tab[i] = rnd() % 256;
35+ }
36+}
37+
38+static void test_motion(const char *name, me_cmp_func test_func)
39+{
40+ /* test configurarion */
41+#define ITERATIONS 16
42+#define WIDTH 64
43+#define HEIGHT 64
44+
45+ /* motion estimation can look up to 17 bytes ahead */
46+ static const int look_ahead = 17;
47+
48+ int i, x, y, d1, d2;
49+ uint8_t *ptr;
50+
51+ LOCAL_ALIGNED_8(uint8_t, img1, [WIDTH * HEIGHT]);
52+ LOCAL_ALIGNED_8(uint8_t, img2, [WIDTH * HEIGHT]);
53+
54+ declare_func_emms(AV_CPU_FLAG_MMX, int, struct MpegEncContext *c,
55+ uint8_t *blk1 /* align width (8 or 16) */,
56+ uint8_t *blk2 /* align 1 */, ptrdiff_t stride,
57+ int h);
58+
59+ if (test_func == NULL) {
60+ return;
61+ }
62+
63+ /* test correctness */
64+ fill_random(img1, WIDTH * HEIGHT);
65+ fill_random(img2, WIDTH * HEIGHT);
66+
67+ if (check_func(test_func, "%s", name)) {
68+ for (i = 0; i < ITERATIONS; i++) {
69+ x = rnd() % (WIDTH - look_ahead);
70+ y = rnd() % (HEIGHT - look_ahead);
71+
72+ ptr = img2 + y * WIDTH + x;
73+ d2 = call_ref(NULL, img1, ptr, WIDTH, 8);
74+ d1 = call_new(NULL, img1, ptr, WIDTH, 8);
75+
76+ if (d1 != d2) {
77+ fail();
78+ printf("func: %s, x=%d y=%d, error: asm=%d c=%d\n", name, x, y, d1, d2);
79+ break;
80+ }
81+ }
82+ // benchmark with the final value of ptr
83+ bench_new(NULL, img1, ptr, WIDTH, 8);
84+ }
85+}
86+
87+#define ME_CMP_1D_ARRAYS(XX) \
88+ XX(sad) \
89+ XX(sse) \
90+ XX(hadamard8_diff) \
91+ XX(vsad) \
92+ XX(vsse) \
93+ XX(nsse) \
94+ XX(me_pre_cmp) \
95+ XX(me_cmp) \
96+ XX(me_sub_cmp) \
97+ XX(mb_cmp) \
98+ XX(ildct_cmp) \
99+ XX(frame_skip_cmp) \
100+ XX(median_sad)
101+
102+// tests for functions not yet implemented
103+#if 0
104+ XX(dct_sad) \
105+ XX(quant_psnr) \
106+ XX(bit) \
107+ XX(rd) \
108+ XX(w53) \
109+ XX(w97) \
110+ XX(dct_max) \
111+ XX(dct264_sad) \
112+
113+#endif
114+
115+static void check_motion(void)
116+{
117+ char buf[64];
118+ AVCodecContext *av_ctx;
119+ MECmpContext me_ctx;
120+
121+ memset(&me_ctx, 0, sizeof(me_ctx));
122+
123+ /* allocate AVCodecContext */
124+ av_ctx = avcodec_alloc_context3(NULL);
125+ av_ctx->flags |= AV_CODEC_FLAG_BITEXACT;
126+
127+ ff_me_cmp_init(&me_ctx, av_ctx);
128+
129+ for (int i = 0; i < FF_ARRAY_ELEMS(me_ctx.pix_abs); i++) {
130+ for (int j = 0; j < FF_ARRAY_ELEMS(me_ctx.pix_abs[0]); j++) {
131+ snprintf(buf, sizeof(buf), "pix_abs_%d_%d", i, j);
132+ test_motion(buf, me_ctx.pix_abs[i][j]);
133+ }
134+ }
135+
136+#define XX(me_cmp_array) \
137+ for (int i = 0; i < FF_ARRAY_ELEMS(me_ctx.me_cmp_array); i++) { \
138+ snprintf(buf, sizeof(buf), #me_cmp_array "_%d", i); \
139+ test_motion(buf, me_ctx.me_cmp_array[i]); \
140+ }
141+ ME_CMP_1D_ARRAYS(XX)
142+#undef XX
143+
144+ avcodec_free_context(&av_ctx);
145+}
146+
147+void checkasm_check_motion(void)
148+{
149+ check_motion();
150+ report("motion");
151+}
tests/fate/checkasm.mak+1−0
@@ -23,6 +23,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ · 22 unmodified lines
2323 fate-checkasm-jpeg2000dsp \
2424 fate-checkasm-llviddsp \
2525 fate-checkasm-llviddspenc \
26+ fate-checkasm-motion \
2627 fate-checkasm-opusdsp \
2728 fate-checkasm-pixblockdsp \
2829 fate-checkasm-sbrdsp \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t