diff --git a/libavcodec/dca_parser.c b/libavcodec/dca_parser.c index 0b09ba5000..308df531bc 100644 --- a/libavcodec/dca_parser.c +++ b/libavcodec/dca_parser.c @@ -23,6 +23,8 @@ */ #include "dca.h" +#include "dcadata.h" +#include "dca_exss.h" #include "dca_syncwords.h" #include "get_bits.h" #include "parser.h" @@ -32,6 +34,8 @@ typedef struct DCAParseContext { uint32_t lastmarker; int size; int framesize; + DCAExssParser exss; + unsigned int sr_code; } DCAParseContext; #define IS_CORE_MARKER(state) \ @@ -177,11 +181,12 @@ static av_cold int dca_parse_init(AVCodecParserContext *s) DCAParseContext *pc1 = s->priv_data; pc1->lastmarker = 0; + pc1->sr_code = -1; return 0; } -static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration, - int *sample_rate) +static int dca_parse_params(DCAParseContext *pc1, const uint8_t *buf, + int buf_size, int *duration, int *sample_rate) { GetBitContext gb; uint8_t hdr[12 + AV_INPUT_BUFFER_PADDING_SIZE] = { 0 }; @@ -190,6 +195,63 @@ static int dca_parse_params(const uint8_t *buf, int buf_size, int *duration, if (buf_size < 12) return AVERROR_INVALIDDATA; + if (AV_RB32(buf) == DCA_SYNCWORD_SUBSTREAM) { + DCAExssAsset *asset = &pc1->exss.assets[0]; + + if ((ret = ff_dca_exss_parse(&pc1->exss, buf, buf_size)) < 0) + return ret; + + if (asset->extension_mask & DCA_EXSS_LBR) { + if ((ret = init_get_bits8(&gb, buf + asset->lbr_offset, asset->lbr_size)) < 0) + return ret; + + if (get_bits_long(&gb, 32) != DCA_SYNCWORD_LBR) + return AVERROR_INVALIDDATA; + + switch (get_bits(&gb, 8)) { + case 2: + pc1->sr_code = get_bits(&gb, 8); + case 1: + break; + default: + return AVERROR_INVALIDDATA; + } + + if (pc1->sr_code >= FF_ARRAY_ELEMS(ff_dca_sampling_freqs)) + return AVERROR_INVALIDDATA; + + *sample_rate = ff_dca_sampling_freqs[pc1->sr_code]; + *duration = 1024 << ff_dca_freq_ranges[pc1->sr_code]; + return 0; + } + + if (asset->extension_mask & DCA_EXSS_XLL) { + int nsamples_log2; + + if ((ret = init_get_bits8(&gb, buf + asset->xll_offset, asset->xll_size)) < 0) + return ret; + + if (get_bits_long(&gb, 32) != DCA_SYNCWORD_XLL) + return AVERROR_INVALIDDATA; + + if (get_bits(&gb, 4)) + return AVERROR_INVALIDDATA; + + skip_bits(&gb, 8); + skip_bits_long(&gb, get_bits(&gb, 5) + 1); + skip_bits(&gb, 4); + nsamples_log2 = get_bits(&gb, 4) + get_bits(&gb, 4); + if (nsamples_log2 > 24) + return AVERROR_INVALIDDATA; + + *sample_rate = asset->max_sample_rate; + *duration = (1 + (*sample_rate > 96000)) << nsamples_log2; + return 0; + } + + return AVERROR_INVALIDDATA; + } + if ((ret = avpriv_dca_convert_bitstream(buf, 12, hdr, 12)) < 0) return ret; @@ -230,7 +292,7 @@ static int dca_parse(AVCodecParserContext *s, AVCodecContext *avctx, } /* read the duration and sample rate from the frame header */ - if (!dca_parse_params(buf, buf_size, &duration, &sample_rate)) { + if (!dca_parse_params(pc1, buf, buf_size, &duration, &sample_rate)) { if (!avctx->sample_rate) avctx->sample_rate = sample_rate; s->duration = av_rescale(duration, avctx->sample_rate, sample_rate);