diff mbox series

[FFmpeg-devel,06/11] lavu/tx: add full-sized iMDCT transform flag

Message ID MYfnRrc--3-2@lynne.ee
State Accepted
Commit 0072a4238817c18e31e1f59cf8ec9a30bdf42a5c
Headers show
Series lavu/tx: FFT improvements, additions and assembly
Related show

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Lynne April 19, 2021, 8:23 p.m. UTC
Patch attached.
Subject: [PATCH 06/11] lavu/tx: add full-sized iMDCT transform flag

---
 libavutil/tx.h          | 11 ++++++++++-
 libavutil/tx_priv.h     |  4 ++++
 libavutil/tx_template.c | 29 ++++++++++++++++++++++++++++-
 3 files changed, 42 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/libavutil/tx.h b/libavutil/tx.h
index a3d70644e4..55173810ee 100644
--- a/libavutil/tx.h
+++ b/libavutil/tx.h
@@ -55,7 +55,8 @@  enum AVTXType {
      * Stride must be a non-zero multiple of sizeof(float).
      *
      * NOTE: the inverse transform is half-length, meaning the output will not
-     * contain redundant data. This is what most codecs work with.
+     * contain redundant data. This is what most codecs work with. To do a full
+     * inverse transform, set the AV_TX_FULL_IMDCT flag on init.
      */
     AV_TX_FLOAT_MDCT = 1,
 
@@ -116,6 +117,14 @@  enum AVTXFlags {
      * May be slower with certain transform types.
      */
     AV_TX_UNALIGNED = 1ULL << 1,
+
+    /**
+     * Performs a full inverse MDCT rather than leaving out samples that can be
+     * derived through symmetry. Requires an output array of 'len' floats,
+     * rather than the usual 'len/2' floats.
+     * Ignored for all transforms but inverse MDCTs.
+     */
+    AV_TX_FULL_IMDCT = 1ULL << 2,
 };
 
 /**
diff --git a/libavutil/tx_priv.h b/libavutil/tx_priv.h
index 0b40234355..1d4245e71b 100644
--- a/libavutil/tx_priv.h
+++ b/libavutil/tx_priv.h
@@ -121,6 +121,10 @@  struct AVTXContext {
     int        *pfatab; /* Input/Output mapping for compound transforms */
     int        *revtab; /* Input mapping for power of two transforms */
     int   *inplace_idx; /* Required indices to revtab for in-place transforms */
+
+    av_tx_fn    top_tx; /* Used for computing transforms derived from other
+                         * transforms, like full-length iMDCTs and RDFTs.
+                         * NOTE: Do NOT use this to mix assembly with C code. */
 };
 
 /* Checks if type is an MDCT */
diff --git a/libavutil/tx_template.c b/libavutil/tx_template.c
index b3532c1c5e..a68a84dcd5 100644
--- a/libavutil/tx_template.c
+++ b/libavutil/tx_template.c
@@ -875,6 +875,24 @@  static void naive_mdct(AVTXContext *s, void *_dst, void *_src,
     }
 }
 
+static void full_imdct_wrapper_fn(AVTXContext *s, void *_dst, void *_src,
+                                  ptrdiff_t stride)
+{
+    int len = s->m*s->n*4;
+    int len2 = len >> 1;
+    int len4 = len >> 2;
+    FFTSample *dst = _dst;
+
+    s->top_tx(s, dst + len4, _src, stride);
+
+    stride /= sizeof(*dst);
+
+    for (int i = 0; i < len4; i++) {
+        dst[            i*stride] = -dst[(len2 - i - 1)*stride];
+        dst[(len - i - 1)*stride] =  dst[(len2 + i + 0)*stride];
+    }
+}
+
 static int gen_mdct_exptab(AVTXContext *s, int len4, double scale)
 {
     const double theta = (scale < 0 ? len4 : 0) + 1.0/8.0;
@@ -942,6 +960,10 @@  int TX_NAME(ff_tx_init_mdct_fft)(AVTXContext *s, av_tx_fn *tx,
         if (is_mdct) {
             s->scale = *((SCALE_TYPE *)scale);
             *tx = inv ? naive_imdct : naive_mdct;
+            if (inv && (flags & AV_TX_FULL_IMDCT)) {
+                s->top_tx = *tx;
+                *tx = full_imdct_wrapper_fn;
+            }
         }
         return 0;
     }
@@ -990,8 +1012,13 @@  int TX_NAME(ff_tx_init_mdct_fft)(AVTXContext *s, av_tx_fn *tx,
             init_cos_tabs(i);
     }
 
-    if (is_mdct)
+    if (is_mdct) {
+        if (inv && (flags & AV_TX_FULL_IMDCT)) {
+            s->top_tx = *tx;
+            *tx = full_imdct_wrapper_fn;
+        }
         return gen_mdct_exptab(s, n*m, *((SCALE_TYPE *)scale));
+    }
 
     return 0;
 }