]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/dcadec.c
Merge commit '74942685cb457c01937686892878403a409baf27'
[ffmpeg] / libavcodec / dcadec.c
index 2302a05fff858e0d66fa1ff369290f0db44eb1b3..bf28f3bca14180de59939f4322de9dd846dc2263 100644 (file)
@@ -112,6 +112,7 @@ enum DCAXxchSpeakerMask {
 
 #define DCA_NSYNCAUX        0x9A1105A0
 
+#define SAMPLES_PER_SUBBAND 8 // number of samples per subband per subsubframe
 
 /** Bit allocation */
 typedef struct BitAlloc {
@@ -437,7 +438,7 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
 
     if (!base_channel) {
         s->subsubframes[s->current_subframe]    = get_bits(&s->gb, 2) + 1;
-        if (block_index + s->subsubframes[s->current_subframe] > s->sample_blocks/8) {
+        if (block_index + s->subsubframes[s->current_subframe] > (s->sample_blocks / SAMPLES_PER_SUBBAND)) {
             s->subsubframes[s->current_subframe] = 1;
             return AVERROR_INVALIDDATA;
         }
@@ -616,7 +617,7 @@ static int dca_subframe_header(DCAContext *s, int base_channel, int block_index)
 }
 
 static void qmf_32_subbands(DCAContext *s, int chans,
-                            float samples_in[32][8], float *samples_out,
+                            float samples_in[32][SAMPLES_PER_SUBBAND], float *samples_out,
                             float scale)
 {
     const float *prCoeff;
@@ -664,7 +665,7 @@ static QMF64_table *qmf64_precompute(void)
 /* FIXME: Totally unoptimized. Based on the reference code and
  * http://multimedia.cx/mirror/dca-transform.pdf, with guessed tweaks
  * for doubling the size. */
-static void qmf_64_subbands(DCAContext *s, int chans, float samples_in[64][8],
+static void qmf_64_subbands(DCAContext *s, int chans, float samples_in[64][SAMPLES_PER_SUBBAND],
                             float *samples_out, float scale)
 {
     float raXin[64];
@@ -675,7 +676,7 @@ static void qmf_64_subbands(DCAContext *s, int chans, float samples_in[64][8],
 
     for (i = s->subband_activity[chans]; i < 64; i++)
         raXin[i] = 0.0;
-    for (subindex = 0; subindex < 8; subindex++) {
+    for (subindex = 0; subindex < SAMPLES_PER_SUBBAND; subindex++) {
         for (i = 0; i < s->subband_activity[chans]; i++)
             raXin[i] = samples_in[i][subindex];
 
@@ -866,8 +867,8 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
     const float *quant_step_table;
 
     /* FIXME */
-    float (*subband_samples)[DCA_SUBBANDS][8] = s->subband_samples[block_index];
-    LOCAL_ALIGNED_16(int32_t, block, [8 * DCA_SUBBANDS]);
+    float (*subband_samples)[DCA_SUBBANDS][SAMPLES_PER_SUBBAND] = s->subband_samples[block_index];
+    LOCAL_ALIGNED_16(int32_t, block, [SAMPLES_PER_SUBBAND * DCA_SUBBANDS]);
 
     /*
      * Audio data
@@ -905,7 +906,7 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
              */
             if (!abits) {
                 rscale[l] = 0;
-                memset(block + 8 * l, 0, 8 * sizeof(block[0]));
+                memset(block + SAMPLES_PER_SUBBAND * l, 0, SAMPLES_PER_SUBBAND * sizeof(block[0]));
             } else {
                 /* Deal with transients */
                 int sfi = s->transition_mode[k][l] && subsubframe >= s->transition_mode[k][l];
@@ -923,7 +924,7 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
                         block_code1 = get_bits(&s->gb, size);
                         block_code2 = get_bits(&s->gb, size);
                         err         = decode_blockcodes(block_code1, block_code2,
-                                                        levels, block + 8 * l);
+                                                        levels, block + SAMPLES_PER_SUBBAND * l);
                         if (err) {
                             av_log(s->avctx, AV_LOG_ERROR,
                                    "ERROR: block code look-up failed\n");
@@ -931,20 +932,20 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
                         }
                     } else {
                         /* no coding */
-                        for (m = 0; m < 8; m++)
-                            block[8 * l + m] = get_sbits(&s->gb, abits - 3);
+                        for (m = 0; m < SAMPLES_PER_SUBBAND; m++)
+                            block[SAMPLES_PER_SUBBAND * l + m] = get_sbits(&s->gb, abits - 3);
                     }
                 } else {
                     /* Huffman coded */
-                    for (m = 0; m < 8; m++)
-                        block[8 * l + m] = get_bitalloc(&s->gb,
+                    for (m = 0; m < SAMPLES_PER_SUBBAND; m++)
+                        block[SAMPLES_PER_SUBBAND * l + m] = get_bitalloc(&s->gb,
                                                         &dca_smpl_bitalloc[abits], sel);
                 }
             }
         }
 
         s->fmt_conv.int32_to_float_fmul_array8(&s->fmt_conv, subband_samples[k][0],
-                                               block, rscale, 8 * s->vq_start_subband[k]);
+                                               block, rscale, SAMPLES_PER_SUBBAND * s->vq_start_subband[k]);
 
         for (l = 0; l < s->vq_start_subband[k]; l++) {
             int m;
@@ -963,7 +964,7 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
                                                  ff_dca_adpcm_vb[s->prediction_vq[k][l]][3] *
                                                  s->subband_samples_hist[k][l][0]) *
                                                 (1.0f / 8192);
-                for (m = 1; m < 8; m++) {
+                for (m = 1; m < SAMPLES_PER_SUBBAND; m++) {
                     float sum = ff_dca_adpcm_vb[s->prediction_vq[k][l]][0] *
                                 subband_samples[k][l][m - 1];
                     for (n = 2; n <= 4; n++)
@@ -988,7 +989,7 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
                 s->debug_flag |= 0x01;
             }
             s->dcadsp.decode_hf(subband_samples[k], s->high_freq_vq[k],
-                                ff_dca_high_freq_vq, subsubframe * 8,
+                                ff_dca_high_freq_vq, subsubframe * SAMPLES_PER_SUBBAND,
                                 s->scale_factor[k], s->vq_start_subband[k],
                                 s->subband_activity[k]);
         }
@@ -1012,7 +1013,7 @@ static int dca_subsubframe(DCAContext *s, int base_channel, int block_index)
 
 static int dca_filter_channels(DCAContext *s, int block_index, int upsample)
 {
-    float (*subband_samples)[DCA_SUBBANDS][8] = s->subband_samples[block_index];
+    float (*subband_samples)[DCA_SUBBANDS][SAMPLES_PER_SUBBAND] = s->subband_samples[block_index];
     int k;
 
     if (upsample) {
@@ -1456,7 +1457,7 @@ static float dca_dmix_code(unsigned code)
 static int scan_for_extensions(AVCodecContext *avctx)
 {
     DCAContext *s = avctx->priv_data;
-    int core_ss_end, ret;
+    int core_ss_end, ret = 0;
 
     core_ss_end = FFMIN(s->frame_size, s->dca_buffer_size) * 8;
 
@@ -1561,121 +1562,12 @@ static int scan_for_extensions(AVCodecContext *avctx)
     return ret;
 }
 
-/**
- * Main frame decoding function
- * FIXME add arguments
- */
-static int dca_decode_frame(AVCodecContext *avctx, void *data,
-                            int *got_frame_ptr, AVPacket *avpkt)
+static int set_channel_layout(AVCodecContext *avctx, int *channels, int num_core_channels)
 {
-    AVFrame *frame     = data;
-    const uint8_t *buf = avpkt->data;
-    int buf_size       = avpkt->size;
-    int channel_mask;
-    int channel_layout;
-    int lfe_samples;
-    int num_core_channels = 0;
-    int i, ret;
-    float **samples_flt;
-    float *src_chan;
-    float *dst_chan;
     DCAContext *s = avctx->priv_data;
-    int channels, full_channels;
-    float scale;
-    int achan;
-    int chset;
-    int mask;
-    int lavc;
-    int posn;
-    int j, k;
-    int endch;
-    int upsample = 0;
-
-    s->exss_ext_mask = 0;
-    s->xch_present   = 0;
-
-    s->dca_buffer_size = AVERROR_INVALIDDATA;
-    for (i = 0; i < buf_size - 3 && s->dca_buffer_size == AVERROR_INVALIDDATA; i++)
-        s->dca_buffer_size = avpriv_dca_convert_bitstream(buf + i, buf_size - i, s->dca_buffer,
-                                                          DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE);
-
-    if (s->dca_buffer_size == AVERROR_INVALIDDATA) {
-        av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n");
-        return AVERROR_INVALIDDATA;
-    }
-
-    if ((ret = dca_parse_frame_header(s)) < 0) {
-        // seems like the frame is corrupt, try with the next one
-        return ret;
-    }
-    // set AVCodec values with parsed data
-    avctx->sample_rate = s->sample_rate;
-
-    s->profile = FF_PROFILE_DTS;
-
-    for (i = 0; i < (s->sample_blocks / 8); i++) {
-        if ((ret = dca_decode_block(s, 0, i))) {
-            av_log(avctx, AV_LOG_ERROR, "error decoding block\n");
-            return ret;
-        }
-    }
-
-    /* record number of core channels incase less than max channels are requested */
-    num_core_channels = s->prim_channels;
-
-    if (s->prim_channels + !!s->lfe > 2 &&
-        avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
-            /* Stereo downmix coefficients
-             *
-             * The decoder can only downmix to 2-channel, so we need to ensure
-             * embedded downmix coefficients are actually targeting 2-channel.
-             */
-            if (s->core_downmix && (s->core_downmix_amode == DCA_STEREO ||
-                                    s->core_downmix_amode == DCA_STEREO_TOTAL)) {
-                for (i = 0; i < num_core_channels + !!s->lfe; i++) {
-                    /* Range checked earlier */
-                    s->downmix_coef[i][0] = dca_dmix_code(s->core_downmix_codes[i][0]);
-                    s->downmix_coef[i][1] = dca_dmix_code(s->core_downmix_codes[i][1]);
-                }
-                s->output = s->core_downmix_amode;
-            } else {
-                int am = s->amode & DCA_CHANNEL_MASK;
-                if (am >= FF_ARRAY_ELEMS(ff_dca_default_coeffs)) {
-                    av_log(s->avctx, AV_LOG_ERROR,
-                           "Invalid channel mode %d\n", am);
-                    return AVERROR_INVALIDDATA;
-                }
-                if (num_core_channels + !!s->lfe >
-                    FF_ARRAY_ELEMS(ff_dca_default_coeffs[0])) {
-                    avpriv_request_sample(s->avctx, "Downmixing %d channels",
-                                          s->prim_channels + !!s->lfe);
-                    return AVERROR_PATCHWELCOME;
-                }
-                for (i = 0; i < num_core_channels + !!s->lfe; i++) {
-                    s->downmix_coef[i][0] = ff_dca_default_coeffs[am][i][0];
-                    s->downmix_coef[i][1] = ff_dca_default_coeffs[am][i][1];
-                }
-            }
-            ff_dlog(s->avctx, "Stereo downmix coeffs:\n");
-            for (i = 0; i < num_core_channels + !!s->lfe; i++) {
-                ff_dlog(s->avctx, "L, input channel %d = %f\n", i,
-                        s->downmix_coef[i][0]);
-                ff_dlog(s->avctx, "R, input channel %d = %f\n", i,
-                        s->downmix_coef[i][1]);
-            }
-            ff_dlog(s->avctx, "\n");
-    }
-
-    if (s->ext_coding)
-        s->core_ext_mask = ff_dca_ext_audio_descr_mask[s->ext_descr];
-    else
-        s->core_ext_mask = 0;
-
-    ret = scan_for_extensions(avctx);
-
-    avctx->profile = s->profile;
-
-    full_channels = channels = s->prim_channels + !!s->lfe;
+    int i, j, chset, mask;
+    int channel_layout, channel_mask;
+    int posn, lavc;
 
     /* If we have XXCH then the channel layout is managed differently */
     /* note that XLL will also have another way to do things */
@@ -1709,7 +1601,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
                 if (s->channel_order_tab[s->xch_base_channel] < 0)
                     return AVERROR_INVALIDDATA;
             } else {
-                channels       = num_core_channels + !!s->lfe;
+                *channels       = num_core_channels + !!s->lfe;
                 s->xch_present = 0; /* disable further xch processing */
                 if (s->lfe) {
                     avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
@@ -1718,18 +1610,18 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
                     s->channel_order_tab = ff_dca_channel_reorder_nolfe[s->amode];
             }
 
-            if (channels > !!s->lfe &&
-                s->channel_order_tab[channels - 1 - !!s->lfe] < 0)
+            if (*channels > !!s->lfe &&
+                s->channel_order_tab[*channels - 1 - !!s->lfe] < 0)
                 return AVERROR_INVALIDDATA;
 
-            if (av_get_channel_layout_nb_channels(avctx->channel_layout) != channels) {
-                av_log(avctx, AV_LOG_ERROR, "Number of channels %d mismatches layout %d\n", channels, av_get_channel_layout_nb_channels(avctx->channel_layout));
+            if (av_get_channel_layout_nb_channels(avctx->channel_layout) != *channels) {
+                av_log(avctx, AV_LOG_ERROR, "Number of channels %d mismatches layout %d\n", *channels, av_get_channel_layout_nb_channels(avctx->channel_layout));
                 return AVERROR_INVALIDDATA;
             }
 
             if (num_core_channels + !!s->lfe > 2 &&
                 avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
-                channels              = 2;
+                *channels              = 2;
                 s->output             = s->prim_channels == 2 ? s->amode : DCA_STEREO;
                 avctx->channel_layout = AV_CH_LAYOUT_STEREO;
             }
@@ -1750,7 +1642,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
         channel_mask = s->xxch_core_spkmask;
 
         {
-            channels = s->prim_channels + !!s->lfe;
+            *channels = s->prim_channels + !!s->lfe;
             for (i = 0; i < s->xxch_chset; i++) {
                 channel_mask |= s->xxch_spk_masks[i];
             }
@@ -1791,17 +1683,136 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
 
             s->lfe_index = av_popcount(channel_layout & (AV_CH_LOW_FREQUENCY-1));
         } else { /* native ordering */
-            for (i = 0; i < channels; i++)
+            for (i = 0; i < *channels; i++)
                 s->xxch_order_tab[i] = i;
 
-            s->lfe_index = channels - 1;
+            s->lfe_index = *channels - 1;
         }
 
         s->channel_order_tab = s->xxch_order_tab;
     }
 
+    return 0;
+}
+
+/**
+ * Main frame decoding function
+ * FIXME add arguments
+ */
+static int dca_decode_frame(AVCodecContext *avctx, void *data,
+                            int *got_frame_ptr, AVPacket *avpkt)
+{
+    AVFrame *frame     = data;
+    const uint8_t *buf = avpkt->data;
+    int buf_size       = avpkt->size;
+    int lfe_samples;
+    int num_core_channels = 0;
+    int i, ret;
+    float **samples_flt;
+    float *src_chan;
+    float *dst_chan;
+    DCAContext *s = avctx->priv_data;
+    int channels, full_channels;
+    float scale;
+    int achan;
+    int chset;
+    int mask;
+    int j, k;
+    int endch;
+    int upsample = 0;
+
+    s->exss_ext_mask = 0;
+    s->xch_present   = 0;
+
+    s->dca_buffer_size = AVERROR_INVALIDDATA;
+    for (i = 0; i < buf_size - 3 && s->dca_buffer_size == AVERROR_INVALIDDATA; i++)
+        s->dca_buffer_size = avpriv_dca_convert_bitstream(buf + i, buf_size - i, s->dca_buffer,
+                                                          DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE);
+
+    if (s->dca_buffer_size == AVERROR_INVALIDDATA) {
+        av_log(avctx, AV_LOG_ERROR, "Not a valid DCA frame\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    if ((ret = dca_parse_frame_header(s)) < 0) {
+        // seems like the frame is corrupt, try with the next one
+        return ret;
+    }
+    // set AVCodec values with parsed data
+    avctx->sample_rate = s->sample_rate;
+
+    s->profile = FF_PROFILE_DTS;
+
+    for (i = 0; i < (s->sample_blocks / SAMPLES_PER_SUBBAND); i++) {
+        if ((ret = dca_decode_block(s, 0, i))) {
+            av_log(avctx, AV_LOG_ERROR, "error decoding block\n");
+            return ret;
+        }
+    }
+
+    /* record number of core channels incase less than max channels are requested */
+    num_core_channels = s->prim_channels;
+
+    if (s->prim_channels + !!s->lfe > 2 &&
+        avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
+            /* Stereo downmix coefficients
+             *
+             * The decoder can only downmix to 2-channel, so we need to ensure
+             * embedded downmix coefficients are actually targeting 2-channel.
+             */
+            if (s->core_downmix && (s->core_downmix_amode == DCA_STEREO ||
+                                    s->core_downmix_amode == DCA_STEREO_TOTAL)) {
+                for (i = 0; i < num_core_channels + !!s->lfe; i++) {
+                    /* Range checked earlier */
+                    s->downmix_coef[i][0] = dca_dmix_code(s->core_downmix_codes[i][0]);
+                    s->downmix_coef[i][1] = dca_dmix_code(s->core_downmix_codes[i][1]);
+                }
+                s->output = s->core_downmix_amode;
+            } else {
+                int am = s->amode & DCA_CHANNEL_MASK;
+                if (am >= FF_ARRAY_ELEMS(ff_dca_default_coeffs)) {
+                    av_log(s->avctx, AV_LOG_ERROR,
+                           "Invalid channel mode %d\n", am);
+                    return AVERROR_INVALIDDATA;
+                }
+                if (num_core_channels + !!s->lfe >
+                    FF_ARRAY_ELEMS(ff_dca_default_coeffs[0])) {
+                    avpriv_request_sample(s->avctx, "Downmixing %d channels",
+                                          s->prim_channels + !!s->lfe);
+                    return AVERROR_PATCHWELCOME;
+                }
+                for (i = 0; i < num_core_channels + !!s->lfe; i++) {
+                    s->downmix_coef[i][0] = ff_dca_default_coeffs[am][i][0];
+                    s->downmix_coef[i][1] = ff_dca_default_coeffs[am][i][1];
+                }
+            }
+            ff_dlog(s->avctx, "Stereo downmix coeffs:\n");
+            for (i = 0; i < num_core_channels + !!s->lfe; i++) {
+                ff_dlog(s->avctx, "L, input channel %d = %f\n", i,
+                        s->downmix_coef[i][0]);
+                ff_dlog(s->avctx, "R, input channel %d = %f\n", i,
+                        s->downmix_coef[i][1]);
+            }
+            ff_dlog(s->avctx, "\n");
+    }
+
+    if (s->ext_coding)
+        s->core_ext_mask = ff_dca_ext_audio_descr_mask[s->ext_descr];
+    else
+        s->core_ext_mask = 0;
+
+    ret = scan_for_extensions(avctx);
+
+    avctx->profile = s->profile;
+
+    full_channels = channels = s->prim_channels + !!s->lfe;
+
+    ret = set_channel_layout(avctx, &channels, num_core_channels);
+    if (ret < 0)
+        return ret;
+
     /* get output buffer */
-    frame->nb_samples = 256 * (s->sample_blocks / 8);
+    frame->nb_samples = 256 * (s->sample_blocks / SAMPLES_PER_SUBBAND);
     if (s->exss_ext_mask & DCA_EXT_EXSS_XLL) {
         int xll_nb_samples = s->xll_segments * s->xll_smpl_in_seg;
         /* Check for invalid/unsupported conditions first */
@@ -1871,7 +1882,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
     }
 
     /* filter to get final output */
-    for (i = 0; i < (s->sample_blocks / 8); i++) {
+    for (i = 0; i < (s->sample_blocks / SAMPLES_PER_SUBBAND); i++) {
         int ch;
         unsigned block = upsample ? 512 : 256;
         for (ch = 0; ch < channels; ch++)
@@ -1940,7 +1951,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data,
     }
 
     /* update lfe history */
-    lfe_samples = 2 * s->lfe * (s->sample_blocks / 8);
+    lfe_samples = 2 * s->lfe * (s->sample_blocks / SAMPLES_PER_SUBBAND);
     for (i = 0; i < 2 * s->lfe * 4; i++)
         s->lfe_data[i] = s->lfe_data[i + lfe_samples];