[FFmpeg-devel] [PATCH 07/10] avcodec/dca_parser: set duration for core-less streams
foo86
foobaz86 at gmail.com
Fri May 13 11:48:29 CEST 2016
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
More information about the ffmpeg-devel
mailing list