OSDN Git Service

Merge commit '89de5157b1cbe7807d3ec1d51bd56a75e98c002e'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 28 Nov 2013 22:15:35 +0000 (23:15 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 28 Nov 2013 23:18:42 +0000 (00:18 +0100)
* commit '89de5157b1cbe7807d3ec1d51bd56a75e98c002e':
  dcadec: implement request_channel_layout.

Conflicts:
libavcodec/dcadec.c

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

@@@ -2224,131 -1801,49 +2225,137 @@@ static int dca_decode_frame(AVCodecCont
  
      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 (avctx->request_channels == 2 && s->prim_channels > 2) {
++            if (s->prim_channels > 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];
 +            }
 +        }
 +
 +        /* 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 (channels > !!s->lfe &&
 -            s->channel_order_tab[channels - 1 - !!s->lfe] < 0)
 +        /* 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;
 +        }
 +
 +        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;
 +                    }
 +                }
 +            }
  
 -        if (s->prim_channels > 2 &&
 -            avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
 -            channels = 2;
 -            s->output = DCA_STEREO;
 -            avctx->channel_layout = AV_CH_LAYOUT_STEREO;
 +            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);