*dst++ = get_bits(gb, bits);
}
-static int dca_parse_audio_coding_header(DCAContext *s, int base_channel)
+static inline int dca_xxch2index(DCAContext *s, int xxch_ch)
+{
+ int i, base, mask;
+
+ /* locate channel set containing the channel */
+ for (i = -1, base = 0, mask = (s->xxch_core_spkmask & ~DCA_XXCH_LFE1);
+ i <= s->xxch_chset && !(mask & xxch_ch); mask = s->xxch_spk_masks[++i])
+ base += av_popcount(mask);
+
+ return base + av_popcount(mask & (xxch_ch - 1));
+}
+
+static int dca_parse_audio_coding_header(DCAContext *s, int base_channel,
+ int xxch)
{
int i, j;
- static const float adj_table[4] = { 1.0, 1.1250, 1.2500, 1.4375 };
+ static const uint8_t adj_table[4] = { 16, 18, 20, 23 };
static const int bitlen[11] = { 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3 };
static const int thr[11] = { 0, 1, 3, 3, 3, 3, 7, 7, 7, 7, 7 };
+ int hdr_pos = 0, hdr_size = 0;
+ float scale_factor;
+ int this_chans, acc_mask;
+ int embedded_downmix;
+ int nchans, mask[8];
+ int coeff, ichan;
+
+ /* xxch has arbitrary sized audio coding headers */
+ if (xxch) {
+ hdr_pos = get_bits_count(&s->gb);
+ hdr_size = get_bits(&s->gb, 7) + 1;
+ }
+
+ nchans = get_bits(&s->gb, 3) + 1;
+ if (xxch && nchans >= 3) {
+ av_log(s->avctx, AV_LOG_ERROR, "nchans %d is too large\n", nchans);
+ return AVERROR_INVALIDDATA;
+ } else if (nchans + base_channel > DCA_PRIM_CHANNELS_MAX) {
+ av_log(s->avctx, AV_LOG_ERROR, "channel sum %d + %d is too large\n", nchans, base_channel);
+ return AVERROR_INVALIDDATA;
+ }
- s->audio_header.total_channels = get_bits(&s->gb, 3) + 1 + base_channel;
+ s->audio_header.total_channels = nchans + base_channel;
s->audio_header.prim_channels = s->audio_header.total_channels;
+ /* obtain speaker layout mask & downmix coefficients for XXCH */
+ if (xxch) {
+ acc_mask = s->xxch_core_spkmask;
+
+ this_chans = get_bits(&s->gb, s->xxch_nbits_spk_mask - 6) << 6;
+ s->xxch_spk_masks[s->xxch_chset] = this_chans;
+ s->xxch_chset_nch[s->xxch_chset] = nchans;
+
+ for (i = 0; i <= s->xxch_chset; i++)
+ acc_mask |= s->xxch_spk_masks[i];
+
+ /* check for downmixing information */
+ if (get_bits1(&s->gb)) {
+ embedded_downmix = get_bits1(&s->gb);
+ coeff = get_bits(&s->gb, 6);
+
+ if (coeff<1 || coeff>61) {
+ av_log(s->avctx, AV_LOG_ERROR, "6bit coeff %d is out of range\n", coeff);
+ return AVERROR_INVALIDDATA;
+ }
+
+ scale_factor = -1.0f / dca_dmix_code((coeff<<2)-3);
+
+ s->xxch_dmix_sf[s->xxch_chset] = scale_factor;
+
+ for (i = base_channel; i < s->audio_header.prim_channels; i++) {
+ mask[i] = get_bits(&s->gb, s->xxch_nbits_spk_mask);
+ }
+
+ for (j = base_channel; j < s->audio_header.prim_channels; j++) {
+ memset(s->xxch_dmix_coeff[j], 0, sizeof(s->xxch_dmix_coeff[0]));
+ s->xxch_dmix_embedded |= (embedded_downmix << j);
+ for (i = 0; i < s->xxch_nbits_spk_mask; i++) {
+ if (mask[j] & (1 << i)) {
+ if ((1 << i) == DCA_XXCH_LFE1) {
+ av_log(s->avctx, AV_LOG_WARNING,
+ "DCA-XXCH: dmix to LFE1 not supported.\n");
+ continue;
+ }
+
+ coeff = get_bits(&s->gb, 7);
+ ichan = dca_xxch2index(s, 1 << i);
+ if ((coeff&63)<1 || (coeff&63)>61) {
+ av_log(s->avctx, AV_LOG_ERROR, "7bit coeff %d is out of range\n", coeff);
+ return AVERROR_INVALIDDATA;
+ }
+ s->xxch_dmix_coeff[j][ichan] = dca_dmix_code((coeff<<2)-3);
+ }
+ }
+ }
+ }
+ }
+
if (s->audio_header.prim_channels > DCA_PRIM_CHANNELS_MAX)
s->audio_header.prim_channels = DCA_PRIM_CHANNELS_MAX;
FATE_DCA-$(CONFIG_DTS_DEMUXER) += fate-dca-xll
fate-dca-xll: CMD = pcm -disable_xll 0 -i $(TARGET_SAMPLES)/dts/master_audio_7.1_24bit.dts
fate-dca-xll: CMP = oneoff
- fate-dca-xll: REF = $(SAMPLES)/dts/master_audio_7.1_24bit.pcm
+ fate-dca-xll: REF = $(SAMPLES)/dts/master_audio_7.1_24bit_2.pcm
-FATE_SAMPLES_AVCONV-$(CONFIG_DCA_DECODER) += $(FATE_DCA-yes)
+FATE_SAMPLES_AUDIO-$(CONFIG_DCA_DECODER) += $(FATE_DCA-yes)
fate-dca: $(FATE_DCA-yes)
-FATE_SAMPLES_AVCONV-$(call DEMDEC, DSICIN, DSICINAUDIO) += fate-delphine-cin-audio
+FATE_SAMPLES_AUDIO-$(call DEMDEC, DSICIN, DSICINAUDIO) += fate-delphine-cin-audio
fate-delphine-cin-audio: CMD = framecrc -i $(TARGET_SAMPLES)/delphine-cin/LOGO-partial.CIN -vn
-FATE_SAMPLES_AVCONV-$(call DEMDEC, DSS, DSS_SP) += fate-dss-lp fate-dss-sp
+FATE_SAMPLES_AUDIO-$(call DEMDEC, DSS, DSS_SP) += fate-dss-lp fate-dss-sp
fate-dss-lp: CMD = framecrc -i $(TARGET_SAMPLES)/dss/lp.dss -frames 30
fate-dss-sp: CMD = framecrc -i $(TARGET_SAMPLES)/dss/sp.dss -frames 30
-FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, IMC) += fate-imc
+FATE_SAMPLES_AUDIO-$(call DEMDEC, DTS, DCA) += fate-dts_es
+fate-dts_es: CMD = pcm -i $(TARGET_SAMPLES)/dts/dts_es.dts
+fate-dts_es: CMP = oneoff
- fate-dts_es: REF = $(SAMPLES)/dts/dts_es.pcm
++fate-dts_es: REF = $(SAMPLES)/dts/dts_es_2.pcm
+
+FATE_SAMPLES_AUDIO-$(call DEMDEC, AVI, IMC) += fate-imc
fate-imc: CMD = pcm -i $(TARGET_SAMPLES)/imc/imc.avi
fate-imc: CMP = oneoff
fate-imc: REF = $(SAMPLES)/imc/imc.pcm