[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