avcodec/dca_parser: set duration for core-less streams

Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
foo86 2016-05-23 17:58:42 +03:00 committed by James Almer
parent 72a9a7e9cb
commit cb55c5b49e
1 changed files with 65 additions and 3 deletions

View File

@ -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);