FFmpeg
tx.c
Go to the documentation of this file.
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 "qsort.h"
23 #include "bprint.h"
24 
25 #include "tx_priv.h"
26 
27 #define TYPE_IS(type, x) \
28  (((x) == AV_TX_FLOAT_ ## type) || \
29  ((x) == AV_TX_DOUBLE_ ## type) || \
30  ((x) == AV_TX_INT32_ ## type))
31 
32 /* Calculates the modular multiplicative inverse */
33 static av_always_inline int mulinv(int n, int m)
34 {
35  n = n % m;
36  for (int x = 1; x < m; x++)
37  if (((n * x) % m) == 1)
38  return x;
39  av_assert0(0); /* Never reached */
40  return 0;
41 }
42 
44  int d1, int d2)
45 {
46  const int sl = d1*d2;
47 
48  s->map = av_malloc(s->len*sizeof(*s->map));
49  if (!s->map)
50  return AVERROR(ENOMEM);
51 
52  for (int k = 0; k < s->len; k += sl) {
53  if (s->inv || (opts && opts->map_dir == FF_TX_MAP_SCATTER)) {
54  for (int m = 0; m < d2; m++)
55  for (int n = 0; n < d1; n++)
56  s->map[k + ((m*d1 + n*d2) % (sl))] = m*d1 + n;
57  } else {
58  for (int m = 0; m < d2; m++)
59  for (int n = 0; n < d1; n++)
60  s->map[k + m*d1 + n] = (m*d1 + n*d2) % (sl);
61  }
62 
63  if (s->inv)
64  for (int w = 1; w <= ((sl) >> 1); w++)
65  FFSWAP(int, s->map[k + w], s->map[k + sl - w]);
66  }
67 
68  s->map_dir = opts ? opts->map_dir : FF_TX_MAP_GATHER;
69 
70  return 0;
71 }
72 
73 /* Guaranteed to work for any n, m where gcd(n, m) == 1 */
75  int inv, int n, int m)
76 {
77  int *in_map, *out_map;
78  const int len = n*m; /* Will not be equal to s->len for MDCTs */
79  int m_inv, n_inv;
80 
81  /* Make sure the numbers are coprime */
82  if (av_gcd(n, m) != 1)
83  return AVERROR(EINVAL);
84 
85  m_inv = mulinv(m, n);
86  n_inv = mulinv(n, m);
87 
88  if (!(s->map = av_malloc(2*len*sizeof(*s->map))))
89  return AVERROR(ENOMEM);
90 
91  in_map = s->map;
92  out_map = s->map + len;
93 
94  /* Ruritanian map for input, CRT map for output, can be swapped */
95  if (opts && opts->map_dir == FF_TX_MAP_SCATTER) {
96  for (int j = 0; j < m; j++) {
97  for (int i = 0; i < n; i++) {
98  in_map[(i*m + j*n) % len] = j*n + i;
99  out_map[(i*m*m_inv + j*n*n_inv) % len] = i*m + j;
100  }
101  }
102  } else {
103  for (int j = 0; j < m; j++) {
104  for (int i = 0; i < n; i++) {
105  in_map[j*n + i] = (i*m + j*n) % len;
106  out_map[(i*m*m_inv + j*n*n_inv) % len] = i*m + j;
107  }
108  }
109  }
110 
111  if (inv) {
112  for (int i = 0; i < m; i++) {
113  int *in = &in_map[i*n + 1]; /* Skip the DC */
114  for (int j = 0; j < ((n - 1) >> 1); j++)
115  FFSWAP(int, in[j], in[n - j - 2]);
116  }
117  }
118 
119  s->map_dir = opts ? opts->map_dir : FF_TX_MAP_GATHER;
120 
121  return 0;
122 }
123 
124 static inline int split_radix_permutation(int i, int len, int inv)
125 {
126  len >>= 1;
127  if (len <= 1)
128  return i & 1;
129  if (!(i & len))
130  return split_radix_permutation(i, len, inv) * 2;
131  len >>= 1;
132  return split_radix_permutation(i, len, inv) * 4 + 1 - 2*(!(i & len) ^ inv);
133 }
134 
136 {
137  int len = s->len;
138 
139  if (!(s->map = av_malloc(len*sizeof(*s->map))))
140  return AVERROR(ENOMEM);
141 
142  if (opts && opts->map_dir == FF_TX_MAP_SCATTER) {
143  for (int i = 0; i < s->len; i++)
144  s->map[-split_radix_permutation(i, len, s->inv) & (len - 1)] = i;
145  } else {
146  for (int i = 0; i < s->len; i++)
147  s->map[i] = -split_radix_permutation(i, len, s->inv) & (len - 1);
148  }
149 
150  s->map_dir = opts ? opts->map_dir : FF_TX_MAP_GATHER;
151 
152  return 0;
153 }
154 
156 {
157  int *src_map, out_map_idx = 0;
158 
159  if (!s->sub || !s->sub->map)
160  return AVERROR(EINVAL);
161 
162  if (!(s->map = av_mallocz(len*sizeof(*s->map))))
163  return AVERROR(ENOMEM);
164 
165  src_map = s->sub->map;
166 
167  /* The first coefficient is always already in-place */
168  for (int src = 1; src < s->len; src++) {
169  int dst = src_map[src];
170  int found = 0;
171 
172  if (dst <= src)
173  continue;
174 
175  /* This just checks if a closed loop has been encountered before,
176  * and if so, skips it, since to fully permute a loop we must only
177  * enter it once. */
178  do {
179  for (int j = 0; j < out_map_idx; j++) {
180  if (dst == s->map[j]) {
181  found = 1;
182  break;
183  }
184  }
185  dst = src_map[dst];
186  } while (dst != src && !found);
187 
188  if (!found)
189  s->map[out_map_idx++] = src;
190  }
191 
192  s->map[out_map_idx++] = 0;
193 
194  return 0;
195 }
196 
197 static void parity_revtab_generator(int *revtab, int n, int inv, int offset,
198  int is_dual, int dual_high, int len,
199  int basis, int dual_stride, int inv_lookup)
200 {
201  len >>= 1;
202 
203  if (len <= basis) {
204  int k1, k2, stride, even_idx, odd_idx;
205 
206  is_dual = is_dual && dual_stride;
207  dual_high = is_dual & dual_high;
208  stride = is_dual ? FFMIN(dual_stride, len) : 0;
209 
210  even_idx = offset + dual_high*(stride - 2*len);
211  odd_idx = even_idx + len + (is_dual && !dual_high)*len + dual_high*len;
212 
213  for (int i = 0; i < len; i++) {
214  k1 = -split_radix_permutation(offset + i*2 + 0, n, inv) & (n - 1);
215  k2 = -split_radix_permutation(offset + i*2 + 1, n, inv) & (n - 1);
216  if (inv_lookup) {
217  revtab[even_idx++] = k1;
218  revtab[odd_idx++] = k2;
219  } else {
220  revtab[k1] = even_idx++;
221  revtab[k2] = odd_idx++;
222  }
223  if (stride && !((i + 1) % stride)) {
224  even_idx += stride;
225  odd_idx += stride;
226  }
227  }
228 
229  return;
230  }
231 
232  parity_revtab_generator(revtab, n, inv, offset,
233  0, 0, len >> 0, basis, dual_stride, inv_lookup);
234  parity_revtab_generator(revtab, n, inv, offset + (len >> 0),
235  1, 0, len >> 1, basis, dual_stride, inv_lookup);
236  parity_revtab_generator(revtab, n, inv, offset + (len >> 0) + (len >> 1),
237  1, 1, len >> 1, basis, dual_stride, inv_lookup);
238 }
239 
242  int basis, int dual_stride)
243 {
244  basis >>= 1;
245  if (len < basis)
246  return AVERROR(EINVAL);
247 
248  if (!(s->map = av_mallocz(len*sizeof(*s->map))))
249  return AVERROR(ENOMEM);
250 
251  av_assert0(!dual_stride || !(dual_stride & (dual_stride - 1)));
252  av_assert0(dual_stride <= basis);
253 
254  parity_revtab_generator(s->map, len, inv, 0, 0, 0, len,
255  basis, dual_stride,
256  opts ? opts->map_dir == FF_TX_MAP_GATHER : FF_TX_MAP_GATHER);
257 
258  s->map_dir = opts ? opts->map_dir : FF_TX_MAP_GATHER;
259 
260  return 0;
261 }
262 
263 static void reset_ctx(AVTXContext *s, int free_sub)
264 {
265  if (!s)
266  return;
267 
268  if (s->sub)
269  for (int i = 0; i < TX_MAX_SUB; i++)
270  reset_ctx(&s->sub[i], free_sub + 1);
271 
272  if (s->cd_self && s->cd_self->uninit)
273  s->cd_self->uninit(s);
274 
275  if (free_sub)
276  av_freep(&s->sub);
277 
278  av_freep(&s->map);
279  av_freep(&s->exp);
280  av_freep(&s->tmp);
281 
282  /* Nothing else needs to be reset, it gets overwritten if another
283  * ff_tx_init_subtx() call is made. */
284  s->nb_sub = 0;
285  s->opaque = NULL;
286  memset(s->fn, 0, sizeof(*s->fn));
287 }
288 
290 {
291  reset_ctx(s, 0);
292 }
293 
295 {
296  if (!(*ctx))
297  return;
298 
299  reset_ctx(*ctx, 1);
300  av_freep(ctx);
301 }
302 
304  uint64_t flags, FFTXCodeletOptions *opts,
305  int len, int inv, const void *scale)
306 {
307  /* Can only handle one sample+type to one sample+type transforms */
308  if (TYPE_IS(MDCT, s->type) || TYPE_IS(RDFT, s->type))
309  return AVERROR(EINVAL);
310  return 0;
311 }
312 
313 /* Null transform when the length is 1 */
314 static void ff_tx_null(AVTXContext *s, void *_out, void *_in, ptrdiff_t stride)
315 {
316  memcpy(_out, _in, stride);
317 }
318 
319 static const FFTXCodelet ff_tx_null_def = {
320  .name = NULL_IF_CONFIG_SMALL("null"),
321  .function = ff_tx_null,
322  .type = TX_TYPE_ANY,
323  .flags = AV_TX_UNALIGNED | FF_TX_ALIGNED |
325  .factors[0] = TX_FACTOR_ANY,
326  .min_len = 1,
327  .max_len = 1,
328  .init = ff_tx_null_init,
329  .cpu_flags = FF_TX_CPU_FLAGS_ALL,
330  .prio = FF_TX_PRIO_MAX,
331 };
332 
333 static const FFTXCodelet * const ff_tx_null_list[] = {
335  NULL,
336 };
337 
338 /* Array of all compiled codelet lists. Order is irrelevant. */
339 static const FFTXCodelet * const * const codelet_list[] = {
344 #if HAVE_X86ASM
346 #endif
347 #if ARCH_AARCH64
349 #endif
350 };
352 
356 
357 static const int cpu_slow_penalties[][2] = {
358  { AV_CPU_FLAG_SSE2SLOW, 1 + 64 },
359  { AV_CPU_FLAG_SSE3SLOW, 1 + 64 },
360  { AV_CPU_FLAG_SSSE3SLOW, 1 + 64 },
361  { AV_CPU_FLAG_ATOM, 1 + 128 },
362  { AV_CPU_FLAG_AVXSLOW, 1 + 128 },
363  { AV_CPU_FLAG_SLOW_GATHER, 1 + 32 },
364 };
365 
366 static int get_codelet_prio(const FFTXCodelet *cd, int cpu_flags, int len)
367 {
368  int prio = cd->prio;
369  int max_factor = 0;
370 
371  /* If the CPU has a SLOW flag, and the instruction is also flagged
372  * as being slow for such, reduce its priority */
373  for (int i = 0; i < FF_ARRAY_ELEMS(cpu_slow_penalties); i++) {
374  if ((cpu_flags & cd->cpu_flags) & cpu_slow_penalties[i][0])
375  prio -= cpu_slow_penalties[i][1];
376  }
377 
378  /* Prioritize aligned-only codelets */
379  if ((cd->flags & FF_TX_ALIGNED) && !(cd->flags & AV_TX_UNALIGNED))
380  prio += 64;
381 
382  /* Codelets for specific lengths are generally faster */
383  if ((len == cd->min_len) && (len == cd->max_len))
384  prio += 64;
385 
386  /* Forward-only or inverse-only transforms are generally better */
388  prio += 64;
389 
390  /* Larger factors are generally better */
391  for (int i = 0; i < TX_MAX_SUB; i++)
392  max_factor = FFMAX(cd->factors[i], max_factor);
393  if (max_factor)
394  prio += 16*max_factor;
395 
396  return prio;
397 }
398 
399 typedef struct FFTXLenDecomp {
400  int len;
401  int len2;
402  int prio;
403  const FFTXCodelet *cd;
404 } FFTXLenDecomp;
405 
407 {
408  return FFDIFFSIGN(b->prio, a->prio);
409 }
410 
412  int len, int inv)
413 {
414  int nb_decomp = 0;
416  int codelet_list_idx = codelet_list_num;
417 
418  const int cpu_flags = av_get_cpu_flags();
419 
420  /* Loop through all codelets in all codelet lists to find matches
421  * to the requirements */
422  while (codelet_list_idx--) {
423  const FFTXCodelet * const * list = codelet_list[codelet_list_idx];
424  const FFTXCodelet *cd = NULL;
425 
426  while ((cd = *list++)) {
427  int fl = len;
428  int skip = 0, prio;
429  int factors_product = 1, factors_mod = 0;
430 
431  if (nb_decomp >= TX_MAX_DECOMPOSITIONS)
432  goto sort;
433 
434  /* Check if the type matches */
435  if (cd->type != TX_TYPE_ANY && type != cd->type)
436  continue;
437 
438  /* Check direction for non-orthogonal codelets */
439  if (((cd->flags & FF_TX_FORWARD_ONLY) && inv) ||
440  ((cd->flags & (FF_TX_INVERSE_ONLY | AV_TX_FULL_IMDCT)) && !inv))
441  continue;
442 
443  /* Check if the CPU supports the required ISA */
444  if (cd->cpu_flags != FF_TX_CPU_FLAGS_ALL &&
445  !(cpu_flags & (cd->cpu_flags & ~cpu_slow_mask)))
446  continue;
447 
448  for (int i = 0; i < TX_MAX_FACTORS; i++) {
449  if (!cd->factors[i] || (fl == 1))
450  break;
451 
452  if (cd->factors[i] == TX_FACTOR_ANY) {
453  factors_mod++;
454  factors_product *= fl;
455  } else if (!(fl % cd->factors[i])) {
456  factors_mod++;
457  if (cd->factors[i] == 2) {
458  int b = ff_ctz(fl);
459  fl >>= b;
460  factors_product <<= b;
461  } else {
462  do {
463  fl /= cd->factors[i];
464  factors_product *= cd->factors[i];
465  } while (!(fl % cd->factors[i]));
466  }
467  }
468  }
469 
470  /* Disqualify if factor requirements are not satisfied or if trivial */
471  if ((factors_mod < cd->nb_factors) || (len == factors_product))
472  continue;
473 
474  if (av_gcd(factors_product, fl) != 1)
475  continue;
476 
477  /* Check if length is supported and factorization was successful */
478  if ((factors_product < cd->min_len) ||
479  (cd->max_len != TX_LEN_UNLIMITED && (factors_product > cd->max_len)))
480  continue;
481 
482  prio = get_codelet_prio(cd, cpu_flags, factors_product) * factors_product;
483 
484  /* Check for duplicates */
485  for (int i = 0; i < nb_decomp; i++) {
486  if (factors_product == ld[i].len) {
487  /* Update priority if new one is higher */
488  if (prio > ld[i].prio)
489  ld[i].prio = prio;
490  skip = 1;
491  break;
492  }
493  }
494 
495  /* Add decomposition if unique */
496  if (!skip) {
497  ld[nb_decomp].cd = cd;
498  ld[nb_decomp].len = factors_product;
499  ld[nb_decomp].len2 = fl;
500  ld[nb_decomp].prio = prio;
501  nb_decomp++;
502  }
503  }
504  }
505 
506  if (!nb_decomp)
507  return AVERROR(EINVAL);
508 
509 sort:
510  AV_QSORT(ld, nb_decomp, FFTXLenDecomp, cmp_decomp);
511 
512  for (int i = 0; i < nb_decomp; i++) {
513  if (ld[i].cd->nb_factors > 1)
514  dst[i] = ld[i].len2;
515  else
516  dst[i] = ld[i].len;
517  }
518 
519  return nb_decomp;
520 }
521 
523 {
524  s->map = av_malloc(s->len*sizeof(*s->map));
525  if (!s->map)
526  return AVERROR(ENOMEM);
527 
528  s->map[0] = 0; /* DC is always at the start */
529  if (s->inv) /* Reversing the ACs flips the transform direction */
530  for (int i = 1; i < s->len; i++)
531  s->map[i] = s->len - i;
532  else
533  for (int i = 1; i < s->len; i++)
534  s->map[i] = i;
535 
536  s->map_dir = FF_TX_MAP_GATHER;
537 
538  return 0;
539 }
540 
541 #if !CONFIG_SMALL
542 static void print_flags(AVBPrint *bp, uint64_t f)
543 {
544  int prev = 0;
545  const char *sep = ", ";
546  av_bprintf(bp, "flags: [");
547  if ((f & FF_TX_ALIGNED) && ++prev)
548  av_bprintf(bp, "aligned");
549  if ((f & AV_TX_UNALIGNED) && ++prev)
550  av_bprintf(bp, "%sunaligned", prev > 1 ? sep : "");
551  if ((f & AV_TX_INPLACE) && ++prev)
552  av_bprintf(bp, "%sinplace", prev > 1 ? sep : "");
553  if ((f & FF_TX_OUT_OF_PLACE) && ++prev)
554  av_bprintf(bp, "%sout_of_place", prev > 1 ? sep : "");
555  if ((f & FF_TX_FORWARD_ONLY) && ++prev)
556  av_bprintf(bp, "%sfwd_only", prev > 1 ? sep : "");
557  if ((f & FF_TX_INVERSE_ONLY) && ++prev)
558  av_bprintf(bp, "%sinv_only", prev > 1 ? sep : "");
559  if ((f & FF_TX_PRESHUFFLE) && ++prev)
560  av_bprintf(bp, "%spreshuf", prev > 1 ? sep : "");
561  if ((f & AV_TX_FULL_IMDCT) && ++prev)
562  av_bprintf(bp, "%simdct_full", prev > 1 ? sep : "");
563  if ((f & FF_TX_ASM_CALL) && ++prev)
564  av_bprintf(bp, "%sasm_call", prev > 1 ? sep : "");
565  av_bprintf(bp, "]");
566 }
567 
568 static void print_type(AVBPrint *bp, enum AVTXType type)
569 {
570  av_bprintf(bp, "%s",
571  type == TX_TYPE_ANY ? "any" :
572  type == AV_TX_FLOAT_FFT ? "fft_float" :
573  type == AV_TX_FLOAT_MDCT ? "mdct_float" :
574  type == AV_TX_FLOAT_RDFT ? "rdft_float" :
575  type == AV_TX_DOUBLE_FFT ? "fft_double" :
576  type == AV_TX_DOUBLE_MDCT ? "mdct_double" :
577  type == AV_TX_DOUBLE_RDFT ? "rdft_double" :
578  type == AV_TX_INT32_FFT ? "fft_int32" :
579  type == AV_TX_INT32_MDCT ? "mdct_int32" :
580  type == AV_TX_INT32_RDFT ? "rdft_int32" :
581  "unknown");
582 }
583 
584 static void print_cd_info(const FFTXCodelet *cd, int prio, int len, int print_prio)
585 {
586  AVBPrint bp = { 0 };
588 
589  av_bprintf(&bp, "%s - type: ", cd->name);
590 
591  print_type(&bp, cd->type);
592 
593  av_bprintf(&bp, ", len: ");
594  if (!len) {
595  if (cd->min_len != cd->max_len)
596  av_bprintf(&bp, "[%i, ", cd->min_len);
597 
598  if (cd->max_len == TX_LEN_UNLIMITED)
599  av_bprintf(&bp, "∞");
600  else
601  av_bprintf(&bp, "%i", cd->max_len);
602  } else {
603  av_bprintf(&bp, "%i", len);
604  }
605 
606  if (cd->factors[1]) {
607  av_bprintf(&bp, "%s, factors", !len && cd->min_len != cd->max_len ? "]" : "");
608  if (!cd->nb_factors)
609  av_bprintf(&bp, ": [");
610  else
611  av_bprintf(&bp, "[%i]: [", cd->nb_factors);
612 
613  for (int i = 0; i < TX_MAX_FACTORS; i++) {
614  if (i && cd->factors[i])
615  av_bprintf(&bp, ", ");
616  if (cd->factors[i] == TX_FACTOR_ANY)
617  av_bprintf(&bp, "any");
618  else if (cd->factors[i])
619  av_bprintf(&bp, "%i", cd->factors[i]);
620  else
621  break;
622  }
623 
624  av_bprintf(&bp, "], ");
625  } else {
626  av_bprintf(&bp, "%s, factor: %i, ",
627  !len && cd->min_len != cd->max_len ? "]" : "", cd->factors[0]);
628  }
629  print_flags(&bp, cd->flags);
630 
631  if (print_prio)
632  av_bprintf(&bp, ", prio: %i", prio);
633 
634  av_log(NULL, AV_LOG_DEBUG, "%s\n", bp.str);
635 }
636 
637 static void print_tx_structure(AVTXContext *s, int depth)
638 {
639  const FFTXCodelet *cd = s->cd_self;
640 
641  for (int i = 0; i <= depth; i++)
642  av_log(NULL, AV_LOG_DEBUG, " ");
643 
644  print_cd_info(cd, cd->prio, s->len, 0);
645 
646  for (int i = 0; i < s->nb_sub; i++)
647  print_tx_structure(&s->sub[i], depth + 1);
648 }
649 #endif /* CONFIG_SMALL */
650 
651 typedef struct TXCodeletMatch {
652  const FFTXCodelet *cd;
653  int prio;
655 
657 {
658  return FFDIFFSIGN(b->prio, a->prio);
659 }
660 
661 /* We want all factors to completely cover the length */
662 static inline int check_cd_factors(const FFTXCodelet *cd, int len)
663 {
664  int matches = 0, any_flag = 0;
665 
666  for (int i = 0; i < TX_MAX_FACTORS; i++) {
667  int factor = cd->factors[i];
668 
669  if (factor == TX_FACTOR_ANY) {
670  any_flag = 1;
671  matches++;
672  continue;
673  } else if (len <= 1 || !factor) {
674  break;
675  } else if (factor == 2) { /* Fast path */
676  int bits_2 = ff_ctz(len);
677  if (!bits_2)
678  continue; /* Factor not supported */
679 
680  len >>= bits_2;
681  matches++;
682  } else {
683  int res = len % factor;
684  if (res)
685  continue; /* Factor not supported */
686 
687  while (!res) {
688  len /= factor;
689  res = len % factor;
690  }
691  matches++;
692  }
693  }
694 
695  return (cd->nb_factors <= matches) && (any_flag || len == 1);
696 }
697 
699  uint64_t flags, FFTXCodeletOptions *opts,
700  int len, int inv, const void *scale)
701 {
702  int ret = 0;
703  AVTXContext *sub = NULL;
704  TXCodeletMatch *cd_tmp, *cd_matches = NULL;
705  unsigned int cd_matches_size = 0;
706  int codelet_list_idx = codelet_list_num;
707  int nb_cd_matches = 0;
708 #if !CONFIG_SMALL
709  AVBPrint bp = { 0 };
710 #endif
711 
712  /* We still accept functions marked with SLOW, even if the CPU is
713  * marked with the same flag, but we give them lower priority. */
714  const int cpu_flags = av_get_cpu_flags();
715 
716  /* Flags the transform wants */
717  uint64_t req_flags = flags;
718 
719  /* Flags the codelet may require to be present */
720  uint64_t inv_req_mask = AV_TX_FULL_IMDCT | FF_TX_PRESHUFFLE | FF_TX_ASM_CALL;
721 
722  /* Unaligned codelets are compatible with the aligned flag */
723  if (req_flags & FF_TX_ALIGNED)
724  req_flags |= AV_TX_UNALIGNED;
725 
726  /* If either flag is set, both are okay, so don't check for an exact match */
727  if ((req_flags & AV_TX_INPLACE) && (req_flags & FF_TX_OUT_OF_PLACE))
728  req_flags &= ~(AV_TX_INPLACE | FF_TX_OUT_OF_PLACE);
729  if ((req_flags & FF_TX_ALIGNED) && (req_flags & AV_TX_UNALIGNED))
730  req_flags &= ~(FF_TX_ALIGNED | AV_TX_UNALIGNED);
731 
732  /* Loop through all codelets in all codelet lists to find matches
733  * to the requirements */
734  while (codelet_list_idx--) {
735  const FFTXCodelet * const * list = codelet_list[codelet_list_idx];
736  const FFTXCodelet *cd = NULL;
737 
738  while ((cd = *list++)) {
739  /* Check if the type matches */
740  if (cd->type != TX_TYPE_ANY && type != cd->type)
741  continue;
742 
743  /* Check direction for non-orthogonal codelets */
744  if (((cd->flags & FF_TX_FORWARD_ONLY) && inv) ||
745  ((cd->flags & (FF_TX_INVERSE_ONLY | AV_TX_FULL_IMDCT)) && !inv))
746  continue;
747 
748  /* Check if the requested flags match from both sides */
749  if (((req_flags & cd->flags) != (req_flags)) ||
750  ((inv_req_mask & cd->flags) != (req_flags & inv_req_mask)))
751  continue;
752 
753  /* Check if length is supported */
754  if ((len < cd->min_len) || (cd->max_len != -1 && (len > cd->max_len)))
755  continue;
756 
757  /* Check if the CPU supports the required ISA */
758  if (cd->cpu_flags != FF_TX_CPU_FLAGS_ALL &&
759  !(cpu_flags & (cd->cpu_flags & ~cpu_slow_mask)))
760  continue;
761 
762  /* Check for factors */
763  if (!check_cd_factors(cd, len))
764  continue;
765 
766  /* Realloc array and append */
767  cd_tmp = av_fast_realloc(cd_matches, &cd_matches_size,
768  sizeof(*cd_tmp) * (nb_cd_matches + 1));
769  if (!cd_tmp) {
770  av_free(cd_matches);
771  return AVERROR(ENOMEM);
772  }
773 
774  cd_matches = cd_tmp;
775  cd_matches[nb_cd_matches].cd = cd;
776  cd_matches[nb_cd_matches].prio = get_codelet_prio(cd, cpu_flags, len);
777  nb_cd_matches++;
778  }
779  }
780 
781 #if !CONFIG_SMALL
782  /* Print debugging info */
784  av_bprintf(&bp, "For transform of length %i, %s, ", len,
785  inv ? "inverse" : "forward");
786  print_type(&bp, type);
787  av_bprintf(&bp, ", ");
788  print_flags(&bp, flags);
789  av_bprintf(&bp, ", found %i matches%s", nb_cd_matches,
790  nb_cd_matches ? ":" : ".");
791 #endif
792 
793  /* No matches found */
794  if (!nb_cd_matches)
795  return AVERROR(ENOSYS);
796 
797  /* Sort the list */
798  AV_QSORT(cd_matches, nb_cd_matches, TXCodeletMatch, cmp_matches);
799 
800 #if !CONFIG_SMALL
801  av_log(NULL, AV_LOG_DEBUG, "%s\n", bp.str);
802 
803  for (int i = 0; i < nb_cd_matches; i++) {
804  av_log(NULL, AV_LOG_DEBUG, " %i: ", i + 1);
805  print_cd_info(cd_matches[i].cd, cd_matches[i].prio, 0, 1);
806  }
807 #endif
808 
809  if (!s->sub) {
810  s->sub = sub = av_mallocz(TX_MAX_SUB*sizeof(*sub));
811  if (!sub) {
812  ret = AVERROR(ENOMEM);
813  goto end;
814  }
815  }
816 
817  /* Attempt to initialize each */
818  for (int i = 0; i < nb_cd_matches; i++) {
819  const FFTXCodelet *cd = cd_matches[i].cd;
820  AVTXContext *sctx = &s->sub[s->nb_sub];
821 
822  sctx->len = len;
823  sctx->inv = inv;
824  sctx->type = type;
825  sctx->flags = cd->flags | flags;
826  sctx->cd_self = cd;
827 
828  s->fn[s->nb_sub] = cd->function;
829  s->cd[s->nb_sub] = cd;
830 
831  ret = 0;
832  if (cd->init)
833  ret = cd->init(sctx, cd, flags, opts, len, inv, scale);
834 
835  if (ret >= 0) {
836  if (opts && opts->map_dir != FF_TX_MAP_NONE &&
837  sctx->map_dir == FF_TX_MAP_NONE) {
838  /* If a specific map direction was requested, and it doesn't
839  * exist, create one.*/
840  sctx->map = av_malloc(len*sizeof(*sctx->map));
841  if (!sctx->map) {
842  ret = AVERROR(ENOMEM);
843  goto end;
844  }
845 
846  for (int i = 0; i < len; i++)
847  sctx->map[i] = i;
848  } else if (opts && (opts->map_dir != sctx->map_dir)) {
849  int *tmp = av_malloc(len*sizeof(*sctx->map));
850  if (!tmp) {
851  ret = AVERROR(ENOMEM);
852  goto end;
853  }
854 
855  memcpy(tmp, sctx->map, len*sizeof(*sctx->map));
856 
857  for (int i = 0; i < len; i++)
858  sctx->map[tmp[i]] = i;
859 
860  av_free(tmp);
861  }
862 
863  s->nb_sub++;
864  goto end;
865  }
866 
867  s->fn[s->nb_sub] = NULL;
868  s->cd[s->nb_sub] = NULL;
869 
870  reset_ctx(sctx, 0);
871  if (ret == AVERROR(ENOMEM))
872  break;
873  }
874 
875  if (!s->nb_sub)
876  av_freep(&s->sub);
877 
878 end:
879  av_free(cd_matches);
880  return ret;
881 }
882 
884  int inv, int len, const void *scale, uint64_t flags)
885 {
886  int ret;
887  AVTXContext tmp = { 0 };
888  const double default_scale_d = 1.0;
889  const float default_scale_f = 1.0f;
890 
891  if (!len || type >= AV_TX_NB || !ctx || !tx)
892  return AVERROR(EINVAL);
893 
894  if (!(flags & AV_TX_UNALIGNED))
895  flags |= FF_TX_ALIGNED;
896  if (!(flags & AV_TX_INPLACE))
898 
899  if (!scale && ((type == AV_TX_FLOAT_MDCT) || (type == AV_TX_INT32_MDCT)))
900  scale = &default_scale_f;
901  else if (!scale && (type == AV_TX_DOUBLE_MDCT))
902  scale = &default_scale_d;
903 
904  ret = ff_tx_init_subtx(&tmp, type, flags, NULL, len, inv, scale);
905  if (ret < 0)
906  return ret;
907 
908  *ctx = &tmp.sub[0];
909  *tx = tmp.fn[0];
910 
911 #if !CONFIG_SMALL
912  av_log(NULL, AV_LOG_DEBUG, "Transform tree:\n");
913  print_tx_structure(*ctx, 0);
914 #endif
915 
916  return ret;
917 }
AV_TX_DOUBLE_MDCT
@ AV_TX_DOUBLE_MDCT
Definition: tx.h:69
AV_CPU_FLAG_SSSE3SLOW
#define AV_CPU_FLAG_SSSE3SLOW
SSSE3 supported, but usually not faster.
Definition: cpu.h:42
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
ff_ctz
#define ff_ctz
Definition: intmath.h:107
AVTXContext::map
int * map
Definition: tx_priv.h:233
TXCodeletMatch
Definition: tx.c:651
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
cmp_decomp
static int cmp_decomp(FFTXLenDecomp *a, FFTXLenDecomp *b)
Definition: tx.c:406
sub
static float sub(float src0, float src1)
Definition: dnn_backend_native_layer_mathbinary.c:31
AV_CPU_FLAG_SSE3SLOW
#define AV_CPU_FLAG_SSE3SLOW
SSE3 supported, but usually not faster.
Definition: cpu.h:39
AVTXContext
Definition: tx_priv.h:228
AVTXContext::map_dir
FFTXMapDirection map_dir
Definition: tx_priv.h:253
ff_tx_null_def
static const FFTXCodelet ff_tx_null_def
Definition: tx.c:319
basis
static int16_t basis[64][64]
Definition: mpegvideo_enc.c:4174
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
FFTXCodeletOptions
Definition: tx_priv.h:176
w
uint8_t w
Definition: llviddspenc.c:38
b
#define b
Definition: input.c:41
print_cd_info
static void print_cd_info(const FFTXCodelet *cd, int prio, int len, int print_prio)
Definition: tx.c:584
ff_tx_gen_split_radix_parity_revtab
int ff_tx_gen_split_radix_parity_revtab(AVTXContext *s, int len, int inv, FFTXCodeletOptions *opts, int basis, int dual_stride)
Definition: tx.c:240
TX_MAX_DECOMPOSITIONS
#define TX_MAX_DECOMPOSITIONS
Definition: tx_priv.h:190
ff_tx_gen_inplace_map
int ff_tx_gen_inplace_map(AVTXContext *s, int len)
Definition: tx.c:155
AV_TX_DOUBLE_FFT
@ AV_TX_DOUBLE_FFT
Definition: tx.h:48
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_get_cpu_flags
int av_get_cpu_flags(void)
Return the flags which specify extensions supported by the CPU.
Definition: cpu.c:103
FF_TX_CPU_FLAGS_ALL
#define FF_TX_CPU_FLAGS_ALL
Definition: tx_priv.h:223
ff_tx_gen_compound_mapping
int ff_tx_gen_compound_mapping(AVTXContext *s, FFTXCodeletOptions *opts, int inv, int n, int m)
Definition: tx.c:74
print_type
static void print_type(AVBPrint *bp, enum AVTXType type)
Definition: tx.c:568
cpu_flags
static atomic_int cpu_flags
Definition: cpu.c:52
cmp_matches
static int cmp_matches(TXCodeletMatch *a, TXCodeletMatch *b)
Definition: tx.c:656
print_flags
static void print_flags(AVBPrint *bp, uint64_t f)
Definition: tx.c:542
av_tx_init
av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags)
Initialize a transform context with the given configuration (i)MDCTs with an odd length are currently...
Definition: tx.c:883
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
av_gcd
int64_t av_gcd(int64_t a, int64_t b)
Compute the greatest common divisor of two integer operands.
Definition: mathematics.c:37
FFTXCodelet::nb_factors
int nb_factors
Definition: tx_priv.h:204
FF_TX_MAP_GATHER
@ FF_TX_MAP_GATHER
Definition: tx_priv.h:169
ff_tx_null_init
static av_cold int ff_tx_null_init(AVTXContext *s, const FFTXCodelet *cd, uint64_t flags, FFTXCodeletOptions *opts, int len, int inv, const void *scale)
Definition: tx.c:303
AV_BPRINT_SIZE_AUTOMATIC
#define AV_BPRINT_SIZE_AUTOMATIC
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
scale
static av_always_inline float scale(float x, float s)
Definition: vf_v360.c:1389
TX_MAX_SUB
#define TX_MAX_SUB
Definition: tx_priv.h:187
FFTXCodelet::min_len
int min_len
Definition: tx_priv.h:207
FF_TX_ALIGNED
#define FF_TX_ALIGNED
Definition: tx_priv.h:148
FFTXCodelet::type
enum AVTXType type
Definition: tx_priv.h:195
FFDIFFSIGN
#define FFDIFFSIGN(x, y)
Comparator.
Definition: macros.h:45
AV_CPU_FLAG_SLOW_GATHER
#define AV_CPU_FLAG_SLOW_GATHER
CPU has slow gathers.
Definition: cpu.h:58
avassert.h
FFTXCodelet::factors
int factors[TX_MAX_FACTORS]
Definition: tx_priv.h:201
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
AV_TX_NB
@ AV_TX_NB
Definition: tx.h:109
av_tx_fn
void(* av_tx_fn)(AVTXContext *s, void *out, void *in, ptrdiff_t stride)
Function pointer to a function to perform the transform.
Definition: tx.h:127
AV_TX_FLOAT_MDCT
@ AV_TX_FLOAT_MDCT
Standard MDCT with a sample data type of float, double or int32_t, respecively.
Definition: tx.h:68
av_fast_realloc
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition: mem.c:505
s
#define s(width, name)
Definition: cbs_vp9.c:256
FFTXCodelet::flags
uint64_t flags
Definition: tx_priv.h:198
FFTXCodelet::prio
int prio
Definition: tx_priv.h:225
AV_TX_INT32_MDCT
@ AV_TX_INT32_MDCT
Definition: tx.h:70
AVTXContext::type
enum AVTXType type
Definition: tx_priv.h:250
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
FF_TX_FORWARD_ONLY
#define FF_TX_FORWARD_ONLY
Definition: tx_priv.h:151
AVTXContext::len
int len
Definition: tx_priv.h:231
AV_TX_FLOAT_FFT
@ AV_TX_FLOAT_FFT
Standard complex to complex FFT with sample data type of AVComplexFloat, AVComplexDouble or AVComplex...
Definition: tx.h:47
split_radix_permutation
static int split_radix_permutation(int i, int len, int inv)
Definition: tx.c:124
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
FFTXCodelet::cpu_flags
int cpu_flags
Definition: tx_priv.h:220
codelet_list_num
static const int codelet_list_num
Definition: tx.c:351
TX_TYPE_ANY
#define TX_TYPE_ANY
Definition: tx_priv.h:196
AV_TX_FULL_IMDCT
@ AV_TX_FULL_IMDCT
Performs a full inverse MDCT rather than leaving out samples that can be derived through symmetry.
Definition: tx.h:151
opts
AVDictionary * opts
Definition: movenc.c:50
FFTXLenDecomp::len2
int len2
Definition: tx.c:401
TXCodeletMatch::cd
const FFTXCodelet * cd
Definition: tx.c:652
NULL
#define NULL
Definition: coverity.c:32
AV_TX_INPLACE
@ AV_TX_INPLACE
Allows for in-place transformations, where input == output.
Definition: tx.h:137
ff_tx_gen_ptwo_revtab
int ff_tx_gen_ptwo_revtab(AVTXContext *s, FFTXCodeletOptions *opts)
Definition: tx.c:135
ff_tx_null
static void ff_tx_null(AVTXContext *s, void *_out, void *_in, ptrdiff_t stride)
Definition: tx.c:314
cpu_slow_mask
static const int cpu_slow_mask
Definition: tx.c:353
FF_TX_OUT_OF_PLACE
#define FF_TX_OUT_OF_PLACE
Definition: tx_priv.h:147
list
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining list
Definition: filter_design.txt:25
FF_TX_PRIO_MAX
@ FF_TX_PRIO_MAX
Definition: tx_priv.h:161
FFTXCodelet::init
int(* init)(AVTXContext *s, const struct FFTXCodelet *cd, uint64_t flags, FFTXCodeletOptions *opts, int len, int inv, const void *scale)
Definition: tx_priv.h:211
AV_TX_UNALIGNED
@ AV_TX_UNALIGNED
Relaxes alignment requirement for the in and out arrays of av_tx_fn().
Definition: tx.h:143
get_codelet_prio
static int get_codelet_prio(const FFTXCodelet *cd, int cpu_flags, int len)
Definition: tx.c:366
TXCodeletMatch::prio
int prio
Definition: tx.c:653
ff_tx_clear_ctx
void ff_tx_clear_ctx(AVTXContext *s)
Definition: tx.c:289
qsort.h
FF_TX_PRESHUFFLE
#define FF_TX_PRESHUFFLE
Definition: tx_priv.h:149
reset_ctx
static void reset_ctx(AVTXContext *s, int free_sub)
Definition: tx.c:263
ff_tx_gen_default_map
int ff_tx_gen_default_map(AVTXContext *s, FFTXCodeletOptions *opts)
Definition: tx.c:522
f
f
Definition: af_crystalizer.c:122
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:115
AV_CPU_FLAG_AVXSLOW
#define AV_CPU_FLAG_AVXSLOW
AVX supported, but slow when using YMM registers (e.g. Bulldozer)
Definition: cpu.h:48
cpu.h
AVTXType
AVTXType
Definition: tx.h:39
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
ff_tx_codelet_list_float_aarch64
const FFTXCodelet *const ff_tx_codelet_list_float_aarch64[]
Definition: tx_float_init.c:47
AV_CPU_FLAG_SSE2SLOW
#define AV_CPU_FLAG_SSE2SLOW
SSE2 supported, but usually not faster.
Definition: cpu.h:35
AV_TX_INT32_FFT
@ AV_TX_INT32_FFT
Definition: tx.h:49
ff_tx_codelet_list_double_c
const FFTXCodelet *const ff_tx_codelet_list_double_c[]
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
FFTXLenDecomp::cd
const FFTXCodelet * cd
Definition: tx.c:403
AVTXContext::inv
int inv
Definition: tx_priv.h:232
av_tx_uninit
av_cold void av_tx_uninit(AVTXContext **ctx)
Frees a context and sets *ctx to NULL, does nothing when *ctx == NULL.
Definition: tx.c:294
FFTXCodelet::max_len
int max_len
Definition: tx_priv.h:208
cpu_slow_penalties
static const int cpu_slow_penalties[][2]
Definition: tx.c:357
bprint.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AV_QSORT
#define AV_QSORT(p, num, type, cmp)
Quicksort This sort is fast, and fully inplace but not stable and it is possible to construct input t...
Definition: qsort.h:33
av_always_inline
#define av_always_inline
Definition: attributes.h:49
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AV_TX_DOUBLE_RDFT
@ AV_TX_DOUBLE_RDFT
Definition: tx.h:91
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:264
len
int len
Definition: vorbis_enc_data.h:426
FF_TX_MAP_SCATTER
@ FF_TX_MAP_SCATTER
Definition: tx_priv.h:172
TX_LEN_UNLIMITED
#define TX_LEN_UNLIMITED
Definition: tx_priv.h:209
stride
#define stride
Definition: h264pred_template.c:537
AV_CPU_FLAG_ATOM
#define AV_CPU_FLAG_ATOM
Atom processor, some SSSE3 instructions are slower.
Definition: cpu.h:43
tx_priv.h
FFTXLenDecomp::len
int len
Definition: tx.c:400
AVTXContext::flags
uint64_t flags
Definition: tx_priv.h:251
ret
ret
Definition: filter_design.txt:187
ff_tx_init_subtx
av_cold int ff_tx_init_subtx(AVTXContext *s, enum AVTXType type, uint64_t flags, FFTXCodeletOptions *opts, int len, int inv, const void *scale)
Definition: tx.c:698
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
TX_FACTOR_ANY
#define TX_FACTOR_ANY
Definition: tx_priv.h:202
FF_TX_INVERSE_ONLY
#define FF_TX_INVERSE_ONLY
Definition: tx_priv.h:150
FFTXLenDecomp::prio
int prio
Definition: tx.c:402
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:94
ff_tx_codelet_list_float_c
const FFTXCodelet *const ff_tx_codelet_list_float_c[]
FFTXLenDecomp
Definition: tx.c:399
AV_TX_FLOAT_RDFT
@ AV_TX_FLOAT_RDFT
Real to complex and complex to real DFTs.
Definition: tx.h:90
FF_TX_MAP_NONE
@ FF_TX_MAP_NONE
Definition: tx_priv.h:166
FFTXCodelet
Definition: tx_priv.h:192
check_cd_factors
static int check_cd_factors(const FFTXCodelet *cd, int len)
Definition: tx.c:662
AV_TX_INT32_RDFT
@ AV_TX_INT32_RDFT
Definition: tx.h:92
AVTXContext::cd_self
const FFTXCodelet * cd_self
Definition: tx_priv.h:249
FFTXCodelet::name
const char * name
Definition: tx_priv.h:193
factor
static const int factor[16]
Definition: vf_pp7.c:76
FF_TX_ASM_CALL
#define FF_TX_ASM_CALL
Definition: tx_priv.h:152
ff_tx_codelet_list_float_x86
const FFTXCodelet *const ff_tx_codelet_list_float_x86[]
Definition: tx_float_init.c:230
print_tx_structure
static void print_tx_structure(AVTXContext *s, int depth)
Definition: tx.c:637
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
ff_tx_null_list
static const FFTXCodelet *const ff_tx_null_list[]
Definition: tx.c:333
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
mulinv
static av_always_inline int mulinv(int n, int m)
Definition: tx.c:33
ff_tx_codelet_list_int32_c
const FFTXCodelet *const ff_tx_codelet_list_int32_c[]
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
TX_MAX_FACTORS
#define TX_MAX_FACTORS
Definition: tx_priv.h:184
ff_tx_gen_pfa_input_map
int ff_tx_gen_pfa_input_map(AVTXContext *s, FFTXCodeletOptions *opts, int d1, int d2)
Definition: tx.c:43
TYPE_IS
#define TYPE_IS(type, x)
Definition: tx.c:27
FFTXCodelet::function
av_tx_fn function
Definition: tx_priv.h:194
parity_revtab_generator
static void parity_revtab_generator(int *revtab, int n, int inv, int offset, int is_dual, int dual_high, int len, int basis, int dual_stride, int inv_lookup)
Definition: tx.c:197
ff_tx_decompose_length
int ff_tx_decompose_length(int dst[TX_MAX_DECOMPOSITIONS], enum AVTXType type, int len, int inv)
Definition: tx.c:411
codelet_list
static const FFTXCodelet *const *const codelet_list[]
Definition: tx.c:339
intmath.h