OSDN Git Service

Merge commit '6bfdb2de881372048be7fbda643417e1fd3ce93c'
authorMichael Niedermayer <michaelni@gmx.at>
Sun, 5 Jan 2014 21:27:34 +0000 (22:27 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Sun, 5 Jan 2014 21:27:34 +0000 (22:27 +0100)
* commit '6bfdb2de881372048be7fbda643417e1fd3ce93c':
  dcadec: set the output channel mode more accurately.

Conflicts:
libavcodec/dcadec.c

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

@@@ -2170,54 -1752,6 +2170,55 @@@ 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 + !!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)) {
 +                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]);
 +                }
++                s->output = s->core_downmix_amode;
 +            } 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];
 +                }
 +            }
 +            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");
 +    }
 +
      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 && !s->xch_disable &&
 -            (!avctx->request_channels ||
 -             avctx->request_channels > num_core_channels + !!s->lfe)) {
 +            if (s->xch_present && !s->xch_disable &&
 +                (!avctx->request_channels ||
 +                 avctx->request_channels > num_core_channels + !!s->lfe)) {
  FF_ENABLE_DEPRECATION_WARNINGS
  #else
 -        if (s->xch_present && !s->xch_disable) {
 +            if (s->xch_present && !s->xch_disable) {
  #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 + !!s->lfe > 2 &&
 +                avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
 +                channels = 2;
-                 s->output = DCA_STEREO;
++                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 = 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 = s->prim_channels == 2 ? s->amode : 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]);
 -                }
 -                s->output = s->core_downmix_amode;
 -            } 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);