This requires parsing EXSS in dca_parse(). Adapt ff_dca_exss_parse() signature and disable header CRC check when avctx->priv_data is NULL. --- libavcodec/dca_exss.c | 2 +- libavcodec/dca_exss.h | 2 +- libavcodec/dca_parser.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++--- libavcodec/dcadec.h | 2 ++ 4 files changed, 71 insertions(+), 5 deletions(-)
diff --git a/libavcodec/dca_exss.c b/libavcodec/dca_exss.c index 87b2f42..8d0b63f 100644 --- a/libavcodec/dca_exss.c +++ b/libavcodec/dca_exss.c @@ -375,7 +375,7 @@ static int set_exss_offsets(DCAExssAsset *asset) return 0; } -int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size) +int ff_dca_exss_parse(DCAExssParser *s, const uint8_t *data, int size) { int i, ret, offset, wide_hdr, header_size; diff --git a/libavcodec/dca_exss.h b/libavcodec/dca_exss.h index 323063a..208fae1 100644 --- a/libavcodec/dca_exss.h +++ b/libavcodec/dca_exss.h @@ -87,6 +87,6 @@ typedef struct DCAExssParser { DCAExssAsset assets[1]; ///< Audio asset descriptors } DCAExssParser; -int ff_dca_exss_parse(DCAExssParser *s, uint8_t *data, int size); +int ff_dca_exss_parse(DCAExssParser *s, const uint8_t *data, int size); #endif diff --git a/libavcodec/dca_parser.c b/libavcodec/dca_parser.c index 0b09ba5..02e8322 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; @@ -229,8 +291,10 @@ static int dca_parse(AVCodecParserContext *s, AVCodecContext *avctx, } } + pc1->exss.avctx = 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); diff --git a/libavcodec/dcadec.h b/libavcodec/dcadec.h index 8528332..f52d9f7 100644 --- a/libavcodec/dcadec.h +++ b/libavcodec/dcadec.h @@ -81,6 +81,8 @@ static inline int ff_dca_check_crc(AVCodecContext *avctx, GetBitContext *s, if (!(avctx->err_recognition & (AV_EF_CRCCHECK | AV_EF_CAREFUL))) return 0; + if (!dca) + return 0; if (((p1 | p2) & 7) || p1 < 0 || p2 > s->size_in_bits || p2 - p1 < 16) return -1; if (av_crc(dca->crctab, 0xffff, s->buffer + p1 / 8, (p2 - p1) / 8)) -- 2.8.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel