]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/dcadec.c
Merge commit '97bf7c03b1338a867da52c159a2afecbdedcfa88'
[ffmpeg] / libavcodec / dcadec.c
index 4d5e1152f2fef488f26acb8cd8fa5ef48e3a95fb..c21a97b2ec65406d7f08029095e0185817ca98b1 100644 (file)
 #include <stddef.h>
 #include <stdio.h>
 
+#include "libavutil/channel_layout.h"
 #include "libavutil/common.h"
 #include "libavutil/float_dsp.h"
 #include "libavutil/intmath.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mathematics.h"
-#include "libavutil/audioconvert.h"
+#include "libavutil/samplefmt.h"
 #include "avcodec.h"
 #include "dsputil.h"
 #include "fft.h"
@@ -420,6 +421,9 @@ typedef struct {
 
     DECLARE_ALIGNED(32, float, subband_samples)[DCA_BLOCKS_MAX][DCA_PRIM_CHANNELS_MAX][DCA_SUBBANDS][8];
     float *samples_chanptr[DCA_PRIM_CHANNELS_MAX + 1];
+    float *extra_channels[DCA_PRIM_CHANNELS_MAX + 1];
+    uint8_t *extra_channels_buffer;
+    unsigned int extra_channels_buffer_size;
 
     uint8_t dca_buffer[DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE + DCA_BUFFER_PADDING_SIZE];
     int dca_buffer_size;        ///< how much data is in the dca_buffer
@@ -444,7 +448,6 @@ typedef struct {
     int xxch_chset_nch[4];
     float xxch_dmix_sf[DCA_CHSETS_MAX];
 
-    uint32_t xxch_downmix;        /* downmix enabled per channel set */
     uint32_t xxch_dmix_embedded;  /* lower layer has mix pre-embedded, per chset */
     float xxch_dmix_coeff[DCA_PRIM_CHANNELS_MAX][32]; /* worst case sizing */
 
@@ -593,7 +596,6 @@ static int dca_parse_audio_coding_header(DCAContext *s, int base_channel,
             s->xxch_dmix_sf[s->xxch_chset] = scale_factor;
 
             for (i = base_channel; i < s->prim_channels; i++) {
-                s->xxch_downmix |= (1 << i);
                 mask[i] = get_bits(&s->gb, s->xxch_nbits_spk_mask);
             }
 
@@ -1438,6 +1440,7 @@ static int dca_filter_channels(DCAContext *s, int block_index)
     for (k = 0; k < s->prim_channels; k++) {
 /*        static float pcm_to_double[8] = { 32768.0, 32768.0, 524288.0, 524288.0,
                                             0, 8388608.0, 8388608.0 };*/
+        if(s->channel_order_tab[k] >= 0)
         qmf_32_subbands(s, k, subband_samples[k],
                         s->samples_chanptr[s->channel_order_tab[k]],
                         M_SQRT1_2 / 32768.0 /* pcm_to_double[s->source_pcm_res] */);
@@ -1900,7 +1903,6 @@ static int dca_xxch_decode_frame(DCAContext *s)
     core_spk               = get_bits(&s->gb, spkmsk_bits);
     s->xxch_core_spkmask   = core_spk;
     s->xxch_nbits_spk_mask = spkmsk_bits;
-    s->xxch_downmix        = 0;
     s->xxch_dmix_embedded  = 0;
 
     /* skip to the end of the header */
@@ -2070,7 +2072,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
     float *dst_chan;
     DCAContext *s = avctx->priv_data;
     int core_ss_end;
-    int channels;
+    int channels, full_channels;
     float scale;
     int achan;
     int chset;
@@ -2211,7 +2213,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
 
     avctx->profile = s->profile;
 
-    channels = s->prim_channels + !!s->lfe;
+    full_channels = channels = s->prim_channels + !!s->lfe;
 
     /* If we have XXCH then the channel layout is managed differently */
     /* note that XLL will also have another way to do things */
@@ -2263,7 +2265,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
             return AVERROR_INVALIDDATA;
         }
 
-        s->xxch_downmix = 0;
+        s->xxch_dmix_embedded = 0;
     } else {
         /* we only get here if an XXCH channel set can be added to the mix */
         channel_mask = s->xxch_core_spkmask;
@@ -2340,12 +2342,35 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
     }
     samples_flt = (float  **) s->frame.extended_data;
 
+    /* allocate buffer for extra channels if downmixing */
+    if (avctx->channels < full_channels) {
+        ret = av_samples_get_buffer_size(NULL, full_channels - channels,
+                                         s->frame.nb_samples,
+                                         avctx->sample_fmt, 0);
+        if (ret < 0)
+            return ret;
+
+        av_fast_malloc(&s->extra_channels_buffer,
+                       &s->extra_channels_buffer_size, ret);
+        if (!s->extra_channels_buffer)
+            return AVERROR(ENOMEM);
+
+        ret = av_samples_fill_arrays((uint8_t **)s->extra_channels, NULL,
+                                     s->extra_channels_buffer,
+                                     full_channels - channels,
+                                     s->frame.nb_samples, avctx->sample_fmt, 0);
+        if (ret < 0)
+            return ret;
+    }
+
     /* filter to get final output */
     for (i = 0; i < (s->sample_blocks / 8); i++) {
         int ch;
 
         for (ch = 0; ch < channels; ch++)
             s->samples_chanptr[ch] = samples_flt[ch] + i * 256;
+        for (; ch < full_channels; ch++)
+            s->samples_chanptr[ch] = s->extra_channels[ch - channels] + i * 256;
 
         dca_filter_channels(s, i);
 
@@ -2457,6 +2482,7 @@ static av_cold int dca_decode_end(AVCodecContext *avctx)
 {
     DCAContext *s = avctx->priv_data;
     ff_mdct_end(&s->imdct);
+    av_freep(&s->extra_channels_buffer);
     return 0;
 }