Merge commit '777885983533235ccda5145f96317fc8cd0a18ab'
authorHendrik Leppkes <h.leppkes@gmail.com>
Thu, 17 Sep 2015 09:21:07 +0000 (11:21 +0200)
committerHendrik Leppkes <h.leppkes@gmail.com>
Thu, 17 Sep 2015 09:21:07 +0000 (11:21 +0200)
* commit '777885983533235ccda5145f96317fc8cd0a18ab':
  dcadec: set channel layout in a separate function

Merged-by: Hendrik Leppkes <h.leppkes@gmail.com>
1  2 
libavcodec/dcadec.c

@@@ -1561,245 -1244,165 +1561,255 @@@ static int scan_for_extensions(AVCodecC
      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)
++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;
++    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 */
 +    if (!(s->core_ext_mask & DCA_EXT_XXCH)) {
 +        /* xxx should also do MA extensions */
 +        if (s->amode < 16) {
 +            avctx->channel_layout = ff_dca_core_channel_layout[s->amode];
 +
 +            if (s->prim_channels + !!s->lfe > 2 &&
 +                avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
 +                /*
 +                 * Neither the core's auxiliary data nor our default tables contain
 +                 * downmix coefficients for the additional channel coded in the XCh
 +                 * extension, so when we're doing a Stereo downmix, don't decode it.
 +                 */
 +                s->xch_disable = 1;
 +            }
  
 -    if (s->amode < 16) {
 -        avctx->channel_layout = dca_core_channel_layout[s->amode];
 +            if (s->xch_present && !s->xch_disable) {
 +                if (avctx->channel_layout & AV_CH_BACK_CENTER) {
 +                    avpriv_request_sample(avctx, "XCh with Back center channel");
 +                    return AVERROR_INVALIDDATA;
 +                }
 +                avctx->channel_layout |= AV_CH_BACK_CENTER;
 +                if (s->lfe) {
 +                    avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
 +                    s->channel_order_tab = ff_dca_channel_reorder_lfe_xch[s->amode];
 +                } else {
 +                    s->channel_order_tab = ff_dca_channel_reorder_nolfe_xch[s->amode];
 +                }
 +                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;
 +                    s->channel_order_tab = ff_dca_channel_reorder_lfe[s->amode];
 +                } else
 +                    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 (s->prim_channels + !!s->lfe > 2 &&
 -            avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
 -            /*
 -             * Neither the core's auxiliary data nor our default tables contain
 -             * downmix coefficients for the additional channel coded in the XCh
 -             * extension, so when we're doing a Stereo downmix, don't decode it.
 -             */
 -            s->xch_disable = 1;
 -        }
++            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 (s->xch_present && !s->xch_disable) {
 -            avctx->channel_layout |= AV_CH_BACK_CENTER;
 -            if (s->lfe) {
 -                avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
 -                s->channel_order_tab = ff_dca_channel_reorder_lfe_xch[s->amode];
 -            } else {
 -                s->channel_order_tab = ff_dca_channel_reorder_nolfe_xch[s->amode];
++            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;
              }
 +            else if (avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE) {
 +                static const int8_t dca_channel_order_native[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
 +                s->channel_order_tab = dca_channel_order_native;
 +            }
 +            s->lfe_index = ff_dca_lfe_index[s->amode];
          } else {
 -            channels       = num_core_channels + !!s->lfe;
 -            s->xch_present = 0; /* disable further xch processing */
 -            if (s->lfe) {
 -                avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
 -                s->channel_order_tab = ff_dca_channel_reorder_lfe[s->amode];
 -            } else
 -                s->channel_order_tab = ff_dca_channel_reorder_nolfe[s->amode];
 +            av_log(avctx, AV_LOG_ERROR,
 +                   "Non standard configuration %d !\n", s->amode);
 +            return AVERROR_INVALIDDATA;
          }
  
 -        if (channels > !!s->lfe &&
 -            s->channel_order_tab[channels - 1 - !!s->lfe] < 0)
 -            return AVERROR_INVALIDDATA;
 +        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;
  
 -        if (num_core_channels + !!s->lfe > 2 &&
 -            avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
 -            channels              = 2;
 -            s->output             = s->prim_channels == 2 ? s->amode : DCA_STEREO;
 -            avctx->channel_layout = AV_CH_LAYOUT_STEREO;
 +        {
-             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];
 +            }
 +        }
  
 -            /* 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];
 -                }
 +        /* Given the DTS spec'ed channel mask, generate an avcodec version */
 +        channel_layout = 0;
 +        for (i = 0; i < s->xxch_nbits_spk_mask; ++i) {
 +            if (channel_mask & (1 << i)) {
 +                channel_layout |= ff_dca_map_xxch_to_native[i];
              }
 -            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]);
 +        }
 +
 +        /* make sure that we have managed to get equivalent dts/avcodec channel
 +         * masks in some sense -- unfortunately some channels could overlap */
 +        if (av_popcount(channel_mask) != av_popcount(channel_layout)) {
 +            av_log(avctx, AV_LOG_DEBUG,
 +                   "DTS-XXCH: Inconsistent avcodec/dts channel layouts\n");
 +            return AVERROR_INVALIDDATA;
 +        }
 +
 +        avctx->channel_layout = channel_layout;
 +
 +        if (!(avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE)) {
 +            /* Estimate DTS --> avcodec ordering table */
 +            for (chset = -1, j = 0; chset < s->xxch_chset; ++chset) {
 +                mask = chset >= 0 ? s->xxch_spk_masks[chset]
 +                                  : s->xxch_core_spkmask;
 +                for (i = 0; i < s->xxch_nbits_spk_mask; i++) {
 +                    if (mask & ~(DCA_XXCH_LFE1 | DCA_XXCH_LFE2) & (1 << i)) {
 +                        lavc = ff_dca_map_xxch_to_native[i];
 +                        posn = av_popcount(channel_layout & (lavc - 1));
 +                        s->xxch_order_tab[j++] = posn;
 +                    }
 +                }
 +
              }
 -            ff_dlog(s->avctx, "\n");
 +
 +            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;
          }
 -    } else {
 -        av_log(avctx, AV_LOG_ERROR, "Non standard configuration %d !\n", s->amode);
 -        return AVERROR_INVALIDDATA;
 +
 +        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;
 -    float  **samples_flt;
+     int lfe_samples;
+     int num_core_channels = 0;
+     int i, ret;
 -    s->dca_buffer_size = ff_dca_convert_bitstream(buf, buf_size, s->dca_buffer,
 -                                                  DCA_MAX_FRAME_SIZE + DCA_MAX_EXSS_HEADER_SIZE);
++    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;
 -    avctx->bit_rate    = s->bit_rate;
++    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->core_ext_mask = dca_ext_audio_descr_mask[s->ext_descr];
+     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)
 -    ret = set_channel_layout(avctx, channels, num_core_channels);
++        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;
 -    avctx->channels = channels;
++    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);
      if (s->exss_ext_mask & DCA_EXT_EXSS_XLL) {