Merge commit 'aaa44d0299338e3bc90128816c21dbfab06cdb48'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 29 Nov 2013 03:00:59 +0000 (04:00 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 29 Nov 2013 03:00:59 +0000 (04:00 +0100)
* commit 'aaa44d0299338e3bc90128816c21dbfab06cdb48':
  dca: support mixing LFE in dca_downmix.

Conflicts:
libavcodec/dcadec.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavcodec/dcadata.h
libavcodec/dcadec.c

Simple merge
@@@ -2145,55 -1733,6 +2154,54 @@@ static int dca_decode_frame(AVCodecCont
      /* record number of core channels incase less than max channels are requested */
      num_core_channels = s->prim_channels;
  
-     if (s->prim_channels > 2 &&
++    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.
-          *
-          * Coefficients for the LFE channel are ignored (not supported) */
-         if (s->core_downmix && (s->core_downmix_amode == DCA_STEREO ||
-                                 s->core_downmix_amode == DCA_STEREO_TOTAL)) {
-             int sign, code;
-             for (i = 0; i < s->prim_channels; i++) {
-                 sign = s->core_downmix_codes[i][0] & 0x100 ? 1 : -1;
-                 code = s->core_downmix_codes[i][0] & 0x0FF;
-                 s->downmix_coef[i][0] = (!code ? 0.0f :
-                                         sign * dca_dmixtable[code - 1]);
-                 sign = s->core_downmix_codes[i][1] & 0x100 ? 1 : -1;
-                 code = s->core_downmix_codes[i][1] & 0x0FF;
-                 s->downmix_coef[i][1] = (!code ? 0.0f :
-                                         sign * dca_dmixtable[code - 1]);
-             }
-         } else {
-             int am = s->amode & DCA_CHANNEL_MASK;
-             if (am >= FF_ARRAY_ELEMS(dca_default_coeffs)) {
-                 av_log(s->avctx, AV_LOG_ERROR,
-                     "Invalid channel mode %d\n", am);
-                 return AVERROR_INVALIDDATA;
-             }
-             if (s->prim_channels > FF_ARRAY_ELEMS(dca_default_coeffs[0])) {
-                 avpriv_request_sample(s->avctx, "Downmixing %d channels",
-                                     s->prim_channels);
-                 return AVERROR_PATCHWELCOME;
++            /* 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)) {
++                int sign, code;
++                for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
++                    sign = s->core_downmix_codes[i][0] & 0x100 ? 1 : -1;
++                    code = s->core_downmix_codes[i][0] & 0x0FF;
++                    s->downmix_coef[i][0] = (!code ? 0.0f :
++                                             sign * dca_dmixtable[code - 1]);
++                    sign = s->core_downmix_codes[i][1] & 0x100 ? 1 : -1;
++                    code = s->core_downmix_codes[i][1] & 0x0FF;
++                    s->downmix_coef[i][1] = (!code ? 0.0f :
++                                             sign * dca_dmixtable[code - 1]);
++                }
++            } else {
++                int am = s->amode & DCA_CHANNEL_MASK;
++                if (am >= FF_ARRAY_ELEMS(dca_default_coeffs)) {
++                    av_log(s->avctx, AV_LOG_ERROR,
++                           "Invalid channel mode %d\n", am);
++                    return AVERROR_INVALIDDATA;
++                }
++                if (s->prim_channels + !!s->lfe >
++                    FF_ARRAY_ELEMS(dca_default_coeffs[0])) {
++                    avpriv_request_sample(s->avctx, "Downmixing %d channels",
++                                          s->prim_channels + !!s->lfe);
++                    return AVERROR_PATCHWELCOME;
++                }
++                for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
++                    s->downmix_coef[i][0] = dca_default_coeffs[am][i][0];
++                    s->downmix_coef[i][1] = dca_default_coeffs[am][i][1];
++                }
 +            }
-             for (i = 0; i < s->prim_channels; i++) {
-                 s->downmix_coef[i][0] = dca_default_coeffs[am][i][0];
-                 s->downmix_coef[i][1] = dca_default_coeffs[am][i][1];
++            av_dlog(s->avctx, "Stereo downmix coeffs:\n");
++            for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
++                av_dlog(s->avctx, "L, input channel %d = %f\n", i,
++                        s->downmix_coef[i][0]);
++                av_dlog(s->avctx, "R, input channel %d = %f\n", i,
++                        s->downmix_coef[i][1]);
 +            }
-         }
-         av_dlog(s->avctx, "Stereo downmix coeffs:\n");
-         for (i = 0; i < s->prim_channels; i++) {
-             av_dlog(s->avctx, "L, input channel %d = %f\n", i,
-                     s->downmix_coef[i][0]);
-             av_dlog(s->avctx, "R, input channel %d = %f\n", i,
-                     s->downmix_coef[i][1]);
-         }
-         av_dlog(s->avctx, "\n");
++            av_dlog(s->avctx, "\n");
 +    }
 +
      if (s->ext_coding)
          s->core_ext_mask = dca_ext_audio_descr_mask[s->ext_descr];
      else
  
      full_channels = channels = s->prim_channels + !!s->lfe;
  
 -    if (s->amode < 16) {
 -        avctx->channel_layout = dca_core_channel_layout[s->amode];
 -
 +    /* 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)
 +        || (s->core_ext_mask & DCA_EXT_XXCH && avctx->request_channels > 0
 +            && avctx->request_channels
 +            < num_core_channels + !!s->lfe + s->xxch_chset_nch[0]))
 +    { /* xxx should also do MA extensions */
 +        if (s->amode < 16) {
 +            avctx->channel_layout = dca_core_channel_layout[s->amode];
  #if FF_API_REQUEST_CHANNELS
  FF_DISABLE_DEPRECATION_WARNINGS
 -        if (s->xch_present && (!avctx->request_channels ||
 -                               avctx->request_channels > num_core_channels + !!s->lfe)) {
 +            if (s->xch_present && (!avctx->request_channels ||
 +                                   avctx->request_channels
 +                                   > num_core_channels + !!s->lfe)) {
  FF_ENABLE_DEPRECATION_WARNINGS
  #else
 -        if (s->xch_present) {
 +            if (s->xch_present) {
  #endif
 -            avctx->channel_layout |= AV_CH_BACK_CENTER;
 -            if (s->lfe) {
 -                avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
 -                s->channel_order_tab = dca_channel_reorder_lfe_xch[s->amode];
 +                avctx->channel_layout |= AV_CH_BACK_CENTER;
 +                if (s->lfe) {
 +                    avctx->channel_layout |= AV_CH_LOW_FREQUENCY;
 +                    s->channel_order_tab = dca_channel_reorder_lfe_xch[s->amode];
 +                } else {
 +                    s->channel_order_tab = dca_channel_reorder_nolfe_xch[s->amode];
 +                }
 +                if (s->channel_order_tab[s->xch_base_channel] < 0)
 +                    return AVERROR_INVALIDDATA;
              } else {
 -                s->channel_order_tab = dca_channel_reorder_nolfe_xch[s->amode];
 +                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 = dca_channel_reorder_lfe[s->amode];
 +                } else
 +                    s->channel_order_tab = dca_channel_reorder_nolfe[s->amode];
 +            }
 +
 +            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));
 +                return AVERROR_INVALIDDATA;
 +            }
 +
-             if (s->prim_channels > 2 &&
++            if (s->prim_channels + !!s->lfe > 2 &&
 +                avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
 +                channels = 2;
 +                s->output = 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 = dca_lfe_index[s->amode];
          } else {
 +            av_log(avctx, AV_LOG_ERROR,
 +                   "Non standard configuration %d !\n", s->amode);
 +            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 (avctx->request_channels > 0
 +            && avctx->request_channels < s->prim_channels) {
              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 = dca_channel_reorder_lfe[s->amode];
 -            } else
 -                s->channel_order_tab = dca_channel_reorder_nolfe[s->amode];
 +            for (i = 0; i < s->xxch_chset && channels + s->xxch_chset_nch[i]
 +                                              <= avctx->request_channels; i++) {
 +                channels += s->xxch_chset_nch[i];
 +                channel_mask |= s->xxch_spk_masks[i];
 +            }
 +        } else {
 +            channels = s->prim_channels + !!s->lfe;
 +            for (i = 0; i < s->xxch_chset; i++) {
 +                channel_mask |= s->xxch_spk_masks[i];
 +            }
          }
  
 -        if (channels > !!s->lfe &&
 -            s->channel_order_tab[channels - 1 - !!s->lfe] < 0)
 -            return AVERROR_INVALIDDATA;
 +        /* 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 |= map_xxch_to_native[i];
 +            }
 +        }
  
 -        if (s->prim_channels + !!s->lfe > 2 &&
 -            avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
 -            channels = 2;
 -            s->output = DCA_STEREO;
 -            avctx->channel_layout = AV_CH_LAYOUT_STEREO;
 +        /* make sure that we have managed to get equivelant 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: Inconsistant avcodec/dts channel layouts\n");
 +            return AVERROR_INVALIDDATA;
 +        }
  
 -            /* 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)) {
 -                int sign, code;
 -                for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
 -                    sign = s->core_downmix_codes[i][0] & 0x100 ? 1 : -1;
 -                    code = s->core_downmix_codes[i][0] & 0x0FF;
 -                    s->downmix_coef[i][0] = (!code ? 0.0f :
 -                                             sign * dca_dmixtable[code - 1]);
 -                    sign = s->core_downmix_codes[i][1] & 0x100 ? 1 : -1;
 -                    code = s->core_downmix_codes[i][1] & 0x0FF;
 -                    s->downmix_coef[i][1] = (!code ? 0.0f :
 -                                             sign * dca_dmixtable[code - 1]);
 -                }
 -            } else {
 -                int am = s->amode & DCA_CHANNEL_MASK;
 -                if (am >= FF_ARRAY_ELEMS(dca_default_coeffs)) {
 -                    av_log(s->avctx, AV_LOG_ERROR,
 -                           "Invalid channel mode %d\n", am);
 -                    return AVERROR_INVALIDDATA;
 -                }
 -                if (s->prim_channels + !!s->lfe >
 -                    FF_ARRAY_ELEMS(dca_default_coeffs[0])) {
 -                    avpriv_request_sample(s->avctx, "Downmixing %d channels",
 -                                          s->prim_channels + !!s->lfe);
 -                    return AVERROR_PATCHWELCOME;
 -                }
 -                for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
 -                    s->downmix_coef[i][0] = dca_default_coeffs[am][i][0];
 -                    s->downmix_coef[i][1] = dca_default_coeffs[am][i][1];
 +        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 = map_xxch_to_native[i];
 +                        posn = av_popcount(channel_layout & (lavc - 1));
 +                        s->xxch_order_tab[j++] = posn;
 +                    }
                  }
              }
 -            av_dlog(s->avctx, "Stereo downmix coeffs:\n");
 -            for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
 -                av_dlog(s->avctx, "L, input channel %d = %f\n", i,
 -                        s->downmix_coef[i][0]);
 -                av_dlog(s->avctx, "R, input channel %d = %f\n", i,
 -                        s->downmix_coef[i][1]);
 -            }
 -            av_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++)
 +                s->xxch_order_tab[i] = i;
 +
 +            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;
 +    }
 +
 +    if (avctx->channels != channels) {
 +        if (avctx->channels)
 +            av_log(avctx, AV_LOG_INFO, "Number of channels changed in DCA decoder (%d -> %d)\n", avctx->channels, channels);
 +        avctx->channels = channels;
      }
 -    avctx->channels = channels;
  
      /* get output buffer */
      frame->nb_samples = 256 * (s->sample_blocks / 8);