Browse Source

avcodec/dca_parser: set duration for core-less streams

Signed-off-by: James Almer <jamrial@gmail.com>
tags/n3.1
foo86 James Almer 9 years ago
parent
commit
cb55c5b49e
1 changed files with 65 additions and 3 deletions
  1. +65
    -3
      libavcodec/dca_parser.c

+ 65
- 3
libavcodec/dca_parser.c 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);


Loading…
Cancel
Save