/* record number of core channels incase less than max channels are requested */
num_core_channels = s->prim_channels;
- for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
+ 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;
- if (s->prim_channels + !!s->lfe >
++ for (i = 0; i < num_core_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;
+ }
- for (i = 0; i < s->prim_channels + !!s->lfe; i++) {
++ if (num_core_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++) {
++ for (i = 0; i < num_core_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 < num_core_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
#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 &&
+
++ 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;
+ }
+ 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 (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;
+ /* 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: Inconsistent 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 < num_core_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 (num_core_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 < num_core_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 < num_core_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);