int ff_dca_lbr_parse(DCALbrDecoder *s, uint8_t *data, DCAExssAsset *asset)

{

    struct {

        LBRChunk    lfe;

        LBRChunk    tonal;

        LBRChunk    tonal_grp[5];

        LBRChunk    grid1[DCA_LBR_CHANNELS / 2];

        LBRChunk    hr_grid[DCA_LBR_CHANNELS / 2];

        LBRChunk    ts1[DCA_LBR_CHANNELS / 2];

        LBRChunk    ts2[DCA_LBR_CHANNELS / 2];

    } chunk = { 0 };



    GetByteContext gb;



    int i, ch, sb, sf, ret, group, chunk_id, chunk_len;



    bytestream2_init(&gb, data + asset->lbr_offset, asset->lbr_size);



    // LBR sync word

    if (bytestream2_get_be32(&gb) != DCA_SYNCWORD_LBR) {

        av_log(s->avctx, AV_LOG_ERROR, "Invalid LBR sync word\n");

        return AVERROR_INVALIDDATA;

    }



    // LBR header type

    switch (bytestream2_get_byte(&gb)) {

    case LBR_HEADER_SYNC_ONLY:

        if (!s->sample_rate) {

            av_log(s->avctx, AV_LOG_ERROR, "LBR decoder not initialized\n");

            return AVERROR_INVALIDDATA;

        }

        break;

    case LBR_HEADER_DECODER_INIT:

        if ((ret = parse_decoder_init(s, &gb)) < 0) {

            s->sample_rate = 0;

            return ret;

        }

        break;

    default:

        av_log(s->avctx, AV_LOG_ERROR, "Invalid LBR header type\n");

        return AVERROR_INVALIDDATA;

    }



    // LBR frame chunk header

    chunk_id = bytestream2_get_byte(&gb);

    chunk_len = (chunk_id & 0x80) ? bytestream2_get_be16(&gb) : bytestream2_get_byte(&gb);



    if (chunk_len > bytestream2_get_bytes_left(&gb)) {

        chunk_len = bytestream2_get_bytes_left(&gb);

        av_log(s->avctx, AV_LOG_WARNING, "LBR frame chunk was truncated\n");

        if (s->avctx->err_recognition & AV_EF_EXPLODE)

            return AVERROR_INVALIDDATA;

    }



    bytestream2_init(&gb, gb.buffer, chunk_len);



    switch (chunk_id & 0x7f) {

    case LBR_CHUNK_FRAME:

        if (s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL)) {

            int checksum = bytestream2_get_be16(&gb);

            uint16_t res = chunk_id;

            res += (chunk_len >> 8) & 0xff;

            res += chunk_len & 0xff;

            for (i = 0; i < chunk_len - 2; i++)

                res += gb.buffer[i];

            if (checksum != res) {

                av_log(s->avctx, AV_LOG_WARNING, "Invalid LBR checksum\n");

                if (s->avctx->err_recognition & AV_EF_EXPLODE)

                    return AVERROR_INVALIDDATA;

            }

        } else {

            bytestream2_skip(&gb, 2);

        }

        break;

    case LBR_CHUNK_FRAME_NO_CSUM:

        break;

    default:

        av_log(s->avctx, AV_LOG_ERROR, "Invalid LBR frame chunk ID\n");

        return AVERROR_INVALIDDATA;

    }



    // Clear current frame

    memset(s->quant_levels, 0, sizeof(s->quant_levels));

    memset(s->sb_indices, 0xff, sizeof(s->sb_indices));

    memset(s->sec_ch_sbms, 0, sizeof(s->sec_ch_sbms));

    memset(s->sec_ch_lrms, 0, sizeof(s->sec_ch_lrms));

    memset(s->ch_pres, 0, sizeof(s->ch_pres));

    memset(s->grid_1_scf, 0, sizeof(s->grid_1_scf));

    memset(s->grid_2_scf, 0, sizeof(s->grid_2_scf));

    memset(s->grid_3_avg, 0, sizeof(s->grid_3_avg));

    memset(s->grid_3_scf, 0, sizeof(s->grid_3_scf));

    memset(s->grid_3_pres, 0, sizeof(s->grid_3_pres));

    memset(s->tonal_scf, 0, sizeof(s->tonal_scf));

    memset(s->lfe_data, 0, sizeof(s->lfe_data));

    s->part_stereo_pres = 0;

    s->framenum = (s->framenum + 1) & 31;



    for (ch = 0; ch < s->nchannels; ch++) {

        for (sb = 0; sb < s->nsubbands / 4; sb++) {

            s->part_stereo[ch][sb][0] = s->part_stereo[ch][sb][4];

            s->part_stereo[ch][sb][4] = 16;

        }

    }



    memset(s->lpc_coeff[s->framenum & 1], 0, sizeof(s->lpc_coeff[0]));



    for (group = 0; group < 5; group++) {

        for (sf = 0; sf < 1 << group; sf++) {

            int sf_idx = ((s->framenum << group) + sf) & 31;

            s->tonal_bounds[group][sf_idx][0] =

            s->tonal_bounds[group][sf_idx][1] = s->ntones;

        }

    }



    // Parse chunk headers

    while (bytestream2_get_bytes_left(&gb) > 0) {

        chunk_id = bytestream2_get_byte(&gb);

        chunk_len = (chunk_id & 0x80) ? bytestream2_get_be16(&gb) : bytestream2_get_byte(&gb);

        chunk_id &= 0x7f;



        if (chunk_len > bytestream2_get_bytes_left(&gb)) {

            chunk_len = bytestream2_get_bytes_left(&gb);

            av_log(s->avctx, AV_LOG_WARNING, "LBR chunk %#x was truncated\n", chunk_id);

            if (s->avctx->err_recognition & AV_EF_EXPLODE)

                return AVERROR_INVALIDDATA;

        }



        switch (chunk_id) {

        case LBR_CHUNK_LFE:

            chunk.lfe.len  = chunk_len;

            chunk.lfe.data = gb.buffer;

            break;



        case LBR_CHUNK_SCF:

        case LBR_CHUNK_TONAL:

        case LBR_CHUNK_TONAL_SCF:

            chunk.tonal.id   = chunk_id;

            chunk.tonal.len  = chunk_len;

            chunk.tonal.data = gb.buffer;

            break;



        case LBR_CHUNK_TONAL_GRP_1:

        case LBR_CHUNK_TONAL_GRP_2:

        case LBR_CHUNK_TONAL_GRP_3:

        case LBR_CHUNK_TONAL_GRP_4:

        case LBR_CHUNK_TONAL_GRP_5:

            i = LBR_CHUNK_TONAL_GRP_5 - chunk_id;

            chunk.tonal_grp[i].id   = i;

            chunk.tonal_grp[i].len  = chunk_len;

            chunk.tonal_grp[i].data = gb.buffer;

            break;



        case LBR_CHUNK_TONAL_SCF_GRP_1:

        case LBR_CHUNK_TONAL_SCF_GRP_2:

        case LBR_CHUNK_TONAL_SCF_GRP_3:

        case LBR_CHUNK_TONAL_SCF_GRP_4:

        case LBR_CHUNK_TONAL_SCF_GRP_5:

            i = LBR_CHUNK_TONAL_SCF_GRP_5 - chunk_id;

            chunk.tonal_grp[i].id   = i;

            chunk.tonal_grp[i].len  = chunk_len;

            chunk.tonal_grp[i].data = gb.buffer;

            break;



        case LBR_CHUNK_RES_GRID_LR:

        case LBR_CHUNK_RES_GRID_LR + 1:

        case LBR_CHUNK_RES_GRID_LR + 2:

            i = chunk_id - LBR_CHUNK_RES_GRID_LR;

            chunk.grid1[i].len  = chunk_len;

            chunk.grid1[i].data = gb.buffer;

            break;



        case LBR_CHUNK_RES_GRID_HR:

        case LBR_CHUNK_RES_GRID_HR + 1:

        case LBR_CHUNK_RES_GRID_HR + 2:

            i = chunk_id - LBR_CHUNK_RES_GRID_HR;

            chunk.hr_grid[i].len  = chunk_len;

            chunk.hr_grid[i].data = gb.buffer;

            break;



        case LBR_CHUNK_RES_TS_1:

        case LBR_CHUNK_RES_TS_1 + 1:

        case LBR_CHUNK_RES_TS_1 + 2:

            i = chunk_id - LBR_CHUNK_RES_TS_1;

            chunk.ts1[i].len  = chunk_len;

            chunk.ts1[i].data = gb.buffer;

            break;



        case LBR_CHUNK_RES_TS_2:

        case LBR_CHUNK_RES_TS_2 + 1:

        case LBR_CHUNK_RES_TS_2 + 2:

            i = chunk_id - LBR_CHUNK_RES_TS_2;

            chunk.ts2[i].len  = chunk_len;

            chunk.ts2[i].data = gb.buffer;

            break;

        }



        bytestream2_skip(&gb, chunk_len);

    }



    // Parse the chunks

    ret = parse_lfe_chunk(s, &chunk.lfe);



    ret |= parse_tonal_chunk(s, &chunk.tonal);



    for (i = 0; i < 5; i++)

        ret |= parse_tonal_group(s, &chunk.tonal_grp[i]);



    for (i = 0; i < (s->nchannels + 1) / 2; i++) {

        int ch1 = i * 2;

        int ch2 = FFMIN(ch1 + 1, s->nchannels - 1);



        if (parse_grid_1_chunk (s, &chunk.grid1  [i], ch1, ch2) < 0 ||

            parse_high_res_grid(s, &chunk.hr_grid[i], ch1, ch2) < 0) {

            ret = -1;

            continue;

        }



        // TS chunks depend on both grids. TS_2 depends on TS_1.

        if (!chunk.grid1[i].len || !chunk.hr_grid[i].len || !chunk.ts1[i].len)

            continue;



        if (parse_ts1_chunk(s, &chunk.ts1[i], ch1, ch2) < 0 ||

            parse_ts2_chunk(s, &chunk.ts2[i], ch1, ch2) < 0) {

            ret = -1;

            continue;

        }

    }



    if (ret < 0 && (s->avctx->err_recognition & AV_EF_EXPLODE))

        return AVERROR_INVALIDDATA;



    return 0;

}

