aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorfoo86 <foobaz86@gmail.com>2016-05-23 17:58:42 +0300
committerJames Almer <jamrial@gmail.com>2016-05-25 11:23:45 -0300
commitcb55c5b49e6d21709d0ea1bf93cc30a577b1de35 (patch)
treedf3a6be0e452966800781dc30c2c2378abd94448
parent72a9a7e9cbc26771b14b880dd45d29a2064bf8ee (diff)
downloadffmpeg-cb55c5b49e6d21709d0ea1bf93cc30a577b1de35.tar.gz
avcodec/dca_parser: set duration for core-less streams
Signed-off-by: James Almer <jamrial@gmail.com>
-rw-r--r--libavcodec/dca_parser.c68
1 files changed, 65 insertions, 3 deletions
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);