FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavutil/tx.c
Date: 2026-10-19 20:11:44
Exec Total Coverage
Lines: 432 496 87.1%
Functions: 24 25 96.0%
Branches: 466 612 76.1%

Line Branch Exec Source
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 "avassert.h"
20 #include "intmath.h"
21 #include "cpu.h"
22 #include "mem.h"
23 #include "qsort.h"
24 #include "bprint.h"
25
26 #include "tx_priv.h"
27
28 #define TYPE_IS(type, x) \
29 (((x) == AV_TX_FLOAT_ ## type) || \
30 ((x) == AV_TX_DOUBLE_ ## type) || \
31 ((x) == AV_TX_INT32_ ## type))
32
33 /* Calculates the modular multiplicative inverse */
34 5658 static av_always_inline int mulinv(int n, int m)
35 {
36 5658 n = n % m;
37
1/2
✓ Branch 0 taken 57492 times.
✗ Branch 1 not taken.
57492 for (int x = 1; x < m; x++)
38
2/2
✓ Branch 0 taken 5658 times.
✓ Branch 1 taken 51834 times.
57492 if (((n * x) % m) == 1)
39 5658 return x;
40 ✗ av_assert0(0); /* Never reached */
41 return 0;
42 }
43
44 81 int ff_tx_gen_pfa_input_map(AVTXContext *s, FFTXCodeletOptions *opts,
45 int d1, int d2)
46 {
47 81 const int sl = d1*d2;
48
49 81 s->map = av_malloc(s->len*sizeof(*s->map));
50
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if (!s->map)
51 ✗ return AVERROR(ENOMEM);
52
53
2/2
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 81 times.
162 for (int k = 0; k < s->len; k += sl) {
54
3/6
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 81 times.
81 if (s->inv || (opts && opts->map_dir == FF_TX_MAP_SCATTER)) {
55 ✗ for (int m = 0; m < d2; m++)
56 ✗ for (int n = 0; n < d1; n++)
57 ✗ s->map[k + ((m*d1 + n*d2) % (sl))] = m*d1 + n;
58 } else {
59
2/2
✓ Branch 0 taken 405 times.
✓ Branch 1 taken 81 times.
486 for (int m = 0; m < d2; m++)
60
2/2
✓ Branch 0 taken 1215 times.
✓ Branch 1 taken 405 times.
1620 for (int n = 0; n < d1; n++)
61 1215 s->map[k + m*d1 + n] = (m*d1 + n*d2) % (sl);
62 }
63
64
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if (s->inv)
65 ✗ for (int w = 1; w <= ((sl) >> 1); w++)
66 ✗ FFSWAP(int, s->map[k + w], s->map[k + sl - w]);
67 }
68
69
1/2
✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
81 s->map_dir = opts ? opts->map_dir : FF_TX_MAP_GATHER;
70
71 81 return 0;
72 }
73
74 /* Guaranteed to work for any n, m where gcd(n, m) == 1 */
75 2829 int ff_tx_gen_compound_mapping(AVTXContext *s, FFTXCodeletOptions *opts,
76 int inv, int n, int m)
77 {
78 int *in_map, *out_map;
79 2829 const int len = n*m; /* Will not be equal to s->len for MDCTs */
80 int m_inv, n_inv;
81
82 /* Make sure the numbers are coprime */
83
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2829 times.
2829 if (av_gcd(n, m) != 1)
84 ✗ return AVERROR(EINVAL);
85
86 2829 m_inv = mulinv(m, n);
87 2829 n_inv = mulinv(n, m);
88
89
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2829 times.
2829 if (!(s->map = av_malloc(2*len*sizeof(*s->map))))
90 ✗ return AVERROR(ENOMEM);
91
92 2829 in_map = s->map;
93 2829 out_map = s->map + len;
94
95 /* Ruritanian map for input, CRT map for output, can be swapped */
96
3/4
✓ Branch 0 taken 549 times.
✓ Branch 1 taken 2280 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 549 times.
2829 if (opts && opts->map_dir == FF_TX_MAP_SCATTER) {
97 ✗ for (int j = 0; j < m; j++) {
98 ✗ for (int i = 0; i < n; i++) {
99 ✗ in_map[(i*m + j*n) % len] = j*n + i;
100 ✗ out_map[(i*m*m_inv + j*n*n_inv) % len] = i*m + j;
101 }
102 }
103 } else {
104
2/2
✓ Branch 0 taken 98392 times.
✓ Branch 1 taken 2829 times.
101221 for (int j = 0; j < m; j++) {
105
2/2
✓ Branch 0 taken 747096 times.
✓ Branch 1 taken 98392 times.
845488 for (int i = 0; i < n; i++) {
106 747096 in_map[j*n + i] = (i*m + j*n) % len;
107 747096 out_map[(i*m*m_inv + j*n*n_inv) % len] = i*m + j;
108 }
109 }
110 }
111
112
2/2
✓ Branch 0 taken 2721 times.
✓ Branch 1 taken 108 times.
2829 if (inv) {
113
2/2
✓ Branch 0 taken 92560 times.
✓ Branch 1 taken 2721 times.
95281 for (int i = 0; i < m; i++) {
114 92560 int *in = &in_map[i*n + 1]; /* Skip the DC */
115
2/2
✓ Branch 0 taken 283856 times.
✓ Branch 1 taken 92560 times.
376416 for (int j = 0; j < ((n - 1) >> 1); j++)
116 283856 FFSWAP(int, in[j], in[n - j - 2]);
117 }
118 }
119
120
2/2
✓ Branch 0 taken 549 times.
✓ Branch 1 taken 2280 times.
2829 s->map_dir = opts ? opts->map_dir : FF_TX_MAP_GATHER;
121
122 2829 return 0;
123 }
124
125 12850186 static inline int split_radix_permutation(int i, int len, int inv)
126 {
127 12850186 len >>= 1;
128
2/2
✓ Branch 0 taken 1687946 times.
✓ Branch 1 taken 11162240 times.
12850186 if (len <= 1)
129 1687946 return i & 1;
130
2/2
✓ Branch 0 taken 5581120 times.
✓ Branch 1 taken 5581120 times.
11162240 if (!(i & len))
131 5581120 return split_radix_permutation(i, len, inv) * 2;
132 5581120 len >>= 1;
133 5581120 return split_radix_permutation(i, len, inv) * 4 + 1 - 2*(!(i & len) ^ inv);
134 }
135
136 5260 int ff_tx_gen_ptwo_revtab(AVTXContext *s, FFTXCodeletOptions *opts)
137 {
138 5260 int len = s->len;
139
140
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5260 times.
5260 if (!(s->map = av_malloc(len*sizeof(*s->map))))
141 ✗ return AVERROR(ENOMEM);
142
143
3/4
✓ Branch 0 taken 5260 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2430 times.
✓ Branch 3 taken 2830 times.
5260 if (opts && opts->map_dir == FF_TX_MAP_SCATTER) {
144
2/2
✓ Branch 0 taken 256756 times.
✓ Branch 1 taken 2430 times.
259186 for (int i = 0; i < s->len; i++)
145 256756 s->map[-split_radix_permutation(i, len, s->inv) & (len - 1)] = i;
146 } else {
147
2/2
✓ Branch 0 taken 1137930 times.
✓ Branch 1 taken 2830 times.
1140760 for (int i = 0; i < s->len; i++)
148 1137930 s->map[i] = -split_radix_permutation(i, len, s->inv) & (len - 1);
149 }
150
151
1/2
✓ Branch 0 taken 5260 times.
✗ Branch 1 not taken.
5260 s->map_dir = opts ? opts->map_dir : FF_TX_MAP_GATHER;
152
153 5260 return 0;
154 }
155
156 ✗ int ff_tx_gen_inplace_map(AVTXContext *s, int len)
157 {
158 ✗ int *src_map, out_map_idx = 0;
159
160 ✗ if (!s->sub || !s->sub->map)
161 ✗ return AVERROR(EINVAL);
162
163 ✗ if (!(s->map = av_mallocz(len*sizeof(*s->map))))
164 ✗ return AVERROR(ENOMEM);
165
166 ✗ src_map = s->sub->map;
167
168 /* The first coefficient is always already in-place */
169 ✗ for (int src = 1; src < s->len; src++) {
170 ✗ int dst = src_map[src];
171 ✗ int found = 0;
172
173 ✗ if (dst <= src)
174 ✗ continue;
175
176 /* This just checks if a closed loop has been encountered before,
177 * and if so, skips it, since to fully permute a loop we must only
178 * enter it once. */
179 do {
180 ✗ for (int j = 0; j < out_map_idx; j++) {
181 ✗ if (dst == s->map[j]) {
182 ✗ found = 1;
183 ✗ break;
184 }
185 }
186 ✗ dst = src_map[dst];
187 ✗ } while (dst != src && !found);
188
189 ✗ if (!found)
190 ✗ s->map[out_map_idx++] = src;
191 }
192
193 ✗ s->map[out_map_idx++] = 0;
194
195 ✗ return 0;
196 }
197
198 72271 static void parity_revtab_generator(int *revtab, int n, int inv, int offset,
199 int is_dual, int dual_high, int len,
200 int basis, int dual_stride, int inv_lookup)
201 {
202 72271 len >>= 1;
203
204
2/2
✓ Branch 0 taken 48795 times.
✓ Branch 1 taken 23476 times.
72271 if (len <= basis) {
205 int k1, k2, stride, even_idx, odd_idx;
206
207
3/4
✓ Branch 0 taken 36466 times.
✓ Branch 1 taken 12329 times.
✓ Branch 2 taken 36466 times.
✗ Branch 3 not taken.
48795 is_dual = is_dual && dual_stride;
208 48795 dual_high = is_dual & dual_high;
209
2/2
✓ Branch 0 taken 36466 times.
✓ Branch 1 taken 12329 times.
48795 stride = is_dual ? FFMIN(dual_stride, len) : 0;
210
211 48795 even_idx = offset + dual_high*(stride - 2*len);
212
4/4
✓ Branch 0 taken 36466 times.
✓ Branch 1 taken 12329 times.
✓ Branch 2 taken 18233 times.
✓ Branch 3 taken 18233 times.
48795 odd_idx = even_idx + len + (is_dual && !dual_high)*len + dual_high*len;
213
214
2/2
✓ Branch 0 taken 146630 times.
✓ Branch 1 taken 48795 times.
195425 for (int i = 0; i < len; i++) {
215 146630 k1 = -split_radix_permutation(offset + i*2 + 0, n, inv) & (n - 1);
216 146630 k2 = -split_radix_permutation(offset + i*2 + 1, n, inv) & (n - 1);
217
2/2
✓ Branch 0 taken 106932 times.
✓ Branch 1 taken 39698 times.
146630 if (inv_lookup) {
218 106932 revtab[even_idx++] = k1;
219 106932 revtab[odd_idx++] = k2;
220 } else {
221 39698 revtab[k1] = even_idx++;
222 39698 revtab[k2] = odd_idx++;
223 }
224
4/4
✓ Branch 0 taken 97676 times.
✓ Branch 1 taken 48954 times.
✓ Branch 2 taken 48838 times.
✓ Branch 3 taken 48838 times.
146630 if (stride && !((i + 1) % stride)) {
225 48838 even_idx += stride;
226 48838 odd_idx += stride;
227 }
228 }
229
230 48795 return;
231 }
232
233 23476 parity_revtab_generator(revtab, n, inv, offset,
234 0, 0, len >> 0, basis, dual_stride, inv_lookup);
235 23476 parity_revtab_generator(revtab, n, inv, offset + (len >> 0),
236 1, 0, len >> 1, basis, dual_stride, inv_lookup);
237 23476 parity_revtab_generator(revtab, n, inv, offset + (len >> 0) + (len >> 1),
238 1, 1, len >> 1, basis, dual_stride, inv_lookup);
239 }
240
241 1843 int ff_tx_gen_split_radix_parity_revtab(AVTXContext *s, int len, int inv,
242 FFTXCodeletOptions *opts,
243 int basis, int dual_stride)
244 {
245 1843 basis >>= 1;
246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1843 times.
1843 if (len < basis)
247 ✗ return AVERROR(EINVAL);
248
249
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1843 times.
1843 if (!(s->map = av_mallocz(len*sizeof(*s->map))))
250 ✗ return AVERROR(ENOMEM);
251
252
3/4
✓ Branch 0 taken 1561 times.
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1561 times.
1843 av_assert0(!dual_stride || !(dual_stride & (dual_stride - 1)));
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1843 times.
1843 av_assert0(dual_stride <= basis);
254
255
2/2
✓ Branch 0 taken 1817 times.
✓ Branch 1 taken 26 times.
3660 parity_revtab_generator(s->map, len, inv, 0, 0, 0, len,
256 basis, dual_stride,
257
2/2
✓ Branch 0 taken 919 times.
✓ Branch 1 taken 898 times.
1817 opts ? opts->map_dir == FF_TX_MAP_GATHER : FF_TX_MAP_GATHER);
258
259
2/2
✓ Branch 0 taken 1817 times.
✓ Branch 1 taken 26 times.
1843 s->map_dir = opts ? opts->map_dir : FF_TX_MAP_GATHER;
260
261 1843 return 0;
262 }
263
264 43820 static void reset_ctx(AVTXContext *s, int free_sub)
265 {
266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43820 times.
43820 if (!s)
267 ✗ return;
268
269
2/2
✓ Branch 0 taken 7837 times.
✓ Branch 1 taken 35983 times.
43820 if (s->sub)
270
2/2
✓ Branch 0 taken 31348 times.
✓ Branch 1 taken 7837 times.
39185 for (int i = 0; i < TX_MAX_SUB; i++)
271 31348 reset_ctx(&s->sub[i], free_sub + 1);
272
273
3/4
✓ Branch 0 taken 20406 times.
✓ Branch 1 taken 23414 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20406 times.
43820 if (s->cd_self && s->cd_self->uninit)
274 ✗ s->cd_self->uninit(s);
275
276
2/2
✓ Branch 0 taken 38500 times.
✓ Branch 1 taken 5320 times.
43820 if (free_sub)
277 38500 av_freep(&s->sub);
278
279 43820 av_freep(&s->map);
280 43820 av_freep(&s->exp);
281 43820 av_freep(&s->tmp);
282
283 /* Nothing else needs to be reset, it gets overwritten if another
284 * ff_tx_init_subtx() call is made. */
285 43820 s->nb_sub = 0;
286 43820 s->opaque = NULL;
287 43820 memset(s->fn, 0, sizeof(s->fn));
288 }
289
290 97 void ff_tx_clear_ctx(AVTXContext *s)
291 {
292 97 reset_ctx(s, 0);
293 97 }
294
295 7801 av_cold void av_tx_uninit(AVTXContext **ctx)
296 {
297
2/2
✓ Branch 0 taken 649 times.
✓ Branch 1 taken 7152 times.
7801 if (!(*ctx))
298 649 return;
299
300 7152 reset_ctx(*ctx, 1);
301 7152 av_freep(ctx);
302 }
303
304 14 static av_cold int ff_tx_null_init(AVTXContext *s, const FFTXCodelet *cd,
305 uint64_t flags, FFTXCodeletOptions *opts,
306 int len, int inv, const void *scale)
307 {
308 /* Can only handle one sample+type to one sample+type transforms */
309
6/12
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 14 times.
14 if (TYPE_IS(MDCT, s->type) || TYPE_IS(RDFT, s->type))
310 ✗ return AVERROR(EINVAL);
311 14 return 0;
312 }
313
314 /* Null transform when the length is 1 */
315 3 static void ff_tx_null(AVTXContext *s, void *_out, void *_in, ptrdiff_t stride)
316 {
317 3 memcpy(_out, _in, stride);
318 3 }
319
320 static const FFTXCodelet ff_tx_null_def = {
321 .name = NULL_IF_CONFIG_SMALL("null"),
322 .function = ff_tx_null,
323 .type = TX_TYPE_ANY,
324 .flags = AV_TX_UNALIGNED | FF_TX_ALIGNED |
325 FF_TX_OUT_OF_PLACE | AV_TX_INPLACE,
326 .factors[0] = TX_FACTOR_ANY,
327 .min_len = 1,
328 .max_len = 1,
329 .init = ff_tx_null_init,
330 .cpu_flags = FF_TX_CPU_FLAGS_ALL,
331 .prio = FF_TX_PRIO_MAX,
332 };
333
334 static const FFTXCodelet * const ff_tx_null_list[] = {
335 &ff_tx_null_def,
336 NULL,
337 };
338
339 /* Array of all compiled codelet lists. Order is irrelevant. */
340 static const FFTXCodelet * const * const codelet_list[] = {
341 ff_tx_codelet_list_float_c,
342 ff_tx_codelet_list_double_c,
343 ff_tx_codelet_list_int32_c,
344 ff_tx_null_list,
345 #if HAVE_X86ASM
346 ff_tx_codelet_list_float_x86,
347 #endif
348 #if ARCH_AARCH64
349 ff_tx_codelet_list_float_aarch64,
350 #endif
351 };
352 static const int codelet_list_num = FF_ARRAY_ELEMS(codelet_list);
353
354 static const int cpu_slow_mask = AV_CPU_FLAG_SSE2SLOW | AV_CPU_FLAG_SSE3SLOW |
355 AV_CPU_FLAG_ATOM | AV_CPU_FLAG_SSSE3SLOW |
356 AV_CPU_FLAG_AVXSLOW | AV_CPU_FLAG_SLOW_GATHER;
357
358 static const int cpu_slow_penalties[][2] = {
359 { AV_CPU_FLAG_SSE2SLOW, 1 + 64 },
360 { AV_CPU_FLAG_SSE3SLOW, 1 + 64 },
361 { AV_CPU_FLAG_SSSE3SLOW, 1 + 64 },
362 { AV_CPU_FLAG_ATOM, 1 + 128 },
363 { AV_CPU_FLAG_AVXSLOW, 1 + 128 },
364 { AV_CPU_FLAG_SLOW_GATHER, 1 + 32 },
365 };
366
367 40352 static int get_codelet_prio(const FFTXCodelet *cd, int cpu_flags, int len)
368 {
369 40352 int prio = cd->prio;
370 40352 int max_factor = 0;
371
372 /* If the CPU has a SLOW flag, and the instruction is also flagged
373 * as being slow for such, reduce its priority */
374
2/2
✓ Branch 0 taken 242112 times.
✓ Branch 1 taken 40352 times.
282464 for (int i = 0; i < FF_ARRAY_ELEMS(cpu_slow_penalties); i++) {
375
2/2
✓ Branch 0 taken 2848 times.
✓ Branch 1 taken 239264 times.
242112 if ((cpu_flags & cd->cpu_flags) & cpu_slow_penalties[i][0])
376 2848 prio -= cpu_slow_penalties[i][1];
377 }
378
379 /* Prioritize aligned-only codelets */
380
4/4
✓ Branch 0 taken 6406 times.
✓ Branch 1 taken 33946 times.
✓ Branch 2 taken 6392 times.
✓ Branch 3 taken 14 times.
40352 if ((cd->flags & FF_TX_ALIGNED) && !(cd->flags & AV_TX_UNALIGNED))
381 6392 prio += 64;
382
383 /* Codelets for specific lengths are generally faster */
384
4/4
✓ Branch 0 taken 9323 times.
✓ Branch 1 taken 31029 times.
✓ Branch 2 taken 8471 times.
✓ Branch 3 taken 852 times.
40352 if ((len == cd->min_len) && (len == cd->max_len))
385 8471 prio += 64;
386
387 /* Forward-only or inverse-only transforms are generally better */
388
2/2
✓ Branch 0 taken 21932 times.
✓ Branch 1 taken 18420 times.
40352 if ((cd->flags & (FF_TX_FORWARD_ONLY | FF_TX_INVERSE_ONLY)))
389 21932 prio += 64;
390
391 /* Larger factors are generally better */
392
2/2
✓ Branch 0 taken 161408 times.
✓ Branch 1 taken 40352 times.
201760 for (int i = 0; i < TX_MAX_SUB; i++)
393 161408 max_factor = FFMAX(cd->factors[i], max_factor);
394
2/2
✓ Branch 0 taken 38432 times.
✓ Branch 1 taken 1920 times.
40352 if (max_factor)
395 38432 prio += 16*max_factor;
396
397 40352 return prio;
398 }
399
400 typedef struct FFTXLenDecomp {
401 int len;
402 int len2;
403 int prio;
404 const FFTXCodelet *cd;
405 } FFTXLenDecomp;
406
407 475 static int cmp_decomp(FFTXLenDecomp *a, FFTXLenDecomp *b)
408 {
409 475 return FFDIFFSIGN(b->prio, a->prio);
410 }
411
412 5100 int ff_tx_decompose_length(int dst[TX_MAX_DECOMPOSITIONS], enum AVTXType type,
413 int len, int inv)
414 {
415 5100 int nb_decomp = 0;
416 FFTXLenDecomp ld[TX_MAX_DECOMPOSITIONS];
417 5100 int codelet_list_idx = codelet_list_num;
418
419 5100 const int cpu_flags = av_get_cpu_flags();
420
421 /* Loop through all codelets in all codelet lists to find matches
422 * to the requirements */
423
2/2
✓ Branch 0 taken 25500 times.
✓ Branch 1 taken 5100 times.
30600 while (codelet_list_idx--) {
424 25500 const FFTXCodelet * const * list = codelet_list[codelet_list_idx];
425 25500 const FFTXCodelet *cd = NULL;
426
427
2/2
✓ Branch 0 taken 1101600 times.
✓ Branch 1 taken 25500 times.
1127100 while ((cd = *list++)) {
428 1101600 int fl = len;
429 1101600 int skip = 0, prio;
430 1101600 int factors_product = 1, factors_mod = 0;
431
432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1101600 times.
1101600 if (nb_decomp >= TX_MAX_DECOMPOSITIONS)
433 ✗ goto sort;
434
435 /* Check if the type matches */
436
4/4
✓ Branch 0 taken 1096500 times.
✓ Branch 1 taken 5100 times.
✓ Branch 2 taken 745440 times.
✓ Branch 3 taken 351060 times.
1101600 if (cd->type != TX_TYPE_ANY && type != cd->type)
437 745440 continue;
438
439 /* Check direction for non-orthogonal codelets */
440
4/4
✓ Branch 0 taken 24969 times.
✓ Branch 1 taken 331191 times.
✓ Branch 2 taken 4222 times.
✓ Branch 3 taken 20747 times.
356160 if (((cd->flags & FF_TX_FORWARD_ONLY) && inv) ||
441
4/4
✓ Branch 0 taken 9138 times.
✓ Branch 1 taken 326275 times.
✓ Branch 2 taken 7910 times.
✓ Branch 3 taken 1228 times.
335413 ((cd->flags & (FF_TX_INVERSE_ONLY | AV_TX_FULL_IMDCT)) && !inv) ||
442
3/4
✓ Branch 0 taken 4222 times.
✓ Branch 1 taken 329963 times.
✓ Branch 2 taken 4222 times.
✗ Branch 3 not taken.
334185 ((cd->flags & (FF_TX_FORWARD_ONLY | AV_TX_REAL_TO_REAL)) && inv) ||
443
3/4
✓ Branch 0 taken 4222 times.
✓ Branch 1 taken 329963 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4222 times.
334185 ((cd->flags & (FF_TX_FORWARD_ONLY | AV_TX_REAL_TO_IMAGINARY)) && inv))
444 21975 continue;
445
446 /* Check if the CPU supports the required ISA */
447
2/2
✓ Branch 0 taken 177577 times.
✓ Branch 1 taken 156608 times.
334185 if (cd->cpu_flags != FF_TX_CPU_FLAGS_ALL &&
448
2/2
✓ Branch 0 taken 176169 times.
✓ Branch 1 taken 1408 times.
177577 !(cpu_flags & (cd->cpu_flags & ~cpu_slow_mask)))
449 176169 continue;
450
451
1/2
✓ Branch 0 taken 346632 times.
✗ Branch 1 not taken.
346632 for (int i = 0; i < TX_MAX_FACTORS; i++) {
452
4/4
✓ Branch 0 taken 198800 times.
✓ Branch 1 taken 147832 times.
✓ Branch 2 taken 188616 times.
✓ Branch 3 taken 10184 times.
346632 if (!cd->factors[i] || (fl == 1))
453 break;
454
455
2/2
✓ Branch 0 taken 30616 times.
✓ Branch 1 taken 158000 times.
188616 if (cd->factors[i] == TX_FACTOR_ANY) {
456 30616 factors_mod++;
457 30616 factors_product *= fl;
458
2/2
✓ Branch 0 taken 98845 times.
✓ Branch 1 taken 59155 times.
158000 } else if (!(fl % cd->factors[i])) {
459 98845 factors_mod++;
460
2/2
✓ Branch 0 taken 98004 times.
✓ Branch 1 taken 841 times.
98845 if (cd->factors[i] == 2) {
461 98004 int b = ff_ctz(fl);
462 98004 fl >>= b;
463 98004 factors_product <<= b;
464 } else {
465 do {
466 873 fl /= cd->factors[i];
467 873 factors_product *= cd->factors[i];
468
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 841 times.
873 } while (!(fl % cd->factors[i]));
469 }
470 }
471 }
472
473 /* Disqualify if factor requirements are not satisfied or if trivial */
474
4/4
✓ Branch 0 taken 119099 times.
✓ Branch 1 taken 38917 times.
✓ Branch 2 taken 116929 times.
✓ Branch 3 taken 2170 times.
158016 if ((factors_mod < cd->nb_factors) || (len == factors_product))
475 155846 continue;
476
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2170 times.
2170 if (av_gcd(factors_product, fl) != 1)
478 ✗ continue;
479
480 /* Check if length is supported and factorization was successful */
481
2/2
✓ Branch 0 taken 1198 times.
✓ Branch 1 taken 972 times.
2170 if ((factors_product < cd->min_len) ||
482
3/4
✓ Branch 0 taken 1198 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 616 times.
✓ Branch 3 taken 582 times.
1198 (cd->max_len != TX_LEN_UNLIMITED && (factors_product > cd->max_len)))
483 1588 continue;
484
485 582 prio = get_codelet_prio(cd, cpu_flags, factors_product) * factors_product;
486
487 /* Check for duplicates */
488
2/2
✓ Branch 0 taken 979 times.
✓ Branch 1 taken 348 times.
1327 for (int i = 0; i < nb_decomp; i++) {
489
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 745 times.
979 if (factors_product == ld[i].len) {
490 /* Update priority if new one is higher */
491
2/2
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 30 times.
234 if (prio > ld[i].prio)
492 204 ld[i].prio = prio;
493 234 skip = 1;
494 234 break;
495 }
496 }
497
498 /* Add decomposition if unique */
499
2/2
✓ Branch 0 taken 348 times.
✓ Branch 1 taken 234 times.
582 if (!skip) {
500 348 ld[nb_decomp].cd = cd;
501 348 ld[nb_decomp].len = factors_product;
502 348 ld[nb_decomp].len2 = fl;
503 348 ld[nb_decomp].prio = prio;
504 348 nb_decomp++;
505 }
506 }
507 }
508
509
2/2
✓ Branch 0 taken 5003 times.
✓ Branch 1 taken 97 times.
5100 if (!nb_decomp)
510 5003 return AVERROR(EINVAL);
511
512 97 sort:
513
27/44
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 89 times.
✓ Branch 3 taken 27 times.
✓ Branch 4 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 27 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 54 times.
✓ Branch 12 taken 81 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 81 times.
✓ Branch 16 taken 81 times.
✓ Branch 17 taken 19 times.
✓ Branch 19 taken 19 times.
✓ Branch 20 taken 62 times.
✓ Branch 21 taken 62 times.
✓ Branch 22 taken 81 times.
✓ Branch 24 taken 62 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 81 times.
✓ Branch 28 taken 81 times.
✓ Branch 29 taken 81 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 81 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✓ Branch 43 taken 19 times.
✓ Branch 44 taken 62 times.
✓ Branch 46 taken 8 times.
✓ Branch 47 taken 81 times.
✓ Branch 48 taken 170 times.
✓ Branch 49 taken 89 times.
✓ Branch 50 taken 178 times.
✓ Branch 51 taken 97 times.
599 AV_QSORT(ld, nb_decomp, FFTXLenDecomp, cmp_decomp);
514
515
2/2
✓ Branch 0 taken 348 times.
✓ Branch 1 taken 97 times.
445 for (int i = 0; i < nb_decomp; i++) {
516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 348 times.
348 if (ld[i].cd->nb_factors > 1)
517 ✗ dst[i] = ld[i].len2;
518 else
519 348 dst[i] = ld[i].len;
520 }
521
522 97 return nb_decomp;
523 }
524
525 24 int ff_tx_gen_default_map(AVTXContext *s, FFTXCodeletOptions *opts)
526 {
527 24 s->map = av_malloc(s->len*sizeof(*s->map));
528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!s->map)
529 ✗ return AVERROR(ENOMEM);
530
531 24 s->map[0] = 0; /* DC is always at the start */
532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (s->inv) /* Reversing the ACs flips the transform direction */
533 ✗ for (int i = 1; i < s->len; i++)
534 ✗ s->map[i] = s->len - i;
535 else
536
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 24 times.
168 for (int i = 1; i < s->len; i++)
537 144 s->map[i] = i;
538
539 24 s->map_dir = FF_TX_MAP_GATHER;
540
541 24 return 0;
542 }
543
544 #if !CONFIG_SMALL
545 70184 static void print_flags(AVBPrint *bp, uint64_t f)
546 {
547 70184 int prev = 0;
548 70184 const char *sep = ", ";
549 70184 av_bprintf(bp, "flags: [");
550
3/4
✓ Branch 0 taken 25565 times.
✓ Branch 1 taken 44619 times.
✓ Branch 2 taken 25565 times.
✗ Branch 3 not taken.
70184 if ((f & FF_TX_ALIGNED) && ++prev)
551 25565 av_bprintf(bp, "aligned");
552
3/4
✓ Branch 0 taken 44647 times.
✓ Branch 1 taken 25537 times.
✓ Branch 2 taken 44647 times.
✗ Branch 3 not taken.
70184 if ((f & AV_TX_UNALIGNED) && ++prev)
553
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 44619 times.
44647 av_bprintf(bp, "%sunaligned", prev > 1 ? sep : "");
554
3/4
✓ Branch 0 taken 32921 times.
✓ Branch 1 taken 37263 times.
✓ Branch 2 taken 32921 times.
✗ Branch 3 not taken.
70184 if ((f & AV_TX_INPLACE) && ++prev)
555
1/2
✓ Branch 0 taken 32921 times.
✗ Branch 1 not taken.
32921 av_bprintf(bp, "%sinplace", prev > 1 ? sep : "");
556
3/4
✓ Branch 0 taken 62294 times.
✓ Branch 1 taken 7890 times.
✓ Branch 2 taken 62294 times.
✗ Branch 3 not taken.
70184 if ((f & FF_TX_OUT_OF_PLACE) && ++prev)
557
1/2
✓ Branch 0 taken 62294 times.
✗ Branch 1 not taken.
62294 av_bprintf(bp, "%sout_of_place", prev > 1 ? sep : "");
558
3/4
✓ Branch 0 taken 1681 times.
✓ Branch 1 taken 68503 times.
✓ Branch 2 taken 1681 times.
✗ Branch 3 not taken.
70184 if ((f & FF_TX_FORWARD_ONLY) && ++prev)
559
1/2
✓ Branch 0 taken 1681 times.
✗ Branch 1 not taken.
1681 av_bprintf(bp, "%sfwd_only", prev > 1 ? sep : "");
560
3/4
✓ Branch 0 taken 26911 times.
✓ Branch 1 taken 43273 times.
✓ Branch 2 taken 26911 times.
✗ Branch 3 not taken.
70184 if ((f & FF_TX_INVERSE_ONLY) && ++prev)
561
1/2
✓ Branch 0 taken 26911 times.
✗ Branch 1 not taken.
26911 av_bprintf(bp, "%sinv_only", prev > 1 ? sep : "");
562
3/4
✓ Branch 0 taken 31309 times.
✓ Branch 1 taken 38875 times.
✓ Branch 2 taken 31309 times.
✗ Branch 3 not taken.
70184 if ((f & FF_TX_PRESHUFFLE) && ++prev)
563
1/2
✓ Branch 0 taken 31309 times.
✗ Branch 1 not taken.
31309 av_bprintf(bp, "%spreshuf", prev > 1 ? sep : "");
564
3/4
✓ Branch 0 taken 276 times.
✓ Branch 1 taken 69908 times.
✓ Branch 2 taken 276 times.
✗ Branch 3 not taken.
70184 if ((f & AV_TX_FULL_IMDCT) && ++prev)
565
1/2
✓ Branch 0 taken 276 times.
✗ Branch 1 not taken.
276 av_bprintf(bp, "%simdct_full", prev > 1 ? sep : "");
566
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 70160 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
70184 if ((f & AV_TX_REAL_TO_REAL) && ++prev)
567
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 av_bprintf(bp, "%sreal_to_real", prev > 1 ? sep : "");
568
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 70160 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
70184 if ((f & AV_TX_REAL_TO_IMAGINARY) && ++prev)
569
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 av_bprintf(bp, "%sreal_to_imaginary", prev > 1 ? sep : "");
570
3/4
✓ Branch 0 taken 7900 times.
✓ Branch 1 taken 62284 times.
✓ Branch 2 taken 7900 times.
✗ Branch 3 not taken.
70184 if ((f & FF_TX_ASM_CALL) && ++prev)
571
1/2
✓ Branch 0 taken 7900 times.
✗ Branch 1 not taken.
7900 av_bprintf(bp, "%sasm_call", prev > 1 ? sep : "");
572 70184 av_bprintf(bp, "]");
573 70184 }
574
575 70184 static void print_type(AVBPrint *bp, enum AVTXType type)
576 {
577
2/2
✓ Branch 0 taken 70156 times.
✓ Branch 1 taken 28 times.
140340 av_bprintf(bp, "%s",
578 type == TX_TYPE_ANY ? "any" :
579
2/2
✓ Branch 0 taken 38843 times.
✓ Branch 1 taken 31313 times.
108999 type == AV_TX_FLOAT_FFT ? "fft_float" :
580
2/2
✓ Branch 0 taken 4809 times.
✓ Branch 1 taken 34034 times.
43652 type == AV_TX_FLOAT_MDCT ? "mdct_float" :
581
2/2
✓ Branch 0 taken 4608 times.
✓ Branch 1 taken 201 times.
9417 type == AV_TX_FLOAT_RDFT ? "rdft_float" :
582
2/2
✓ Branch 0 taken 4584 times.
✓ Branch 1 taken 24 times.
9192 type == AV_TX_FLOAT_DCT_I ? "dctI_float" :
583
2/2
✓ Branch 0 taken 4560 times.
✓ Branch 1 taken 24 times.
9144 type == AV_TX_FLOAT_DST_I ? "dstI_float" :
584
2/2
✓ Branch 0 taken 2628 times.
✓ Branch 1 taken 1932 times.
7188 type == AV_TX_DOUBLE_FFT ? "fft_double" :
585
1/2
✓ Branch 0 taken 2628 times.
✗ Branch 1 not taken.
5256 type == AV_TX_DOUBLE_MDCT ? "mdct_double" :
586
1/2
✓ Branch 0 taken 2628 times.
✗ Branch 1 not taken.
5256 type == AV_TX_DOUBLE_RDFT ? "rdft_double" :
587
1/2
✓ Branch 0 taken 2628 times.
✗ Branch 1 not taken.
5256 type == AV_TX_DOUBLE_DCT_I ? "dctI_double" :
588
1/2
✓ Branch 0 taken 2628 times.
✗ Branch 1 not taken.
5256 type == AV_TX_DOUBLE_DST_I ? "dstI_double" :
589
2/2
✓ Branch 0 taken 1449 times.
✓ Branch 1 taken 1179 times.
4077 type == AV_TX_INT32_FFT ? "fft_int32" :
590
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1431 times.
1467 type == AV_TX_INT32_MDCT ? "mdct_int32" :
591
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
36 type == AV_TX_INT32_RDFT ? "rdft_int32" :
592
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
36 type == AV_TX_INT32_DCT_I ? "dctI_int32" :
593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 type == AV_TX_INT32_DST_I ? "dstI_int32" :
594 "unknown");
595 70184 }
596
597 54856 static void print_cd_info(const FFTXCodelet *cd, int prio, int len, int print_prio,
598 int log_level)
599 {
600 AVBPrint bp;
601 54856 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
602
603 54856 av_bprintf(&bp, "%s - type: ", cd->name);
604
605 54856 print_type(&bp, cd->type);
606
607 54856 av_bprintf(&bp, ", len: ");
608
2/2
✓ Branch 0 taken 39770 times.
✓ Branch 1 taken 15086 times.
54856 if (!len) {
609
2/2
✓ Branch 0 taken 31863 times.
✓ Branch 1 taken 7907 times.
39770 if (cd->min_len != cd->max_len)
610 31863 av_bprintf(&bp, "[%i, ", cd->min_len);
611
612
2/2
✓ Branch 0 taken 29150 times.
✓ Branch 1 taken 10620 times.
39770 if (cd->max_len == TX_LEN_UNLIMITED)
613 29150 av_bprintf(&bp, "∞");
614 else
615 10620 av_bprintf(&bp, "%i", cd->max_len);
616 } else {
617 15086 av_bprintf(&bp, "%i", len);
618 }
619
620
2/2
✓ Branch 0 taken 35552 times.
✓ Branch 1 taken 19304 times.
54856 if (cd->factors[1]) {
621
3/4
✓ Branch 0 taken 27959 times.
✓ Branch 1 taken 7593 times.
✓ Branch 2 taken 27959 times.
✗ Branch 3 not taken.
35552 av_bprintf(&bp, "%s, factors", !len && cd->min_len != cd->max_len ? "]" : "");
622
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 35540 times.
35552 if (!cd->nb_factors)
623 12 av_bprintf(&bp, ": [");
624 else
625 35540 av_bprintf(&bp, "[%i]: [", cd->nb_factors);
626
627
1/2
✓ Branch 0 taken 123636 times.
✗ Branch 1 not taken.
123636 for (int i = 0; i < TX_MAX_FACTORS; i++) {
628
4/4
✓ Branch 0 taken 88084 times.
✓ Branch 1 taken 35552 times.
✓ Branch 2 taken 52532 times.
✓ Branch 3 taken 35552 times.
123636 if (i && cd->factors[i])
629 52532 av_bprintf(&bp, ", ");
630
2/2
✓ Branch 0 taken 34448 times.
✓ Branch 1 taken 89188 times.
123636 if (cd->factors[i] == TX_FACTOR_ANY)
631 34448 av_bprintf(&bp, "any");
632
2/2
✓ Branch 0 taken 53636 times.
✓ Branch 1 taken 35552 times.
89188 else if (cd->factors[i])
633 53636 av_bprintf(&bp, "%i", cd->factors[i]);
634 else
635 35552 break;
636 }
637
638 35552 av_bprintf(&bp, "], ");
639 } else {
640 19304 av_bprintf(&bp, "%s, factor: %i, ",
641
4/4
✓ Branch 0 taken 11811 times.
✓ Branch 1 taken 7493 times.
✓ Branch 2 taken 3904 times.
✓ Branch 3 taken 7907 times.
19304 !len && cd->min_len != cd->max_len ? "]" : "", cd->factors[0]);
642 }
643 54856 print_flags(&bp, cd->flags);
644
645
2/2
✓ Branch 0 taken 39770 times.
✓ Branch 1 taken 15086 times.
54856 if (print_prio)
646 39770 av_bprintf(&bp, ", prio: %i", prio);
647
648 54856 av_log(NULL, log_level, "%s\n", bp.str);
649 54856 }
650
651 15086 static void print_tx_structure(AVTXContext *s, int depth)
652 {
653 15086 const FFTXCodelet *cd = s->cd_self;
654
655
2/2
✓ Branch 0 taken 23800 times.
✓ Branch 1 taken 15086 times.
38886 for (int i = 0; i <= depth; i++)
656 23800 av_log(NULL, AV_LOG_DEBUG, " ");
657
658 15086 print_cd_info(cd, cd->prio, s->len, 0, AV_LOG_DEBUG);
659
660
2/2
✓ Branch 0 taken 7934 times.
✓ Branch 1 taken 15086 times.
23020 for (int i = 0; i < s->nb_sub; i++)
661 7934 print_tx_structure(&s->sub[i], depth + 1);
662 15086 }
663 #endif /* CONFIG_SMALL */
664
665 typedef struct TXCodeletMatch {
666 const FFTXCodelet *cd;
667 int prio;
668 } TXCodeletMatch;
669
670 40482 static int cmp_matches(TXCodeletMatch *a, TXCodeletMatch *b)
671 {
672 40482 return FFDIFFSIGN(b->prio, a->prio);
673 }
674
675 /* We want all factors to completely cover the length */
676 69119 static inline int check_cd_factors(const FFTXCodelet *cd, int len)
677 {
678 69119 int matches = 0, any_flag = 0;
679
680
1/2
✓ Branch 0 taken 210704 times.
✗ Branch 1 not taken.
210704 for (int i = 0; i < TX_MAX_FACTORS; i++) {
681 210704 int factor = cd->factors[i];
682
683
2/2
✓ Branch 0 taken 56342 times.
✓ Branch 1 taken 154362 times.
210704 if (factor == TX_FACTOR_ANY) {
684 56342 any_flag = 1;
685 56342 matches++;
686 56342 continue;
687
4/4
✓ Branch 0 taken 128582 times.
✓ Branch 1 taken 25780 times.
✓ Branch 2 taken 85243 times.
✓ Branch 3 taken 43339 times.
154362 } else if (len <= 1 || !factor) {
688 break;
689
2/2
✓ Branch 0 taken 33375 times.
✓ Branch 1 taken 51868 times.
85243 } else if (factor == 2) { /* Fast path */
690 33375 int bits_2 = ff_ctz(len);
691
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 33327 times.
33375 if (!bits_2)
692 48 continue; /* Factor not supported */
693
694 33327 len >>= bits_2;
695 33327 matches++;
696 } else {
697 51868 int res = len % factor;
698
2/2
✓ Branch 0 taken 44291 times.
✓ Branch 1 taken 7577 times.
51868 if (res)
699 44291 continue; /* Factor not supported */
700
701
2/2
✓ Branch 0 taken 7795 times.
✓ Branch 1 taken 7577 times.
15372 while (!res) {
702 7795 len /= factor;
703 7795 res = len % factor;
704 }
705 7577 matches++;
706 }
707 }
708
709
6/6
✓ Branch 0 taken 41243 times.
✓ Branch 1 taken 27876 times.
✓ Branch 2 taken 12005 times.
✓ Branch 3 taken 29238 times.
✓ Branch 4 taken 10532 times.
✓ Branch 5 taken 1473 times.
69119 return (cd->nb_factors <= matches) && (any_flag || len == 1);
710 }
711
712 15328 av_cold int ff_tx_init_subtx(AVTXContext *s, enum AVTXType type,
713 uint64_t flags, FFTXCodeletOptions *opts,
714 int len, int inv, const void *scale)
715 {
716 15328 int ret = 0;
717 15328 AVTXContext *sub = NULL;
718 15328 TXCodeletMatch *cd_tmp, *cd_matches = NULL;
719 15328 unsigned int cd_matches_size = 0;
720 15328 int codelet_list_idx = codelet_list_num;
721 15328 int nb_cd_matches = 0;
722 #if !CONFIG_SMALL
723 AVBPrint bp;
724 #endif
725
726 /* We still accept functions marked with SLOW, even if the CPU is
727 * marked with the same flag, but we give them lower priority. */
728 15328 const int cpu_flags = av_get_cpu_flags();
729
730 /* Flags the transform wants */
731 15328 uint64_t req_flags = flags;
732
733 /* Flags the codelet may require to be present */
734 15328 uint64_t inv_req_mask = AV_TX_FULL_IMDCT |
735 AV_TX_REAL_TO_REAL |
736 AV_TX_REAL_TO_IMAGINARY |
737 FF_TX_PRESHUFFLE |
738 FF_TX_ASM_CALL;
739
740 /* Unaligned codelets are compatible with the aligned flag */
741
1/2
✓ Branch 0 taken 15328 times.
✗ Branch 1 not taken.
15328 if (req_flags & FF_TX_ALIGNED)
742 15328 req_flags |= AV_TX_UNALIGNED;
743
744 /* If either flag is set, both are okay, so don't check for an exact match */
745
3/4
✓ Branch 0 taken 7890 times.
✓ Branch 1 taken 7438 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7890 times.
15328 if ((req_flags & AV_TX_INPLACE) && (req_flags & FF_TX_OUT_OF_PLACE))
746 ✗ req_flags &= ~(AV_TX_INPLACE | FF_TX_OUT_OF_PLACE);
747
2/4
✓ Branch 0 taken 15328 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15328 times.
✗ Branch 3 not taken.
15328 if ((req_flags & FF_TX_ALIGNED) && (req_flags & AV_TX_UNALIGNED))
748 15328 req_flags &= ~(FF_TX_ALIGNED | AV_TX_UNALIGNED);
749
750 /* Loop through all codelets in all codelet lists to find matches
751 * to the requirements */
752
2/2
✓ Branch 0 taken 76640 times.
✓ Branch 1 taken 15328 times.
91968 while (codelet_list_idx--) {
753 76640 const FFTXCodelet * const * list = codelet_list[codelet_list_idx];
754 76640 const FFTXCodelet *cd = NULL;
755
756
2/2
✓ Branch 0 taken 3310848 times.
✓ Branch 1 taken 76640 times.
3387488 while ((cd = *list++)) {
757 /* Check if the type matches */
758
4/4
✓ Branch 0 taken 3295520 times.
✓ Branch 1 taken 15328 times.
✓ Branch 2 taken 2599678 times.
✓ Branch 3 taken 695842 times.
3310848 if (cd->type != TX_TYPE_ANY && type != cd->type)
759 2599678 continue;
760
761 /* Check direction for non-orthogonal codelets */
762
4/4
✓ Branch 0 taken 89596 times.
✓ Branch 1 taken 621574 times.
✓ Branch 2 taken 9990 times.
✓ Branch 3 taken 79606 times.
711170 if (((cd->flags & FF_TX_FORWARD_ONLY) && inv) ||
763
4/4
✓ Branch 0 taken 76936 times.
✓ Branch 1 taken 554628 times.
✓ Branch 2 taken 70385 times.
✓ Branch 3 taken 6551 times.
631564 ((cd->flags & (FF_TX_INVERSE_ONLY | AV_TX_FULL_IMDCT)) && !inv) ||
764
3/4
✓ Branch 0 taken 9990 times.
✓ Branch 1 taken 615023 times.
✓ Branch 2 taken 9990 times.
✗ Branch 3 not taken.
625013 ((cd->flags & (FF_TX_FORWARD_ONLY | AV_TX_REAL_TO_REAL)) && inv) ||
765
3/4
✓ Branch 0 taken 9990 times.
✓ Branch 1 taken 615023 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9990 times.
625013 ((cd->flags & (FF_TX_FORWARD_ONLY | AV_TX_REAL_TO_IMAGINARY)) && inv))
766 86157 continue;
767
768 /* Check if the requested flags match from both sides */
769
2/2
✓ Branch 0 taken 381623 times.
✓ Branch 1 taken 243390 times.
625013 if (((req_flags & cd->flags) != (req_flags)) ||
770
2/2
✓ Branch 0 taken 85687 times.
✓ Branch 1 taken 295936 times.
381623 ((inv_req_mask & cd->flags) != (req_flags & inv_req_mask)))
771 329077 continue;
772
773 /* Check if length is supported */
774
6/6
✓ Branch 0 taken 201848 times.
✓ Branch 1 taken 94088 times.
✓ Branch 2 taken 138216 times.
✓ Branch 3 taken 63632 times.
✓ Branch 4 taken 114217 times.
✓ Branch 5 taken 23999 times.
295936 if ((len < cd->min_len) || (cd->max_len != -1 && (len > cd->max_len)))
775 208305 continue;
776
777 /* Check if the CPU supports the required ISA */
778
2/2
✓ Branch 0 taken 27085 times.
✓ Branch 1 taken 60546 times.
87631 if (cd->cpu_flags != FF_TX_CPU_FLAGS_ALL &&
779
2/2
✓ Branch 0 taken 18512 times.
✓ Branch 1 taken 8573 times.
27085 !(cpu_flags & (cd->cpu_flags & ~cpu_slow_mask)))
780 18512 continue;
781
782 /* Check for factors */
783
2/2
✓ Branch 1 taken 29349 times.
✓ Branch 2 taken 39770 times.
69119 if (!check_cd_factors(cd, len))
784 29349 continue;
785
786 /* Realloc array and append */
787 39770 cd_tmp = av_fast_realloc(cd_matches, &cd_matches_size,
788 39770 sizeof(*cd_tmp) * (nb_cd_matches + 1));
789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39770 times.
39770 if (!cd_tmp) {
790 ✗ av_free(cd_matches);
791 ✗ return AVERROR(ENOMEM);
792 }
793
794 39770 cd_matches = cd_tmp;
795 39770 cd_matches[nb_cd_matches].cd = cd;
796 39770 cd_matches[nb_cd_matches].prio = get_codelet_prio(cd, cpu_flags, len);
797 39770 nb_cd_matches++;
798 }
799 }
800
801 #if !CONFIG_SMALL
802 /* Print debugging info */
803 15328 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
804
2/2
✓ Branch 0 taken 13446 times.
✓ Branch 1 taken 1882 times.
15328 av_bprintf(&bp, "For transform of length %i, %s, ", len,
805 inv ? "inverse" : "forward");
806 15328 print_type(&bp, type);
807 15328 av_bprintf(&bp, ", ");
808 15328 print_flags(&bp, flags);
809
2/2
✓ Branch 0 taken 15086 times.
✓ Branch 1 taken 242 times.
15328 av_bprintf(&bp, ", found %i matches%s", nb_cd_matches,
810 nb_cd_matches ? ":" : ".");
811 #endif
812
813 /* No matches found */
814
2/2
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 15086 times.
15328 if (!nb_cd_matches)
815 242 return AVERROR(ENOSYS);
816
817 /* Sort the list */
818
44/44
✓ Branch 0 taken 7045 times.
✓ Branch 1 taken 10396 times.
✓ Branch 3 taken 1820 times.
✓ Branch 4 taken 5225 times.
✓ Branch 6 taken 484 times.
✓ Branch 7 taken 1336 times.
✓ Branch 9 taken 2330 times.
✓ Branch 10 taken 2895 times.
✓ Branch 12 taken 2648 times.
✓ Branch 13 taken 4397 times.
✓ Branch 14 taken 4223 times.
✓ Branch 15 taken 2822 times.
✓ Branch 16 taken 5260 times.
✓ Branch 17 taken 2110 times.
✓ Branch 19 taken 3745 times.
✓ Branch 20 taken 1515 times.
✓ Branch 21 taken 1565 times.
✓ Branch 22 taken 2728 times.
✓ Branch 24 taken 668 times.
✓ Branch 25 taken 897 times.
✓ Branch 26 taken 2728 times.
✓ Branch 27 taken 897 times.
✓ Branch 28 taken 3625 times.
✓ Branch 29 taken 2822 times.
✓ Branch 30 taken 1154 times.
✓ Branch 31 taken 1668 times.
✓ Branch 32 taken 377 times.
✓ Branch 33 taken 777 times.
✓ Branch 34 taken 316 times.
✓ Branch 35 taken 61 times.
✓ Branch 36 taken 2126 times.
✓ Branch 37 taken 198 times.
✓ Branch 39 taken 1231 times.
✓ Branch 40 taken 895 times.
✓ Branch 41 taken 198 times.
✓ Branch 42 taken 895 times.
✓ Branch 43 taken 1932 times.
✓ Branch 44 taken 692 times.
✓ Branch 46 taken 6521 times.
✓ Branch 47 taken 3875 times.
✓ Branch 48 taken 17441 times.
✓ Branch 49 taken 2893 times.
✓ Branch 50 taken 17710 times.
✓ Branch 51 taken 15086 times.
47511 AV_QSORT(cd_matches, nb_cd_matches, TXCodeletMatch, cmp_matches);
819
820 #if !CONFIG_SMALL
821 15086 av_log(NULL, AV_LOG_TRACE, "%s\n", bp.str);
822
823
2/2
✓ Branch 0 taken 39770 times.
✓ Branch 1 taken 15086 times.
54856 for (int i = 0; i < nb_cd_matches; i++) {
824 39770 av_log(NULL, AV_LOG_TRACE, " %i: ", i + 1);
825 39770 print_cd_info(cd_matches[i].cd, cd_matches[i].prio, 0, 1, AV_LOG_TRACE);
826 }
827 #endif
828
829
2/2
✓ Branch 0 taken 14989 times.
✓ Branch 1 taken 97 times.
15086 if (!s->sub) {
830 14989 s->sub = sub = av_mallocz(TX_MAX_SUB*sizeof(*sub));
831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14989 times.
14989 if (!sub) {
832 ✗ ret = AVERROR(ENOMEM);
833 ✗ goto end;
834 }
835 }
836
837 /* Attempt to initialize each */
838
1/2
✓ Branch 0 taken 20309 times.
✗ Branch 1 not taken.
20309 for (int i = 0; i < nb_cd_matches; i++) {
839 20309 const FFTXCodelet *cd = cd_matches[i].cd;
840 20309 AVTXContext *sctx = &s->sub[s->nb_sub];
841
842 20309 sctx->len = len;
843 20309 sctx->inv = inv;
844 20309 sctx->type = type;
845 20309 sctx->flags = cd->flags | flags;
846 20309 sctx->cd_self = cd;
847
848 20309 s->fn[s->nb_sub] = cd->function;
849 20309 s->cd[s->nb_sub] = cd;
850
851 20309 ret = 0;
852
2/2
✓ Branch 0 taken 20290 times.
✓ Branch 1 taken 19 times.
20309 if (cd->init)
853 20290 ret = cd->init(sctx, cd, flags, opts, len, inv, scale);
854
855
2/2
✓ Branch 0 taken 15086 times.
✓ Branch 1 taken 5223 times.
20309 if (ret >= 0) {
856
3/4
✓ Branch 0 taken 7753 times.
✓ Branch 1 taken 7333 times.
✓ Branch 2 taken 7753 times.
✗ Branch 3 not taken.
15086 if (opts && opts->map_dir != FF_TX_MAP_NONE &&
857
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 7731 times.
7753 sctx->map_dir == FF_TX_MAP_NONE) {
858 /* If a specific map direction was requested, and it doesn't
859 * exist, create one.*/
860 22 sctx->map = av_malloc(len*sizeof(*sctx->map));
861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (!sctx->map) {
862 ✗ ret = AVERROR(ENOMEM);
863 ✗ goto end;
864 }
865
866
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 22 times.
140 for (int i = 0; i < len; i++)
867 118 sctx->map[i] = i;
868
4/4
✓ Branch 0 taken 7731 times.
✓ Branch 1 taken 7333 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 7715 times.
15064 } else if (opts && (opts->map_dir != sctx->map_dir)) {
869 16 int *tmp = av_malloc(len*sizeof(*sctx->map));
870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (!tmp) {
871 ✗ ret = AVERROR(ENOMEM);
872 ✗ goto end;
873 }
874
875 16 memcpy(tmp, sctx->map, len*sizeof(*sctx->map));
876
877
2/2
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 16 times.
128 for (int i = 0; i < len; i++)
878 112 sctx->map[tmp[i]] = i;
879
880 16 av_free(tmp);
881 }
882
883 15086 s->nb_sub++;
884 15086 goto end;
885 }
886
887 5223 s->fn[s->nb_sub] = NULL;
888 5223 s->cd[s->nb_sub] = NULL;
889
890 5223 reset_ctx(sctx, 0);
891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5223 times.
5223 if (ret == AVERROR(ENOMEM))
892 ✗ break;
893 }
894
895 ✗ if (!s->nb_sub)
896 ✗ av_freep(&s->sub);
897
898 ✗ end:
899 15086 av_free(cd_matches);
900 15086 return ret;
901 }
902
903 7152 av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type,
904 int inv, int len, const void *scale, uint64_t flags)
905 {
906 int ret;
907 7152 AVTXContext tmp = { 0 };
908 7152 const double default_scale_d = 1.0;
909 7152 const float default_scale_f = 1.0f;
910
911
4/8
✓ Branch 0 taken 7152 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7152 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7152 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 7152 times.
7152 if (!len || type >= AV_TX_NB || !ctx || !tx)
912 ✗ return AVERROR(EINVAL);
913
914
1/2
✓ Branch 0 taken 7152 times.
✗ Branch 1 not taken.
7152 if (!(flags & AV_TX_UNALIGNED))
915 7152 flags |= FF_TX_ALIGNED;
916
1/2
✓ Branch 0 taken 7152 times.
✗ Branch 1 not taken.
7152 if (!(flags & AV_TX_INPLACE))
917 7152 flags |= FF_TX_OUT_OF_PLACE;
918
919
5/8
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 7140 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
7152 if (!scale && ((type == AV_TX_DOUBLE_MDCT) || (type == AV_TX_DOUBLE_DCT) ||
920
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 (type == AV_TX_DOUBLE_DCT_I) || (type == AV_TX_DOUBLE_DST_I) ||
921 (type == AV_TX_DOUBLE_RDFT)))
922 ✗ scale = &default_scale_d;
923
3/8
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 7140 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
7152 else if (!scale && !TYPE_IS(FFT, type))
924 ✗ scale = &default_scale_f;
925
926 7152 ret = ff_tx_init_subtx(&tmp, type, flags, NULL, len, inv, scale);
927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7152 times.
7152 if (ret < 0)
928 ✗ return ret;
929
930 7152 *ctx = &tmp.sub[0];
931 7152 *tx = tmp.fn[0];
932
933 #if !CONFIG_SMALL
934 7152 av_log(NULL, AV_LOG_DEBUG, "Transform tree:\n");
935 7152 print_tx_structure(*ctx, 0);
936 #endif
937
938 7152 return ret;
939 }
940