int ff_dca_lbr_parse(DCALbrDecoder *s, uint8_t *data, DCAExssAsset *asset)

{

    struct {

        LBRChunk    lfe;

        LBRChunk    tonal;

        LBRChunk    tonal_grp[5];

        LBRChunk    grid1[DCA_LBR_CHANNELS / 2];

        LBRChunk    hr_grid[DCA_LBR_CHANNELS / 2];

        LBRChunk    ts1[DCA_LBR_CHANNELS / 2];

        LBRChunk    ts2[DCA_LBR_CHANNELS / 2];

    } chunk = { 0 };



    GetByteContext gb;



    int i, ch, sb, sf, ret, group, chunk_id, chunk_len;



    bytestream2_init(&gb, data + asset->lbr_offset, asset->lbr_size);



    

    if (bytestream2_get_be32(&gb) != DCA_SYNCWORD_LBR) {

        av_log(s->avctx, AV_LOG_ERROR, "Invalid LBR sync word\n");

        return AVERROR_INVALIDDATA;

    }



    

    switch (bytestream2_get_byte(&gb)) {

    case LBR_HEADER_SYNC_ONLY:

        if (!s->sample_rate) {

            av_log(s->avctx, AV_LOG_ERROR, "LBR decoder not initialized\n");

            return AVERROR_INVALIDDATA;

        }

        break;

    case LBR_HEADER_DECODER_INIT:

        if ((ret = parse_decoder_init(s, &gb)) < 0) {

            s->sample_rate = 0;

            return ret;

        }

        break;

    default:

        av_log(s->avctx, AV_LOG_ERROR, "Invalid LBR header type\n");

        return AVERROR_INVALIDDATA;

    }



    

    chunk_id = bytestream2_get_byte(&gb);

    chunk_len = (chunk_id & 0x80) ? bytestream2_get_be16(&gb) : bytestream2_get_byte(&gb);



    if (chunk_len > bytestream2_get_bytes_left(&gb)) {

        chunk_len = bytestream2_get_bytes_left(&gb);

        av_log(s->avctx, AV_LOG_WARNING, "LBR frame chunk was truncated\n");

        if (s->avctx->err_recognition & AV_EF_EXPLODE)

            return AVERROR_INVALIDDATA;

    }



    bytestream2_init(&gb, gb.buffer, chunk_len);



    switch (chunk_id & 0x7f) {

    case LBR_CHUNK_FRAME:

        if (s->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL)) {

            int checksum = bytestream2_get_be16(&gb);

            uint16_t res = chunk_id;

            res += (chunk_len >> 8) & 0xff;

            res += chunk_len & 0xff;

            for (i = 0; i < chunk_len - 2; i++)

                res += gb.buffer[i];

            if (checksum != res) {

                av_log(s->avctx, AV_LOG_WARNING, "Invalid LBR checksum\n");

                if (s->avctx->err_recognition & AV_EF_EXPLODE)

                    return AVERROR_INVALIDDATA;

            }

        } else {

            bytestream2_skip(&gb, 2);

        }

        break;

    case LBR_CHUNK_FRAME_NO_CSUM:

        break;

    default:

        av_log(s->avctx, AV_LOG_ERROR, "Invalid LBR frame chunk ID\n");

        return AVERROR_INVALIDDATA;

    }



    

    memset(s->quant_levels, 0, sizeof(s->quant_levels));

    memset(s->sb_indices, 0xff, sizeof(s->sb_indices));

    memset(s->sec_ch_sbms, 0, sizeof(s->sec_ch_sbms));

    memset(s->sec_ch_lrms, 0, sizeof(s->sec_ch_lrms));

    memset(s->ch_pres, 0, sizeof(s->ch_pres));

    memset(s->grid_1_scf, 0, sizeof(s->grid_1_scf));

    memset(s->grid_2_scf, 0, sizeof(s->grid_2_scf));

    memset(s->grid_3_avg, 0, sizeof(s->grid_3_avg));

    memset(s->grid_3_scf, 0, sizeof(s->grid_3_scf));

    memset(s->grid_3_pres, 0, sizeof(s->grid_3_pres));

    memset(s->tonal_scf, 0, sizeof(s->tonal_scf));

    memset(s->lfe_data, 0, sizeof(s->lfe_data));

    s->part_stereo_pres = 0;

    s->framenum = (s->framenum + 1) & 31;



    for (ch = 0; ch < s->nchannels; ch++) {

        for (sb = 0; sb < s->nsubbands / 4; sb++) {

            s->part_stereo[ch][sb][0] = s->part_stereo[ch][sb][4];

            s->part_stereo[ch][sb][4] = 16;

        }

    }



    memset(s->lpc_coeff[s->framenum & 1], 0, sizeof(s->lpc_coeff[0]));



    for (group = 0; group < 5; group++) {

        for (sf = 0; sf < 1 << group; sf++) {

            int sf_idx = ((s->framenum << group) + sf) & 31;

            s->tonal_bounds[group][sf_idx][0] =

            s->tonal_bounds[group][sf_idx][1] = s->ntones;

        }

    }



    

    while (bytestream2_get_bytes_left(&gb) > 0) {

        chunk_id = bytestream2_get_byte(&gb);

        chunk_len = (chunk_id & 0x80) ? bytestream2_get_be16(&gb) : bytestream2_get_byte(&gb);

        chunk_id &= 0x7f;



        if (chunk_len > bytestream2_get_bytes_left(&gb)) {

            chunk_len = bytestream2_get_bytes_left(&gb);

            av_log(s->avctx, AV_LOG_WARNING, "LBR chunk %#x was truncated\n", chunk_id);

            if (s->avctx->err_recognition & AV_EF_EXPLODE)

                return AVERROR_INVALIDDATA;

        }



        switch (chunk_id) {

        case LBR_CHUNK_LFE:

            chunk.lfe.len  = chunk_len;

            chunk.lfe.data = gb.buffer;

            break;



        case LBR_CHUNK_SCF:

        case LBR_CHUNK_TONAL:

        case LBR_CHUNK_TONAL_SCF:

            chunk.tonal.id   = chunk_id;

            chunk.tonal.len  = chunk_len;

            chunk.tonal.data = gb.buffer;

            break;



        case LBR_CHUNK_TONAL_GRP_1:

        case LBR_CHUNK_TONAL_GRP_2:

        case LBR_CHUNK_TONAL_GRP_3:

        case LBR_CHUNK_TONAL_GRP_4:

        case LBR_CHUNK_TONAL_GRP_5:

            i = LBR_CHUNK_TONAL_GRP_5 - chunk_id;

            chunk.tonal_grp[i].id   = i;

            chunk.tonal_grp[i].len  = chunk_len;

            chunk.tonal_grp[i].data = gb.buffer;

            break;



        case LBR_CHUNK_TONAL_SCF_GRP_1:

        case LBR_CHUNK_TONAL_SCF_GRP_2:

        case LBR_CHUNK_TONAL_SCF_GRP_3:

        case LBR_CHUNK_TONAL_SCF_GRP_4:

        case LBR_CHUNK_TONAL_SCF_GRP_5:

            i = LBR_CHUNK_TONAL_SCF_GRP_5 - chunk_id;

            chunk.tonal_grp[i].id   = i;

            chunk.tonal_grp[i].len  = chunk_len;

            chunk.tonal_grp[i].data = gb.buffer;

            break;



        case LBR_CHUNK_RES_GRID_LR:

        case LBR_CHUNK_RES_GRID_LR + 1:

        case LBR_CHUNK_RES_GRID_LR + 2:

            i = chunk_id - LBR_CHUNK_RES_GRID_LR;

            chunk.grid1[i].len  = chunk_len;

            chunk.grid1[i].data = gb.buffer;

            break;



        case LBR_CHUNK_RES_GRID_HR:

        case LBR_CHUNK_RES_GRID_HR + 1:

        case LBR_CHUNK_RES_GRID_HR + 2:

            i = chunk_id - LBR_CHUNK_RES_GRID_HR;

            chunk.hr_grid[i].len  = chunk_len;

            chunk.hr_grid[i].data = gb.buffer;

            break;



        case LBR_CHUNK_RES_TS_1:

        case LBR_CHUNK_RES_TS_1 + 1:

        case LBR_CHUNK_RES_TS_1 + 2:

            i = chunk_id - LBR_CHUNK_RES_TS_1;

            chunk.ts1[i].len  = chunk_len;

            chunk.ts1[i].data = gb.buffer;

            break;



        case LBR_CHUNK_RES_TS_2:

        case LBR_CHUNK_RES_TS_2 + 1:

        case LBR_CHUNK_RES_TS_2 + 2:

            i = chunk_id - LBR_CHUNK_RES_TS_2;

            chunk.ts2[i].len  = chunk_len;

            chunk.ts2[i].data = gb.buffer;

            break;

        }



        bytestream2_skip(&gb, chunk_len);

    }



    

    ret = parse_lfe_chunk(s, &chunk.lfe);



    ret |= parse_tonal_chunk(s, &chunk.tonal);



    for (i = 0; i < 5; i++)

        ret |= parse_tonal_group(s, &chunk.tonal_grp[i]);



    for (i = 0; i < (s->nchannels + 1) / 2; i++) {

        int ch1 = i * 2;

        int ch2 = FFMIN(ch1 + 1, s->nchannels - 1);



        if (parse_grid_1_chunk (s, &chunk.grid1  [i], ch1, ch2) < 0 ||

            parse_high_res_grid(s, &chunk.hr_grid[i], ch1, ch2) < 0) {

            ret = -1;

            continue;

        }



        

        if (!chunk.grid1[i].len || !chunk.hr_grid[i].len || !chunk.ts1[i].len)

            continue;



        if (parse_ts1_chunk(s, &chunk.ts1[i], ch1, ch2) < 0 ||

            parse_ts2_chunk(s, &chunk.ts2[i], ch1, ch2) < 0) {

            ret = -1;

            continue;

        }

    }



    if (ret < 0 && (s->avctx->err_recognition & AV_EF_EXPLODE))

        return AVERROR_INVALIDDATA;



    return 0;

}

    } chunk = { 0 };
