int ff_dca_xll_filter_frame(DCAXllDecoder *s, AVFrame *frame)

{

    AVCodecContext *avctx = s->avctx;

    DCAContext *dca = avctx->priv_data;

    DCAExssAsset *asset = &dca->exss.assets[0];

    DCAXllChSet *p = &s->chset[0], *c;

    enum AVMatrixEncoding matrix_encoding = AV_MATRIX_ENCODING_NONE;

    int i, j, k, ret, shift, nsamples, request_mask;

    int ch_remap[DCA_SPEAKER_COUNT];



    // Force lossy downmixed output during recovery

    if (dca->packet & DCA_PACKET_RECOVERY) {

        for (i = 0, c = s->chset; i < s->nchsets; i++, c++) {

            if (i < s->nactivechsets)

                force_lossy_output(s, c);



            if (!c->primary_chset)

                c->dmix_embedded = 0;

        }



        s->scalable_lsbs = 0;

        s->fixed_lsb_width = 0;

    }



    // Filter frequency bands for active channel sets

    s->output_mask = 0;

    for (i = 0, c = s->chset; i < s->nactivechsets; i++, c++) {

        chs_filter_band_data(s, c, 0);



        if (c->residual_encode != (1 << c->nchannels) - 1

            && (ret = combine_residual_frame(s, c)) < 0)

            return ret;



        if (s->scalable_lsbs)

            chs_assemble_msbs_lsbs(s, c, 0);



        if (c->nfreqbands > 1) {

            chs_filter_band_data(s, c, 1);

            chs_assemble_msbs_lsbs(s, c, 1);

        }



        s->output_mask |= c->ch_mask;

    }



    // Undo hierarchial downmix and/or apply scaling

    for (i = 1, c = &s->chset[1]; i < s->nchsets; i++, c++) {

        if (!is_hier_dmix_chset(c))

            continue;



        if (i >= s->nactivechsets) {

            for (j = 0; j < c->nfreqbands; j++)

                if (c->bands[j].dmix_embedded)

                    scale_down_mix(s, c, j);

            break;

        }



        for (j = 0; j < c->nfreqbands; j++)

            if (c->bands[j].dmix_embedded)

                undo_down_mix(s, c, j);

    }



    // Assemble frequency bands for active channel sets

    if (s->nfreqbands > 1) {

        for (i = 0; i < s->nactivechsets; i++)

            if ((ret = chs_assemble_freq_bands(s, &s->chset[i])) < 0)

                return ret;

    }



    // Normalize to regular 5.1 layout if downmixing

    if (dca->request_channel_layout) {

        if (s->output_mask & DCA_SPEAKER_MASK_Lss) {

            s->output_samples[DCA_SPEAKER_Ls] = s->output_samples[DCA_SPEAKER_Lss];

            s->output_mask = (s->output_mask & ~DCA_SPEAKER_MASK_Lss) | DCA_SPEAKER_MASK_Ls;

        }

        if (s->output_mask & DCA_SPEAKER_MASK_Rss) {

            s->output_samples[DCA_SPEAKER_Rs] = s->output_samples[DCA_SPEAKER_Rss];

            s->output_mask = (s->output_mask & ~DCA_SPEAKER_MASK_Rss) | DCA_SPEAKER_MASK_Rs;

        }

    }



    // Handle downmixing to stereo request

    if (dca->request_channel_layout == DCA_SPEAKER_LAYOUT_STEREO

        && DCA_HAS_STEREO(s->output_mask) && p->dmix_embedded

        && (p->dmix_type == DCA_DMIX_TYPE_LoRo ||

            p->dmix_type == DCA_DMIX_TYPE_LtRt))

        request_mask = DCA_SPEAKER_LAYOUT_STEREO;

    else

        request_mask = s->output_mask;

    if (!ff_dca_set_channel_layout(avctx, ch_remap, request_mask))

        return AVERROR(EINVAL);



    avctx->sample_rate = p->freq << (s->nfreqbands - 1);



    switch (p->storage_bit_res) {

    case 16:

        avctx->sample_fmt = AV_SAMPLE_FMT_S16P;

        shift = 16 - p->pcm_bit_res;

        break;

    case 20:

    case 24:

        avctx->sample_fmt = AV_SAMPLE_FMT_S32P;

        shift = 24 - p->pcm_bit_res;

        break;

    default:

        return AVERROR(EINVAL);

    }



    avctx->bits_per_raw_sample = p->storage_bit_res;

    avctx->profile = FF_PROFILE_DTS_HD_MA;

    avctx->bit_rate = 0;



    frame->nb_samples = nsamples = s->nframesamples << (s->nfreqbands - 1);

    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)

        return ret;



    // Downmix primary channel set to stereo

    if (request_mask != s->output_mask) {

        ff_dca_downmix_to_stereo_fixed(s->dcadsp, s->output_samples,

                                       p->dmix_coeff, nsamples,

                                       s->output_mask);

    }



    for (i = 0; i < avctx->channels; i++) {

        int32_t *samples = s->output_samples[ch_remap[i]];

        if (frame->format == AV_SAMPLE_FMT_S16P) {

            int16_t *plane = (int16_t *)frame->extended_data[i];

            for (k = 0; k < nsamples; k++)

                plane[k] = av_clip_int16(samples[k] * (1 << shift));

        } else {

            int32_t *plane = (int32_t *)frame->extended_data[i];

            for (k = 0; k < nsamples; k++)

                plane[k] = clip23(samples[k] * (1 << shift)) * (1 << 8);

        }

    }



    if (!asset->one_to_one_map_ch_to_spkr) {

        if (asset->representation_type == DCA_REPR_TYPE_LtRt)

            matrix_encoding = AV_MATRIX_ENCODING_DOLBY;

        else if (asset->representation_type == DCA_REPR_TYPE_LhRh)

            matrix_encoding = AV_MATRIX_ENCODING_DOLBYHEADPHONE;

    } else if (request_mask != s->output_mask && p->dmix_type == DCA_DMIX_TYPE_LtRt) {

        matrix_encoding = AV_MATRIX_ENCODING_DOLBY;

    }

    if ((ret = ff_side_data_update_matrix_encoding(frame, matrix_encoding)) < 0)

        return ret;



    return 0;

}
