FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/tests/checkasm/aacpsdsp.c
Date: 2026-09-12 04:54:02
Exec Total Coverage
Lines: 128 136 94.1%
Functions: 8 8 100.0%
Branches: 71 190 37.4%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (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
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with FFmpeg; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include <string.h>
20
21 #include "libavcodec/aacpsdsp.h"
22 #include "libavutil/intfloat.h"
23 #include "libavutil/mem_internal.h"
24
25 #include "checkasm.h"
26
27 #define N 32
28 #define STRIDE 128
29 #define BUF_SIZE (N * STRIDE)
30
31 #define randomize(buf, len) do { \
32 int i; \
33 for (i = 0; i < len; i++) { \
34 const INTFLOAT f = (INTFLOAT)rnd() / UINT_MAX; \
35 (buf)[i] = f; \
36 } \
37 } while (0)
38
39 #define EPS 0.005
40
41 4 static void clear_less_significant_bits(INTFLOAT *buf, int len, int bits)
42 {
43 int i;
44
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 4 times.
36 for (i = 0; i < len; i++) {
45 32 union av_intfloat32 u = { .f = buf[i] };
46 32 u.i &= (0xffffffff << bits);
47 32 buf[i] = u.f;
48 }
49 4 }
50
51 3 static void test_add_squares(void)
52 {
53 3 LOCAL_ALIGNED_16(INTFLOAT, dst0, [BUF_SIZE]);
54 3 LOCAL_ALIGNED_16(INTFLOAT, dst1, [BUF_SIZE]);
55 3 LOCAL_ALIGNED_16(INTFLOAT, src, [BUF_SIZE], [2]);
56
57 3 declare_func(void, INTFLOAT *dst,
58 const INTFLOAT (*src)[2], int n);
59
60
2/2
✓ Branch 1 taken 24576 times.
✓ Branch 2 taken 3 times.
24579 randomize((INTFLOAT *)src, BUF_SIZE * 2);
61
2/2
✓ Branch 1 taken 12288 times.
✓ Branch 2 taken 3 times.
12291 randomize(dst0, BUF_SIZE);
62 3 memcpy(dst1, dst0, BUF_SIZE * sizeof(INTFLOAT));
63
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 call_ref(dst0, src, BUF_SIZE);
64 3 call_new(dst1, src, BUF_SIZE);
65
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (!float_near_abs_eps_array(dst0, dst1, EPS, BUF_SIZE))
66 fail();
67
1/18
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
3 bench_new(dst1, src, BUF_SIZE);
68 3 }
69
70 2 static void test_mul_pair_single(void)
71 {
72 2 LOCAL_ALIGNED_16(INTFLOAT, dst0, [BUF_SIZE], [2]);
73 2 LOCAL_ALIGNED_16(INTFLOAT, dst1, [BUF_SIZE], [2]);
74 2 LOCAL_ALIGNED_16(INTFLOAT, src0, [BUF_SIZE], [2]);
75 2 LOCAL_ALIGNED_16(INTFLOAT, src1, [BUF_SIZE]);
76
77 2 declare_func(void, INTFLOAT (*dst)[2],
78 INTFLOAT (*src0)[2], INTFLOAT *src1, int n);
79
80
2/2
✓ Branch 1 taken 16384 times.
✓ Branch 2 taken 2 times.
16386 randomize((INTFLOAT *)src0, BUF_SIZE * 2);
81
2/2
✓ Branch 1 taken 8192 times.
✓ Branch 2 taken 2 times.
8194 randomize(src1, BUF_SIZE);
82
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 call_ref(dst0, src0, src1, BUF_SIZE);
83 2 call_new(dst1, src0, src1, BUF_SIZE);
84
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!float_near_abs_eps_array((float *)dst0, (float *)dst1, EPS, BUF_SIZE * 2))
85 fail();
86
1/18
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
2 bench_new(dst1, src0, src1, BUF_SIZE);
87 2 }
88
89 3 static void test_hybrid_analysis(void)
90 {
91 3 LOCAL_ALIGNED_16(INTFLOAT, dst0, [BUF_SIZE], [2]);
92 3 LOCAL_ALIGNED_16(INTFLOAT, dst1, [BUF_SIZE], [2]);
93 3 LOCAL_ALIGNED_16(INTFLOAT, in, [13], [2]);
94 3 LOCAL_ALIGNED_16(INTFLOAT, filter, [N], [8][2]);
95
96 3 declare_func(void, INTFLOAT (*out)[2], INTFLOAT (*in)[2],
97 const INTFLOAT (*filter)[8][2],
98 ptrdiff_t stride, int n);
99
100
2/2
✓ Branch 1 taken 78 times.
✓ Branch 2 taken 3 times.
81 randomize((INTFLOAT *)in, 13 * 2);
101
2/2
✓ Branch 1 taken 1536 times.
✓ Branch 2 taken 3 times.
1539 randomize((INTFLOAT *)filter, N * 8 * 2);
102
103
2/2
✓ Branch 1 taken 24576 times.
✓ Branch 2 taken 3 times.
24579 randomize((INTFLOAT *)dst0, BUF_SIZE * 2);
104 3 memcpy(dst1, dst0, BUF_SIZE * 2 * sizeof(INTFLOAT));
105
106
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 call_ref(dst0, in, filter, STRIDE, N);
107 3 call_new(dst1, in, filter, STRIDE, N);
108
109
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (!float_near_abs_eps_array((float *)dst0, (float *)dst1, EPS, BUF_SIZE * 2))
110 fail();
111
1/18
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
3 bench_new(dst1, in, filter, STRIDE, N);
112 3 }
113
114 2 static void test_hybrid_analysis_ileave(void)
115 {
116 2 LOCAL_ALIGNED_16(INTFLOAT, in, [2], [38][64]);
117 2 LOCAL_ALIGNED_16(INTFLOAT, out0, [91], [32][2]);
118 2 LOCAL_ALIGNED_16(INTFLOAT, out1, [91], [32][2]);
119
120 2 declare_func(void, INTFLOAT (*out)[32][2], INTFLOAT L[2][38][64],
121 int i, int len);
122
123
2/2
✓ Branch 1 taken 11648 times.
✓ Branch 2 taken 2 times.
11650 randomize((INTFLOAT *)out0, 91 * 32 * 2);
124
2/2
✓ Branch 1 taken 9728 times.
✓ Branch 2 taken 2 times.
9730 randomize((INTFLOAT *)in, 2 * 38 * 64);
125 2 memcpy(out1, out0, 91 * 32 * 2 * sizeof(INTFLOAT));
126
127 /* len is hardcoded to 32 as that's the only value used in
128 libavcodec. asm functions are likely to be optimized
129 hardcoding this value in their loops and could fail with
130 anything else.
131 i is hardcoded to the two values currently used by the
132 aac decoder because the arm neon implementation is
133 micro-optimized for them and will fail for almost every
134 other value. */
135
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 call_ref(out0, in, 3, 32);
136 2 call_new(out1, in, 3, 32);
137
138 /* the function just moves data around, so memcmp is enough */
139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (memcmp(out0, out1, 91 * 32 * 2 * sizeof(INTFLOAT)))
140 fail();
141
142
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 call_ref(out0, in, 5, 32);
143 2 call_new(out1, in, 5, 32);
144
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (memcmp(out0, out1, 91 * 32 * 2 * sizeof(INTFLOAT)))
146 fail();
147
148
1/18
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
2 bench_new(out1, in, 3, 32);
149 2 }
150
151 3 static void test_hybrid_synthesis_deint(void)
152 {
153 3 LOCAL_ALIGNED_16(INTFLOAT, out0, [2], [38][64]);
154 3 LOCAL_ALIGNED_16(INTFLOAT, out1, [2], [38][64]);
155 3 LOCAL_ALIGNED_16(INTFLOAT, in, [91], [32][2]);
156
157 3 declare_func(void, INTFLOAT out[2][38][64], INTFLOAT (*in)[32][2],
158 int i, int len);
159
160
2/2
✓ Branch 1 taken 17472 times.
✓ Branch 2 taken 3 times.
17475 randomize((INTFLOAT *)in, 91 * 32 * 2);
161
2/2
✓ Branch 1 taken 14592 times.
✓ Branch 2 taken 3 times.
14595 randomize((INTFLOAT *)out0, 2 * 38 * 64);
162 3 memcpy(out1, out0, 2 * 38 * 64 * sizeof(INTFLOAT));
163
164 /* len is hardcoded to 32 as that's the only value used in
165 libavcodec. asm functions are likely to be optimized
166 hardcoding this value in their loops and could fail with
167 anything else.
168 i is hardcoded to the two values currently used by the
169 aac decoder because the arm neon implementation is
170 micro-optimized for them and will fail for almost every
171 other value. */
172
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 call_ref(out0, in, 3, 32);
173 3 call_new(out1, in, 3, 32);
174
175 /* the function just moves data around, so memcmp is enough */
176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (memcmp(out0, out1, 2 * 38 * 64 * sizeof(INTFLOAT)))
177 fail();
178
179
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 call_ref(out0, in, 5, 32);
180 3 call_new(out1, in, 5, 32);
181
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (memcmp(out0, out1, 2 * 38 * 64 * sizeof(INTFLOAT)))
183 fail();
184
185
1/18
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
3 bench_new(out1, in, 3, 32);
186 3 }
187
188 14 static void test_stereo_interpolate(PSDSPContext *psdsp)
189 {
190 int i;
191 14 LOCAL_ALIGNED_16(INTFLOAT, l, [BUF_SIZE], [2]);
192 14 LOCAL_ALIGNED_16(INTFLOAT, r, [BUF_SIZE], [2]);
193 14 LOCAL_ALIGNED_16(INTFLOAT, l0, [BUF_SIZE], [2]);
194 14 LOCAL_ALIGNED_16(INTFLOAT, r0, [BUF_SIZE], [2]);
195 14 LOCAL_ALIGNED_16(INTFLOAT, l1, [BUF_SIZE], [2]);
196 14 LOCAL_ALIGNED_16(INTFLOAT, r1, [BUF_SIZE], [2]);
197 14 LOCAL_ALIGNED_16(INTFLOAT, h, [2], [4]);
198 14 LOCAL_ALIGNED_16(INTFLOAT, h_step, [2], [4]);
199
200 14 declare_func(void, INTFLOAT (*l)[2], INTFLOAT (*r)[2],
201 INTFLOAT h[2][4], INTFLOAT h_step[2][4], int len);
202
203
2/2
✓ Branch 1 taken 114688 times.
✓ Branch 2 taken 14 times.
114702 randomize((INTFLOAT *)l, BUF_SIZE * 2);
204
2/2
✓ Branch 1 taken 114688 times.
✓ Branch 2 taken 14 times.
114702 randomize((INTFLOAT *)r, BUF_SIZE * 2);
205
206
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 14 times.
42 for (i = 0; i < 2; i++) {
207
4/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 24 times.
28 if (check_func(psdsp->stereo_interpolate[i], "ps_stereo_interpolate%s", i ? "_ipdopd" : "")) {
208 4 memcpy(l0, l, BUF_SIZE * 2 * sizeof(INTFLOAT));
209 4 memcpy(l1, l, BUF_SIZE * 2 * sizeof(INTFLOAT));
210 4 memcpy(r0, r, BUF_SIZE * 2 * sizeof(INTFLOAT));
211 4 memcpy(r1, r, BUF_SIZE * 2 * sizeof(INTFLOAT));
212
213
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 4 times.
36 randomize((INTFLOAT *)h, 2 * 4);
214
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 4 times.
36 randomize((INTFLOAT *)h_step, 2 * 4);
215 // Clear the least significant 14 bits of h_step, to avoid
216 // divergence when accumulating h_step BUF_SIZE times into
217 // a float variable which may or may not have extra intermediate
218 // precision. Therefore clear roughly log2(BUF_SIZE) less
219 // significant bits, to get the same result regardless of any
220 // extra precision in the accumulator.
221 4 clear_less_significant_bits((INTFLOAT *)h_step, 2 * 4, 14);
222
223
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 call_ref(l0, r0, h, h_step, BUF_SIZE);
224 4 call_new(l1, r1, h, h_step, BUF_SIZE);
225
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
8 if (!float_near_abs_eps_array((float *)l0, (float *)l1, EPS, BUF_SIZE * 2) ||
226 4 !float_near_abs_eps_array((float *)r0, (float *)r1, EPS, BUF_SIZE * 2))
227 fail();
228
229 4 memcpy(l1, l, BUF_SIZE * 2 * sizeof(INTFLOAT));
230 4 memcpy(r1, r, BUF_SIZE * 2 * sizeof(INTFLOAT));
231
1/18
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
4 bench_new(l1, r1, h, h_step, BUF_SIZE);
232 }
233 }
234 14 }
235
236 14 void checkasm_check_aacpsdsp(void)
237 {
238 PSDSPContext psdsp;
239
240 14 ff_psdsp_init(&psdsp);
241
242
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 11 times.
14 if (check_func(psdsp.add_squares, "ps_add_squares"))
243 3 test_add_squares();
244 14 report("add_squares");
245
246
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 12 times.
14 if (check_func(psdsp.mul_pair_single, "ps_mul_pair_single"))
247 2 test_mul_pair_single();
248 14 report("mul_pair_single");
249
250
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 11 times.
14 if (check_func(psdsp.hybrid_analysis, "ps_hybrid_analysis"))
251 3 test_hybrid_analysis();
252 14 report("hybrid_analysis");
253
254
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 12 times.
14 if (check_func(psdsp.hybrid_analysis_ileave, "ps_hybrid_analysis_ileave"))
255 2 test_hybrid_analysis_ileave();
256 14 report("hybrid_analysis_ileave");
257
258
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 11 times.
14 if (check_func(psdsp.hybrid_synthesis_deint, "ps_hybrid_synthesis_deint"))
259 3 test_hybrid_synthesis_deint();
260 14 report("hybrid_synthesis_deint");
261
262 14 test_stereo_interpolate(&psdsp);
263 14 report("stereo_interpolate");
264 14 }
265