int FUNC_0(DCALbrDecoder *VAR_0, uint8_t *VAR_1, DCAExssAsset *VAR_2)

{

    struct {

        LBRChunk    lfe;

        LBRChunk    tonal;

        LBRChunk    tonal_grp[5];

        LBRChunk    grid1[DCA_LBR_CHANNELS / 2];

        LBRChunk    hr_grid[DCA_LBR_CHANNELS / 2];

        LBRChunk    ts1[DCA_LBR_CHANNELS / 2];

        LBRChunk    ts2[DCA_LBR_CHANNELS / 2];

    } VAR_3 = { 0 };



    GetByteContext gb;



    int VAR_4, VAR_5, VAR_6, VAR_7, VAR_8, VAR_9, VAR_10, VAR_11;



    bytestream2_init(&gb, VAR_1 + VAR_2->lbr_offset, VAR_2->lbr_size);



    

    if (bytestream2_get_be32(&gb) != DCA_SYNCWORD_LBR) {

        av_log(VAR_0->avctx, AV_LOG_ERROR, "Invalid LBR sync word\n");

        return AVERROR_INVALIDDATA;

    }



    

    switch (bytestream2_get_byte(&gb)) {

    case LBR_HEADER_SYNC_ONLY:

        if (!VAR_0->sample_rate) {

            av_log(VAR_0->avctx, AV_LOG_ERROR, "LBR decoder not initialized\n");

            return AVERROR_INVALIDDATA;

        }

        break;

    case LBR_HEADER_DECODER_INIT:

        if ((VAR_8 = parse_decoder_init(VAR_0, &gb)) < 0) {

            VAR_0->sample_rate = 0;

            return VAR_8;

        }

        break;

    default:

        av_log(VAR_0->avctx, AV_LOG_ERROR, "Invalid LBR header type\n");

        return AVERROR_INVALIDDATA;

    }



    

    VAR_10 = bytestream2_get_byte(&gb);

    VAR_11 = (VAR_10 & 0x80) ? bytestream2_get_be16(&gb) : bytestream2_get_byte(&gb);



    if (VAR_11 > bytestream2_get_bytes_left(&gb)) {

        VAR_11 = bytestream2_get_bytes_left(&gb);

        av_log(VAR_0->avctx, AV_LOG_WARNING, "LBR frame VAR_3 was truncated\n");

        if (VAR_0->avctx->err_recognition & AV_EF_EXPLODE)

            return AVERROR_INVALIDDATA;

    }



    bytestream2_init(&gb, gb.buffer, VAR_11);



    switch (VAR_10 & 0x7f) {

    case LBR_CHUNK_FRAME:

        if (VAR_0->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL)) {

            int VAR_12 = bytestream2_get_be16(&gb);

            uint16_t res = VAR_10;

            res += (VAR_11 >> 8) & 0xff;

            res += VAR_11 & 0xff;

            for (VAR_4 = 0; VAR_4 < VAR_11 - 2; VAR_4++)

                res += gb.buffer[VAR_4];

            if (VAR_12 != res) {

                av_log(VAR_0->avctx, AV_LOG_WARNING, "Invalid LBR VAR_12\n");

                if (VAR_0->avctx->err_recognition & AV_EF_EXPLODE)

                    return AVERROR_INVALIDDATA;

            }

        } else {

            bytestream2_skip(&gb, 2);

        }

        break;

    case LBR_CHUNK_FRAME_NO_CSUM:

        break;

    default:

        av_log(VAR_0->avctx, AV_LOG_ERROR, "Invalid LBR frame VAR_3 ID\n");

        return AVERROR_INVALIDDATA;

    }



    

    memset(VAR_0->quant_levels, 0, sizeof(VAR_0->quant_levels));

    memset(VAR_0->sb_indices, 0xff, sizeof(VAR_0->sb_indices));

    memset(VAR_0->sec_ch_sbms, 0, sizeof(VAR_0->sec_ch_sbms));

    memset(VAR_0->sec_ch_lrms, 0, sizeof(VAR_0->sec_ch_lrms));

    memset(VAR_0->ch_pres, 0, sizeof(VAR_0->ch_pres));

    memset(VAR_0->grid_1_scf, 0, sizeof(VAR_0->grid_1_scf));

    memset(VAR_0->grid_2_scf, 0, sizeof(VAR_0->grid_2_scf));

    memset(VAR_0->grid_3_avg, 0, sizeof(VAR_0->grid_3_avg));

    memset(VAR_0->grid_3_scf, 0, sizeof(VAR_0->grid_3_scf));

    memset(VAR_0->grid_3_pres, 0, sizeof(VAR_0->grid_3_pres));

    memset(VAR_0->tonal_scf, 0, sizeof(VAR_0->tonal_scf));

    memset(VAR_0->lfe_data, 0, sizeof(VAR_0->lfe_data));

    VAR_0->part_stereo_pres = 0;

    VAR_0->framenum = (VAR_0->framenum + 1) & 31;



    for (VAR_5 = 0; VAR_5 < VAR_0->nchannels; VAR_5++) {

        for (VAR_6 = 0; VAR_6 < VAR_0->nsubbands / 4; VAR_6++) {

            VAR_0->part_stereo[VAR_5][VAR_6][0] = VAR_0->part_stereo[VAR_5][VAR_6][4];

            VAR_0->part_stereo[VAR_5][VAR_6][4] = 16;

        }

    }



    memset(VAR_0->lpc_coeff[VAR_0->framenum & 1], 0, sizeof(VAR_0->lpc_coeff[0]));



    for (VAR_9 = 0; VAR_9 < 5; VAR_9++) {

        for (VAR_7 = 0; VAR_7 < 1 << VAR_9; VAR_7++) {

            int VAR_13 = ((VAR_0->framenum << VAR_9) + VAR_7) & 31;

            VAR_0->tonal_bounds[VAR_9][VAR_13][0] =

            VAR_0->tonal_bounds[VAR_9][VAR_13][1] = VAR_0->ntones;

        }

    }



    

    while (bytestream2_get_bytes_left(&gb) > 0) {

        VAR_10 = bytestream2_get_byte(&gb);

        VAR_11 = (VAR_10 & 0x80) ? bytestream2_get_be16(&gb) : bytestream2_get_byte(&gb);

        VAR_10 &= 0x7f;



        if (VAR_11 > bytestream2_get_bytes_left(&gb)) {

            VAR_11 = bytestream2_get_bytes_left(&gb);

            av_log(VAR_0->avctx, AV_LOG_WARNING, "LBR VAR_3 %#x was truncated\n", VAR_10);

            if (VAR_0->avctx->err_recognition & AV_EF_EXPLODE)

                return AVERROR_INVALIDDATA;

        }



        switch (VAR_10) {

        case LBR_CHUNK_LFE:

            VAR_3.lfe.len  = VAR_11;

            VAR_3.lfe.VAR_1 = gb.buffer;

            break;



        case LBR_CHUNK_SCF:

        case LBR_CHUNK_TONAL:

        case LBR_CHUNK_TONAL_SCF:

            VAR_3.tonal.id   = VAR_10;

            VAR_3.tonal.len  = VAR_11;

            VAR_3.tonal.VAR_1 = gb.buffer;

            break;



        case LBR_CHUNK_TONAL_GRP_1:

        case LBR_CHUNK_TONAL_GRP_2:

        case LBR_CHUNK_TONAL_GRP_3:

        case LBR_CHUNK_TONAL_GRP_4:

        case LBR_CHUNK_TONAL_GRP_5:

            VAR_4 = LBR_CHUNK_TONAL_GRP_5 - VAR_10;

            VAR_3.tonal_grp[VAR_4].id   = VAR_4;

            VAR_3.tonal_grp[VAR_4].len  = VAR_11;

            VAR_3.tonal_grp[VAR_4].VAR_1 = gb.buffer;

            break;



        case LBR_CHUNK_TONAL_SCF_GRP_1:

        case LBR_CHUNK_TONAL_SCF_GRP_2:

        case LBR_CHUNK_TONAL_SCF_GRP_3:

        case LBR_CHUNK_TONAL_SCF_GRP_4:

        case LBR_CHUNK_TONAL_SCF_GRP_5:

            VAR_4 = LBR_CHUNK_TONAL_SCF_GRP_5 - VAR_10;

            VAR_3.tonal_grp[VAR_4].id   = VAR_4;

            VAR_3.tonal_grp[VAR_4].len  = VAR_11;

            VAR_3.tonal_grp[VAR_4].VAR_1 = gb.buffer;

            break;



        case LBR_CHUNK_RES_GRID_LR:

        case LBR_CHUNK_RES_GRID_LR + 1:

        case LBR_CHUNK_RES_GRID_LR + 2:

            VAR_4 = VAR_10 - LBR_CHUNK_RES_GRID_LR;

            VAR_3.grid1[VAR_4].len  = VAR_11;

            VAR_3.grid1[VAR_4].VAR_1 = gb.buffer;

            break;



        case LBR_CHUNK_RES_GRID_HR:

        case LBR_CHUNK_RES_GRID_HR + 1:

        case LBR_CHUNK_RES_GRID_HR + 2:

            VAR_4 = VAR_10 - LBR_CHUNK_RES_GRID_HR;

            VAR_3.hr_grid[VAR_4].len  = VAR_11;

            VAR_3.hr_grid[VAR_4].VAR_1 = gb.buffer;

            break;



        case LBR_CHUNK_RES_TS_1:

        case LBR_CHUNK_RES_TS_1 + 1:

        case LBR_CHUNK_RES_TS_1 + 2:

            VAR_4 = VAR_10 - LBR_CHUNK_RES_TS_1;

            VAR_3.ts1[VAR_4].len  = VAR_11;

            VAR_3.ts1[VAR_4].VAR_1 = gb.buffer;

            break;



        case LBR_CHUNK_RES_TS_2:

        case LBR_CHUNK_RES_TS_2 + 1:

        case LBR_CHUNK_RES_TS_2 + 2:

            VAR_4 = VAR_10 - LBR_CHUNK_RES_TS_2;

            VAR_3.ts2[VAR_4].len  = VAR_11;

            VAR_3.ts2[VAR_4].VAR_1 = gb.buffer;

            break;

        }



        bytestream2_skip(&gb, VAR_11);

    }



    

    VAR_8 = parse_lfe_chunk(VAR_0, &VAR_3.lfe);



    VAR_8 |= parse_tonal_chunk(VAR_0, &VAR_3.tonal);



    for (VAR_4 = 0; VAR_4 < 5; VAR_4++)

        VAR_8 |= parse_tonal_group(VAR_0, &VAR_3.tonal_grp[VAR_4]);



    for (VAR_4 = 0; VAR_4 < (VAR_0->nchannels + 1) / 2; VAR_4++) {

        int ch1 = VAR_4 * 2;

        int ch2 = FFMIN(ch1 + 1, VAR_0->nchannels - 1);



        if (parse_grid_1_chunk (VAR_0, &VAR_3.grid1  [VAR_4], ch1, ch2) < 0 ||

            parse_high_res_grid(VAR_0, &VAR_3.hr_grid[VAR_4], ch1, ch2) < 0) {

            VAR_8 = -1;

            continue;

        }



        

        if (!VAR_3.grid1[VAR_4].len || !VAR_3.hr_grid[VAR_4].len || !VAR_3.ts1[VAR_4].len)

            continue;



        if (parse_ts1_chunk(VAR_0, &VAR_3.ts1[VAR_4], ch1, ch2) < 0 ||

            parse_ts2_chunk(VAR_0, &VAR_3.ts2[VAR_4], ch1, ch2) < 0) {

            VAR_8 = -1;

            continue;

        }

    }



    if (VAR_8 < 0 && (VAR_0->avctx->err_recognition & AV_EF_EXPLODE))

        return AVERROR_INVALIDDATA;



    return 0;

}

