From 3a3db14c5792e0892e4c0ca0e507a24048c6a1e2 Mon Sep 17 00:00:00 2001
From: Daniil Cherednik <dan.cherednik@gmail.com>
Date: Sat, 27 Jan 2018 23:19:55 +0000
Subject: [PATCH 1/2] avcodec/dcaenc: Use planar float frame format

Signed-off-by: Daniil Cherednik <dan.cherednik@gmail.com>
---
 libavcodec/dcaenc.c   | 72 ++++++++++++++++++++++++++++-----------------------
 tests/fate/acodec.mak | 21 +++++----------
 2 files changed, 46 insertions(+), 47 deletions(-)

diff --git a/libavcodec/dcaenc.c b/libavcodec/dcaenc.c
index 186997c631..da1d7411de 100644
--- a/libavcodec/dcaenc.c
+++ b/libavcodec/dcaenc.c
@@ -29,6 +29,7 @@
 #include "libavutil/common.h"
 #include "libavutil/ffmath.h"
 #include "libavutil/opt.h"
+#include "libswresample/swresample.h"
 #include "avcodec.h"
 #include "dca.h"
 #include "dcaadpcm.h"
@@ -64,6 +65,7 @@ typedef struct DCAEncContext {
     DCAADPCMEncContext adpcm_ctx;
     FFTContext mdct;
     CompressionOptions options;
+    SwrContext *swr;
     int frame_size;
     int frame_bits;
     int fullband_channels;
@@ -242,6 +244,15 @@ static int encode_init(AVCodecContext *avctx)
     if ((ret = ff_mdct_init(&c->mdct, 9, 0, 1.0)) < 0)
         return ret;
 
+    c->swr = swr_alloc_set_opts(NULL,
+                                AV_CH_LAYOUT_MONO, AV_SAMPLE_FMT_S32P, avctx->sample_rate,
+                                AV_CH_LAYOUT_MONO, avctx->sample_fmt, avctx->sample_rate,
+                                0, NULL);
+    if ((ret = swr_init(c->swr)) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Error opening the resampler.\n");
+        return ret;
+    }
+
     /* Init all tables */
     c->cos_table[0] = 0x7fffffff;
     c->cos_table[512] = 0;
@@ -305,6 +316,7 @@ static int encode_init(AVCodecContext *avctx)
 static av_cold int encode_close(AVCodecContext *avctx)
 {
     DCAEncContext *c = avctx->priv_data;
+    swr_free(&c->swr);
     ff_mdct_end(&c->mdct);
     subband_bufer_free(c);
     ff_dcaadpcm_free(&c->adpcm_ctx);
@@ -312,22 +324,21 @@ static av_cold int encode_close(AVCodecContext *avctx)
     return 0;
 }
 
-static void subband_transform(DCAEncContext *c, const int32_t *input)
+static void subband_transform(DCAEncContext *c, const float **input)
 {
     int ch, subs, i, k, j;
 
     for (ch = 0; ch < c->fullband_channels; ch++) {
-        /* History is copied because it is also needed for PSY */
-        int32_t hist[512];
         int hist_start = 0;
         const int chi = c->channel_order_tab[ch];
-
-        memcpy(hist, &c->history[ch][0], 512 * sizeof(int32_t));
+        int32_t *hist = c->history[ch];
 
         for (subs = 0; subs < SUBBAND_SAMPLES; subs++) {
             int32_t accum[64];
             int32_t resp;
             int band;
+            int32_t * const to = hist + hist_start;
+            const float* from = &input[chi][subs * 32];
 
             /* Calculate the convolutions at once */
             memset(accum, 0, 64 * sizeof(int32_t));
@@ -354,26 +365,28 @@ static void subband_transform(DCAEncContext *c, const int32_t *input)
             }
 
             /* Copy in 32 new samples from input */
-            for (i = 0; i < 32; i++)
-                hist[i + hist_start] = input[(subs * 32 + i) * c->channels + chi];
+            swr_convert(c->swr,
+                        (uint8_t**)&to, 32,
+                        (const uint8_t**)&from, 32);
 
             hist_start = (hist_start + 32) & 511;
         }
     }
 }
 
