You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

198 lines
5.1KB

  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. #include "tx_priv.h"
  19. int ff_tx_type_is_mdct(enum AVTXType type)
  20. {
  21. switch (type) {
  22. case AV_TX_FLOAT_MDCT:
  23. case AV_TX_DOUBLE_MDCT:
  24. case AV_TX_INT32_MDCT:
  25. return 1;
  26. default:
  27. return 0;
  28. }
  29. }
  30. /* Calculates the modular multiplicative inverse, not fast, replace */
  31. static av_always_inline int mulinv(int n, int m)
  32. {
  33. n = n % m;
  34. for (int x = 1; x < m; x++)
  35. if (((n * x) % m) == 1)
  36. return x;
  37. av_assert0(0); /* Never reached */
  38. }
  39. /* Guaranteed to work for any n, m where gcd(n, m) == 1 */
  40. int ff_tx_gen_compound_mapping(AVTXContext *s)
  41. {
  42. int *in_map, *out_map;
  43. const int n = s->n;
  44. const int m = s->m;
  45. const int inv = s->inv;
  46. const int len = n*m;
  47. const int m_inv = mulinv(m, n);
  48. const int n_inv = mulinv(n, m);
  49. const int mdct = ff_tx_type_is_mdct(s->type);
  50. if (!(s->pfatab = av_malloc(2*len*sizeof(*s->pfatab))))
  51. return AVERROR(ENOMEM);
  52. in_map = s->pfatab;
  53. out_map = s->pfatab + n*m;
  54. /* Ruritanian map for input, CRT map for output, can be swapped */
  55. for (int j = 0; j < m; j++) {
  56. for (int i = 0; i < n; i++) {
  57. /* Shifted by 1 to simplify MDCTs */
  58. in_map[j*n + i] = ((i*m + j*n) % len) << mdct;
  59. out_map[(i*m*m_inv + j*n*n_inv) % len] = i*m + j;
  60. }
  61. }
  62. /* Change transform direction by reversing all ACs */
  63. if (inv) {
  64. for (int i = 0; i < m; i++) {
  65. int *in = &in_map[i*n + 1]; /* Skip the DC */
  66. for (int j = 0; j < ((n - 1) >> 1); j++)
  67. FFSWAP(int, in[j], in[n - j - 2]);
  68. }
  69. }
  70. /* Our 15-point transform is also a compound one, so embed its input map */
  71. if (n == 15) {
  72. for (int k = 0; k < m; k++) {
  73. int tmp[15];
  74. memcpy(tmp, &in_map[k*15], 15*sizeof(*tmp));
  75. for (int i = 0; i < 5; i++) {
  76. for (int j = 0; j < 3; j++)
  77. in_map[k*15 + i*3 + j] = tmp[(i*3 + j*5) % 15];
  78. }
  79. }
  80. }
  81. return 0;
  82. }
  83. int ff_tx_gen_ptwo_revtab(AVTXContext *s, int invert_lookup)
  84. {
  85. const int m = s->m, inv = s->inv;
  86. if (!(s->revtab = av_malloc(m*sizeof(*s->revtab))))
  87. return AVERROR(ENOMEM);
  88. /* Default */
  89. for (int i = 0; i < m; i++) {
  90. int k = -split_radix_permutation(i, m, inv) & (m - 1);
  91. if (invert_lookup)
  92. s->revtab[i] = k;
  93. else
  94. s->revtab[k] = i;
  95. }
  96. return 0;
  97. }
  98. int ff_tx_gen_ptwo_inplace_revtab_idx(AVTXContext *s)
  99. {
  100. int nb_inplace_idx = 0;
  101. if (!(s->inplace_idx = av_malloc(s->m*sizeof(*s->inplace_idx))))
  102. return AVERROR(ENOMEM);
  103. for (int src = 1; src < s->m; src++) {
  104. int dst = s->revtab[src];
  105. int found = 0;
  106. if (dst <= src)
  107. continue;
  108. do {
  109. for (int j = 0; j < nb_inplace_idx; j++) {
  110. if (dst == s->inplace_idx[j]) {
  111. found = 1;
  112. break;
  113. }
  114. }
  115. dst = s->revtab[dst];
  116. } while (dst != src && !found);
  117. if (!found)
  118. s->inplace_idx[nb_inplace_idx++] = src;
  119. }
  120. s->inplace_idx[nb_inplace_idx++] = 0;
  121. return 0;
  122. }
  123. av_cold void av_tx_uninit(AVTXContext **ctx)
  124. {
  125. if (!(*ctx))
  126. return;
  127. av_free((*ctx)->pfatab);
  128. av_free((*ctx)->exptab);
  129. av_free((*ctx)->revtab);
  130. av_free((*ctx)->inplace_idx);
  131. av_free((*ctx)->tmp);
  132. av_freep(ctx);
  133. }
  134. av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type,
  135. int inv, int len, const void *scale, uint64_t flags)
  136. {
  137. int err;
  138. AVTXContext *s = av_mallocz(sizeof(*s));
  139. if (!s)
  140. return AVERROR(ENOMEM);
  141. switch (type) {
  142. case AV_TX_FLOAT_FFT:
  143. case AV_TX_FLOAT_MDCT:
  144. if ((err = ff_tx_init_mdct_fft_float(s, tx, type, inv, len, scale, flags)))
  145. goto fail;
  146. break;
  147. case AV_TX_DOUBLE_FFT:
  148. case AV_TX_DOUBLE_MDCT:
  149. if ((err = ff_tx_init_mdct_fft_double(s, tx, type, inv, len, scale, flags)))
  150. goto fail;
  151. break;
  152. case AV_TX_INT32_FFT:
  153. case AV_TX_INT32_MDCT:
  154. if ((err = ff_tx_init_mdct_fft_int32(s, tx, type, inv, len, scale, flags)))
  155. goto fail;
  156. break;
  157. default:
  158. err = AVERROR(EINVAL);
  159. goto fail;
  160. }
  161. *ctx = s;
  162. return 0;
  163. fail:
  164. av_tx_uninit(&s);
  165. *tx = NULL;
  166. return err;
  167. }