int FUNC_0(DCALbrDecoder *VAR_0, uint8_t *VAR_1, DCAExssAsset *VAR_2)
{ struct { LBRChunk    lfe; LBRChunk    tonal; LBRChunk    tonal_grp[5]; LBRChunk    grid1[DCA_LBR_CHANNELS / 2]; LBRChunk    hr_grid[DCA_LBR_CHANNELS / 2]; LBRChunk    ts1[DCA_LBR_CHANNELS / 2]; LBRChunk    ts2[DCA_LBR_CHANNELS / 2]; } VAR_3 = { 0 }; GetByteContext gb; int VAR_4, VAR_5, VAR_6, VAR_7, VAR_8, VAR_9, VAR_10, VAR_11; bytestream2_init(&gb, VAR_1 + VAR_2->lbr_offset, VAR_2->lbr_size); if (bytestream2_get_be32(&gb) != DCA_SYNCWORD_LBR) { av_log(VAR_0->avctx, AV_LOG_ERROR, "Invalid LBR sync word\n"); return AVERROR_INVALIDDATA; } switch (bytestream2_get_byte(&gb)) { case LBR_HEADER_SYNC_ONLY:
if (!VAR_0->sample_rate) { av_log(VAR_0->avctx, AV_LOG_ERROR, "LBR decoder not initialized\n"); return AVERROR_INVALIDDATA; } break; case LBR_HEADER_DECODER_INIT:
if ((VAR_8 = parse_decoder_init(VAR_0, &gb)) < 0) { VAR_0->sample_rate = 0; return VAR_8; } break; default:
av_log(VAR_0->avctx, AV_LOG_ERROR, "Invalid LBR header type\n"); return AVERROR_INVALIDDATA; } VAR_10 = bytestream2_get_byte(&gb); VAR_11 = (VAR_10 & 0x80) ? bytestream2_get_be16(&gb) : bytestream2_get_byte(&gb); if (VAR_11 > bytestream2_get_bytes_left(&gb)) { VAR_11 = bytestream2_get_bytes_left(&gb); av_log(VAR_0->avctx, AV_LOG_WARNING, "LBR frame VAR_3 was truncated\n"); if (VAR_0->avctx->err_recognition & AV_EF_EXPLODE)
return AVERROR_INVALIDDATA; } bytestream2_init(&gb, gb.buffer, VAR_11); switch (VAR_10 & 0x7f) { case LBR_CHUNK_FRAME:
if (VAR_0->avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL)) { int VAR_12 = bytestream2_get_be16(&gb); uint16_t res = VAR_10; res += (VAR_11 >> 8) & 0xff; res += VAR_11 & 0xff; for (VAR_4 = 0; VAR_4 < VAR_11 - 2; VAR_4++) res += gb.buffer[VAR_4]; if (VAR_12 != res) { av_log(VAR_0->avctx, AV_LOG_WARNING, "Invalid LBR VAR_12\n"); if (VAR_0->avctx->err_recognition & AV_EF_EXPLODE)
return AVERROR_INVALIDDATA; } } else { bytestream2_skip(&gb, 2); } break; case LBR_CHUNK_FRAME_NO_CSUM:
break; default:
av_log(VAR_0->avctx, AV_LOG_ERROR, "Invalid LBR frame VAR_3 ID\n"); return AVERROR_INVALIDDATA; } memset(VAR_0->quant_levels, 0, sizeof(VAR_0->quant_levels)); memset(VAR_0->sb_indices, 0xff, sizeof(VAR_0->sb_indices)); memset(VAR_0->sec_ch_sbms, 0, sizeof(VAR_0->sec_ch_sbms)); memset(VAR_0->sec_ch_lrms, 0, sizeof(VAR_0->sec_ch_lrms)); memset(VAR_0->ch_pres, 0, sizeof(VAR_0->ch_pres)); memset(VAR_0->grid_1_scf, 0, sizeof(VAR_0->grid_1_scf)); memset(VAR_0->grid_2_scf, 0, sizeof(VAR_0->grid_2_scf)); memset(VAR_0->grid_3_avg, 0, sizeof(VAR_0->grid_3_avg)); memset(VAR_0->grid_3_scf, 0, sizeof(VAR_0->grid_3_scf)); memset(VAR_0->grid_3_pres, 0, sizeof(VAR_0->grid_3_pres)); memset(VAR_0->tonal_scf, 0, sizeof(VAR_0->tonal_scf)); memset(VAR_0->lfe_data, 0, sizeof(VAR_0->lfe_data)); VAR_0->part_stereo_pres = 0; VAR_0->framenum = (VAR_0->framenum + 1) & 31; for (VAR_5 = 0; VAR_5 < VAR_0->nchannels; VAR_5++) { for (VAR_6 = 0; VAR_6 < VAR_0->nsubbands / 4; VAR_6++) { VAR_0->part_stereo[VAR_5][VAR_6][0] = VAR_0->part_stereo[VAR_5][VAR_6][4]; VAR_0->part_stereo[VAR_5][VAR_6][4] = 16; } } memset(VAR_0->lpc_coeff[VAR_0->framenum & 1], 0, sizeof(VAR_0->lpc_coeff[0])); for (VAR_9 = 0; VAR_9 < 5; VAR_9++) { for (VAR_7 = 0; VAR_7 < 1 << VAR_9; VAR_7++) { int VAR_13 = ((VAR_0->framenum << VAR_9) + VAR_7) & 31; VAR_0->tonal_bounds[VAR_9][VAR_13][0] =
VAR_0->tonal_bounds[VAR_9][VAR_13][1] = VAR_0->ntones; } } while (bytestream2_get_bytes_left(&gb) > 0) { VAR_10 = bytestream2_get_byte(&gb); VAR_11 = (VAR_10 & 0x80) ? bytestream2_get_be16(&gb) : bytestream2_get_byte(&gb); VAR_10 &= 0x7f; if (VAR_11 > bytestream2_get_bytes_left(&gb)) { VAR_11 = bytestream2_get_bytes_left(&gb); av_log(VAR_0->avctx, AV_LOG_WARNING, "LBR VAR_3 %#x was truncated\n", VAR_10); if (VAR_0->avctx->err_recognition & AV_EF_EXPLODE)
return AVERROR_INVALIDDATA; } switch (VAR_10) { case LBR_CHUNK_LFE:
VAR_3.lfe.len  = VAR_11; VAR_3.lfe.VAR_1 = gb.buffer; break; case LBR_CHUNK_SCF:
case LBR_CHUNK_TONAL:
case LBR_CHUNK_TONAL_SCF:
VAR_3.tonal.id   = VAR_10; VAR_3.tonal.len  = VAR_11; VAR_3.tonal.VAR_1 = gb.buffer; break; case LBR_CHUNK_TONAL_GRP_1:
case LBR_CHUNK_TONAL_GRP_2:
case LBR_CHUNK_TONAL_GRP_3:
case LBR_CHUNK_TONAL_GRP_4:
case LBR_CHUNK_TONAL_GRP_5:
VAR_4 = LBR_CHUNK_TONAL_GRP_5 - VAR_10; VAR_3.tonal_grp[VAR_4].id   = VAR_4; VAR_3.tonal_grp[VAR_4].len  = VAR_11; VAR_3.tonal_grp[VAR_4].VAR_1 = gb.buffer; break; case LBR_CHUNK_TONAL_SCF_GRP_1:
case LBR_CHUNK_TONAL_SCF_GRP_2:
case LBR_CHUNK_TONAL_SCF_GRP_3:
case LBR_CHUNK_TONAL_SCF_GRP_4:
case LBR_CHUNK_TONAL_SCF_GRP_5:
VAR_4 = LBR_CHUNK_TONAL_SCF_GRP_5 - VAR_10; VAR_3.tonal_grp[VAR_4].id   = VAR_4; VAR_3.tonal_grp[VAR_4].len  = VAR_11; VAR_3.tonal_grp[VAR_4].VAR_1 = gb.buffer; break; case LBR_CHUNK_RES_GRID_LR:
case LBR_CHUNK_RES_GRID_LR + 1:
case LBR_CHUNK_RES_GRID_LR + 2:
VAR_4 = VAR_10 - LBR_CHUNK_RES_GRID_LR; VAR_3.grid1[VAR_4].len  = VAR_11; VAR_3.grid1[VAR_4].VAR_1 = gb.buffer; break; case LBR_CHUNK_RES_GRID_HR:
case LBR_CHUNK_RES_GRID_HR + 1:
case LBR_CHUNK_RES_GRID_HR + 2:
VAR_4 = VAR_10 - LBR_CHUNK_RES_GRID_HR; VAR_3.hr_grid[VAR_4].len  = VAR_11; VAR_3.hr_grid[VAR_4].VAR_1 = gb.buffer; break; case LBR_CHUNK_RES_TS_1:
case LBR_CHUNK_RES_TS_1 + 1:
case LBR_CHUNK_RES_TS_1 + 2:
VAR_4 = VAR_10 - LBR_CHUNK_RES_TS_1; VAR_3.ts1[VAR_4].len  = VAR_11; VAR_3.ts1[VAR_4].VAR_1 = gb.buffer; break; case LBR_CHUNK_RES_TS_2:
case LBR_CHUNK_RES_TS_2 + 1:
case LBR_CHUNK_RES_TS_2 + 2:
VAR_4 = VAR_10 - LBR_CHUNK_RES_TS_2; VAR_3.ts2[VAR_4].len  = VAR_11; VAR_3.ts2[VAR_4].VAR_1 = gb.buffer; break; } bytestream2_skip(&gb, VAR_11); } VAR_8 = parse_lfe_chunk(VAR_0, &VAR_3.lfe); VAR_8 |= parse_tonal_chunk(VAR_0, &VAR_3.tonal); for (VAR_4 = 0; VAR_4 < 5; VAR_4++) VAR_8 |= parse_tonal_group(VAR_0, &VAR_3.tonal_grp[VAR_4]); for (VAR_4 = 0; VAR_4 < (VAR_0->nchannels + 1) / 2; VAR_4++) { int ch1 = VAR_4 * 2; int ch2 = FFMIN(ch1 + 1, VAR_0->nchannels - 1); if (parse_grid_1_chunk (VAR_0, &VAR_3.grid1  [VAR_4], ch1, ch2) < 0 ||
parse_high_res_grid(VAR_0, &VAR_3.hr_grid[VAR_4], ch1, ch2) < 0) { VAR_8 = -1; continue; } if (!VAR_3.grid1[VAR_4].len || !VAR_3.hr_grid[VAR_4].len || !VAR_3.ts1[VAR_4].len)
continue; if (parse_ts1_chunk(VAR_0, &VAR_3.ts1[VAR_4], ch1, ch2) < 0 ||
parse_ts2_chunk(VAR_0, &VAR_3.ts2[VAR_4], ch1, ch2) < 0) { VAR_8 = -1; continue; } } if (VAR_8 < 0 && (VAR_0->avctx->err_recognition & AV_EF_EXPLODE))
return AVERROR_INVALIDDATA; return 0; }