-static void lfe_downsample(DCAEncContext *c, const int32_t *input)
+static void lfe_downsample(DCAEncContext *c, const float **input)
 {
     /* FIXME: make 128x LFE downsampling possible */
     const int lfech = lfe_index[c->channel_config];
     int i, j, lfes;
-    int32_t hist[512];
+    int32_t *hist = c->history[c->channels - 1];
     int32_t accum;
     int hist_start = 0;
 
-    memcpy(hist, &c->history[c->channels - 1][0], 512 * sizeof(int32_t));
-
     for (lfes = 0; lfes < DCA_LFE_SAMPLES; lfes++) {
+        int32_t * const to = hist + hist_start;
+        const float* from = &input[lfech][lfes * 64];
+
         /* Calculate the convolution */
         accum = 0;
 
@@ -385,8 +398,9 @@ static void lfe_downsample(DCAEncContext *c, const int32_t *input)
         c->downsampled_lfe[lfes] = accum;
 
         /* Copy in 64 new samples from input */
-        for (i = 0; i < 64; i++)
-            hist[i + hist_start] = input[(lfes * 64 + i) * c->channels + lfech];
+        swr_convert(c->swr,
+                    (uint8_t**)&to, 64,
+                    (const uint8_t**)&from, 64);
 
         hist_start = (hist_start + 64) & 511;
     }
@@ -504,10 +518,11 @@ static void update_band_masking(DCAEncContext *c, int band1, int band2,
         c->band_masking_cb[band1] = value;
 }
 
-static void calc_masking(DCAEncContext *c, const int32_t *input)
+static void calc_masking(DCAEncContext *c, const float **input)
 {
     int i, k, band, ch, ssf;
     int32_t data[512];
+    int32_t *p;
 
     for (i = 0; i < 256; i++)
         for (ssf = 0; ssf < SUBSUBFRAMES; ssf++)
@@ -516,11 +531,15 @@ static void calc_masking(DCAEncContext *c, const int32_t *input)
     for (ssf = 0; ssf < SUBSUBFRAMES; ssf++)
         for (ch = 0; ch < c->fullband_channels; ch++) {
             const int chi = c->channel_order_tab[ch];
+            const float *from = &input[chi][0];
 
             for (i = 0, k = 128 + 256 * ssf; k < 512; i++, k++)
                 data[i] = c->history[ch][k];
-            for (k -= 512; i < 512; i++, k++)
-                data[i] = input[k * c->channels + chi];
+
+            p = &data[i];
+            swr_convert(c->swr,
+                        (uint8_t**)&p, 512 - i,
+                        (const uint8_t**)&from, 512 - i);
             adjust_jnd(c, data, c->masking_curve_cb[ssf]);
         }
     for (i = 0; i < 256; i++) {
@@ -881,18 +900,6 @@ out:
         c->worst_noise_ever = high;
 }
 
-static void shift_history(DCAEncContext *c, const int32_t *input)
-{
-    int k, ch;
-
-    for (k = 0; k < 512; k++)
-        for (ch = 0; ch < c->channels; ch++) {
-            const int chi = c->channel_order_tab[ch];
-
-            c->history[ch][k] = input[k * c->channels + chi];
-        }
-}
-
 static void fill_in_adpcm_bufer(DCAEncContext *c)
 {
      int ch, band;
@@ -1175,25 +1182,24 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                         const AVFrame *frame, int *got_packet_ptr)
 {
     DCAEncContext *c = avctx->priv_data;
-    const int32_t *samples;
+    const float **samples;
     int ret, i;
 
     if ((ret = ff_alloc_packet2(avctx, avpkt, c->frame_size, 0)) < 0)
         return ret;
 
-    samples = (const int32_t *)frame->data[0];
+    samples = (const float**)frame->extended_data;
 
+    calc_masking(c, samples);
     subband_transform(c, samples);
     if (c->lfe_channel)
         lfe_downsample(c, samples);
 
-    calc_masking(c, samples);
     if (c->options.adpcm_mode)
         adpcm_analysis(c);
     find_peaks(c);
     assign_bits(c);
     calc_lfe_scales(c);
-    shift_history(c, samples);
 
     init_put_bits(&c->pb, avpkt->data, avpkt->size);
     fill_in_adpcm_bufer(c);
@@ -1245,7 +1251,7 @@ AVCodec ff_dca_encoder = {
     .encode2               = encode_frame,
     .capabilities          = AV_CODEC_CAP_EXPERIMENTAL,
     .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
-    .sample_fmts           = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32,
+    .sample_fmts           = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
                                                             AV_SAMPLE_FMT_NONE },
     .supported_samplerates = sample_rates,
     .channel_layouts       = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
diff --git a/tests/fate/acodec.mak b/tests/fate/acodec.mak
index 80d26de0f9..a072c203c2 100644
--- a/tests/fate/acodec.mak
+++ b/tests/fate/acodec.mak
@@ -99,20 +99,13 @@ FATE_ACODEC-$(call ENCDEC, ALAC, MOV) += fate-acodec-alac
 fate-acodec-alac: FMT = mov
 fate-acodec-alac: CODEC = alac -compression_level 1
 
-FATE_ACODEC-$(call ENCDEC, DCA, DTS) += fate-acodec-dca
-fate-acodec-dca: tests/data/asynth-44100-2.wav
-fate-acodec-dca: SRC = tests/data/asynth-44100-2.wav
-fate-acodec-dca: CMD = md5 -i $(TARGET_PATH)/$(SRC) -c:a dca -strict -2 -f dts -flags +bitexact
-fate-acodec-dca: CMP = oneline
-fate-acodec-dca: REF = 2aa580ac67820fce4f581b96ebb34acc
-
-FATE_ACODEC-$(call ENCDEC, DCA, WAV) += fate-acodec-dca2
-fate-acodec-dca2: CMD = enc_dec_pcm dts wav s16le $(SRC) -c:a dca -strict -2 -flags +bitexact
-fate-acodec-dca2: REF = $(SRC)
-fate-acodec-dca2: CMP = stddev
-fate-acodec-dca2: CMP_SHIFT = -2048
-fate-acodec-dca2: CMP_TARGET = 535
-fate-acodec-dca2: SIZE_TOLERANCE = 1632
+FATE_ACODEC-$(call ENCDEC, DCA, WAV) += fate-acodec-dca
+fate-acodec-dca: CMD = enc_dec_pcm dts wav s16le $(SRC) -c:a dca -strict -2
+fate-acodec-dca: REF = $(SRC)
+fate-acodec-dca: CMP = stddev
+fate-acodec-dca: CMP_SHIFT = -2048
+fate-acodec-dca: CMP_TARGET = 535
+fate-acodec-dca: SIZE_TOLERANCE = 1632
 
 FATE_ACODEC-$(call ENCDEC, FLAC, FLAC) += fate-acodec-flac fate-acodec-flac-exact-rice
 fate-acodec-flac: FMT = flac
-- 
2.13.5

