+static int chs_assemble_freq_bands(DCAXllDecoder *s, DCAXllChSet *c)
+{
+ int ch, nsamples = s->nframesamples;
+ int32_t *ptr;
+
+ av_assert1(c->nfreqbands > 1);
+
+ // Reallocate frequency band assembly buffer
+ av_fast_malloc(&c->sample_buffer[2], &c->sample_size[2],
+ 2 * nsamples * c->nchannels * sizeof(int32_t));
+ if (!c->sample_buffer[2])
+ return AVERROR(ENOMEM);
+
+ // Assemble frequency bands 0 and 1
+ ptr = c->sample_buffer[2];
+ for (ch = 0; ch < c->nchannels; ch++) {
+ int32_t *band0 = c->bands[0].msb_sample_buffer[ch];
+ int32_t *band1 = c->bands[1].msb_sample_buffer[ch];
+
+ // Copy decimator history
+ memcpy(band0 - DCA_XLL_DECI_HISTORY_MAX,
+ c->deci_history[ch], sizeof(c->deci_history[0]));
+
+ // Filter
+ s->dcadsp->assemble_freq_bands(ptr, band0, band1,
+ ff_dca_xll_band_coeff,
+ nsamples);
+
+ // Remap output channel pointer to assembly buffer
+ s->output_samples[c->ch_remap[ch]] = ptr;
+ ptr += nsamples * 2;
+ }
+
+ return 0;
+}
+
+static int parse_common_header(DCAXllDecoder *s)
+{
+ int stream_ver, header_size, frame_size_nbits, nframesegs_log2;
+
+ // XLL extension sync word
+ if (get_bits_long(&s->gb, 32) != DCA_SYNCWORD_XLL) {
+ av_log(s->avctx, AV_LOG_VERBOSE, "Invalid XLL sync word\n");
+ return AVERROR(EAGAIN);
+ }
+
+ // Version number
+ stream_ver = get_bits(&s->gb, 4) + 1;
+ if (stream_ver > 1) {
+ avpriv_request_sample(s->avctx, "XLL stream version %d", stream_ver);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ // Lossless frame header length
+ header_size = get_bits(&s->gb, 8) + 1;
+
+ // Check CRC
+ if ((s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))
+ && ff_dca_check_crc(&s->gb, 32, header_size * 8)) {
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid XLL common header checksum\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ // Number of bits used to read frame size
+ frame_size_nbits = get_bits(&s->gb, 5) + 1;
+
+ // Number of bytes in a lossless frame
+ s->frame_size = get_bits_long(&s->gb, frame_size_nbits);
+ if (s->frame_size < 0 || s->frame_size >= DCA_XLL_PBR_BUFFER_MAX) {
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid XLL frame size (%d bytes)\n", s->frame_size);
+ return AVERROR_INVALIDDATA;
+ }
+ s->frame_size++;
+
+ // Number of channels sets per frame
+ s->nchsets = get_bits(&s->gb, 4) + 1;
+ if (s->nchsets > DCA_XLL_CHSETS_MAX) {
+ avpriv_request_sample(s->avctx, "%d XLL channel sets", s->nchsets);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ // Number of segments per frame
+ nframesegs_log2 = get_bits(&s->gb, 4);
+ s->nframesegs = 1 << nframesegs_log2;
+ if (s->nframesegs > 1024) {
+ av_log(s->avctx, AV_LOG_ERROR, "Too many segments per XLL frame\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ // Samples in segment per one frequency band for the first channel set
+ // Maximum value is 256 for sampling frequencies <= 48 kHz
+ // Maximum value is 512 for sampling frequencies > 48 kHz
+ s->nsegsamples_log2 = get_bits(&s->gb, 4);
+ if (!s->nsegsamples_log2) {
+ av_log(s->avctx, AV_LOG_ERROR, "Too few samples per XLL segment\n");
+ return AVERROR_INVALIDDATA;
+ }
+ s->nsegsamples = 1 << s->nsegsamples_log2;
+ if (s->nsegsamples > 512) {
+ av_log(s->avctx, AV_LOG_ERROR, "Too many samples per XLL segment\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ // Samples in frame per one frequency band for the first channel set
+ s->nframesamples_log2 = s->nsegsamples_log2 + nframesegs_log2;
+ s->nframesamples = 1 << s->nframesamples_log2;
+ if (s->nframesamples > 65536) {
+ av_log(s->avctx, AV_LOG_ERROR, "Too many samples per XLL frame\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ // Number of bits used to read segment size
+ s->seg_size_nbits = get_bits(&s->gb, 5) + 1;
+
+ // Presence of CRC16 within each frequency band
+ // 0 - No CRC16 within band
+ // 1 - CRC16 placed at the end of MSB0
+ // 2 - CRC16 placed at the end of MSB0 and LSB0
+ // 3 - CRC16 placed at the end of MSB0 and LSB0 and other frequency bands
+ s->band_crc_present = get_bits(&s->gb, 2);
+
+ // MSB/LSB split flag
+ s->scalable_lsbs = get_bits1(&s->gb);
+
+ // Channel position mask
+ s->ch_mask_nbits = get_bits(&s->gb, 5) + 1;
+
+ // Fixed LSB width
+ if (s->scalable_lsbs)
+ s->fixed_lsb_width = get_bits(&s->gb, 4);
+ else
+ s->fixed_lsb_width = 0;
+
+ // Reserved
+ // Byte align
+ // Header CRC16 protection
+ if (ff_dca_seek_bits(&s->gb, header_size * 8)) {
+ av_log(s->avctx, AV_LOG_ERROR, "Read past end of XLL common header\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ return 0;
+}
+
+static int is_hier_dmix_chset(DCAXllChSet *c)
+{
+ return !c->primary_chset && c->dmix_embedded && c->hier_chset;
+}
+
+static DCAXllChSet *find_next_hier_dmix_chset(DCAXllDecoder *s, DCAXllChSet *c)
+{
+ if (c->hier_chset)
+ while (++c < &s->chset[s->nchsets])
+ if (is_hier_dmix_chset(c))
+ return c;
+
+ return NULL;
+}
+
+static void prescale_down_mix(DCAXllChSet *c, DCAXllChSet *o)
+{
+ int i, j, *coeff_ptr = c->dmix_coeff;
+
+ for (i = 0; i < c->hier_ofs; i++) {
+ int scale = o->dmix_scale[i];
+ int scale_inv = o->dmix_scale_inv[i];
+ c->dmix_scale[i] = mul15(c->dmix_scale[i], scale);
+ c->dmix_scale_inv[i] = mul16(c->dmix_scale_inv[i], scale_inv);
+ for (j = 0; j < c->nchannels; j++) {
+ int coeff = mul16(*coeff_ptr, scale_inv);
+ *coeff_ptr++ = mul15(coeff, o->dmix_scale[c->hier_ofs + j]);
+ }
+ }
+}
+
+static int parse_sub_headers(DCAXllDecoder *s, DCAExssAsset *asset)
+{
+ DCAContext *dca = s->avctx->priv_data;
+ DCAXllChSet *c;
+ int i, ret;
+
+ // Parse channel set headers
+ s->nfreqbands = 0;
+ s->nchannels = 0;
+ s->nreschsets = 0;
+ for (i = 0, c = s->chset; i < s->nchsets; i++, c++) {
+ c->hier_ofs = s->nchannels;
+ if ((ret = chs_parse_header(s, c, asset)) < 0)
+ return ret;
+ if (c->nfreqbands > s->nfreqbands)
+ s->nfreqbands = c->nfreqbands;
+ if (c->hier_chset)
+ s->nchannels += c->nchannels;
+ if (c->residual_encode != (1 << c->nchannels) - 1)
+ s->nreschsets++;
+ }
+
+ // Pre-scale downmixing coefficients for all non-primary channel sets
+ for (i = s->nchsets - 1, c = &s->chset[i]; i > 0; i--, c--) {
+ if (is_hier_dmix_chset(c)) {
+ DCAXllChSet *o = find_next_hier_dmix_chset(s, c);
+ if (o)
+ prescale_down_mix(c, o);
+ }
+ }
+
+ // Determine number of active channel sets to decode
+ switch (dca->request_channel_layout) {
+ case DCA_SPEAKER_LAYOUT_STEREO:
+ s->nactivechsets = 1;
+ break;
+ case DCA_SPEAKER_LAYOUT_5POINT0:
+ case DCA_SPEAKER_LAYOUT_5POINT1:
+ s->nactivechsets = (s->chset[0].nchannels < 5 && s->nchsets > 1) ? 2 : 1;
+ break;
+ default:
+ s->nactivechsets = s->nchsets;
+ break;
+ }
+
+ return 0;
+}
+
+static int parse_navi_table(DCAXllDecoder *s)
+{
+ int chs, seg, band, navi_nb, navi_pos, *navi_ptr;
+ DCAXllChSet *c;
+
+ // Determine size of NAVI table
+ navi_nb = s->nfreqbands * s->nframesegs * s->nchsets;
+ if (navi_nb > 1024) {
+ av_log(s->avctx, AV_LOG_ERROR, "Too many NAVI entries (%d)\n", navi_nb);
+ return AVERROR_INVALIDDATA;
+ }
+
+ // Reallocate NAVI table
+ av_fast_malloc(&s->navi, &s->navi_size, navi_nb * sizeof(*s->navi));
+ if (!s->navi)
+ return AVERROR(ENOMEM);
+
+ // Parse NAVI
+ navi_pos = get_bits_count(&s->gb);
+ navi_ptr = s->navi;
+ for (band = 0; band < s->nfreqbands; band++) {
+ for (seg = 0; seg < s->nframesegs; seg++) {
+ for (chs = 0, c = s->chset; chs < s->nchsets; chs++, c++) {
+ int size = 0;
+ if (c->nfreqbands > band) {
+ size = get_bits_long(&s->gb, s->seg_size_nbits);
+ if (size < 0 || size >= s->frame_size) {
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid NAVI segment size (%d bytes)\n", size);
+ return AVERROR_INVALIDDATA;