]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/dca_parser.c
Merge commit '5c8a5765dc5f4e29afb85b95be393c30f45412a8'
[ffmpeg] / libavcodec / dca_parser.c
index e5bea3347cc7cf94088cb0c0afae6f5fe7926150..11ddb8f188237f1c1a07d308d2db79aae4a4ac31 100644 (file)
@@ -23,7 +23,9 @@
  */
 
 #include "dca.h"
+#include "dca_core.h"
 #include "dca_exss.h"
+#include "dca_lbr.h"
 #include "dca_syncwords.h"
 #include "get_bits.h"
 #include "parser.h"
@@ -189,18 +191,19 @@ static av_cold int dca_parse_init(AVCodecParserContext *s)
 }
 
 static int dca_parse_params(DCAParseContext *pc1, const uint8_t *buf,
-                            int buf_size, int *duration, int *sample_rate)
+                            int buf_size, int *duration, int *sample_rate,
+                            int *profile)
 {
+    DCAExssAsset *asset = &pc1->exss.assets[0];
     GetBitContext gb;
-    uint8_t hdr[12 + AV_INPUT_BUFFER_PADDING_SIZE] = { 0 };
-    int ret, sample_blocks;
+    DCACoreFrameHeader h;
+    uint8_t hdr[DCA_CORE_FRAME_HEADER_SIZE + AV_INPUT_BUFFER_PADDING_SIZE] = { 0 };
+    int ret, frame_size;
 
-    if (buf_size < 12)
+    if (buf_size < DCA_CORE_FRAME_HEADER_SIZE)
         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;
 
@@ -212,9 +215,9 @@ static int dca_parse_params(DCAParseContext *pc1, const uint8_t *buf,
                 return AVERROR_INVALIDDATA;
 
             switch (get_bits(&gb, 8)) {
-            case 2:
+            case DCA_LBR_HEADER_DECODER_INIT:
                 pc1->sr_code = get_bits(&gb, 8);
-            case 1:
+            case DCA_LBR_HEADER_SYNC_ONLY:
                 break;
             default:
                 return AVERROR_INVALIDDATA;
@@ -225,6 +228,7 @@ static int dca_parse_params(DCAParseContext *pc1, const uint8_t *buf,
 
             *sample_rate = ff_dca_sampling_freqs[pc1->sr_code];
             *duration = 1024 << ff_dca_freq_ranges[pc1->sr_code];
+            *profile = FF_PROFILE_DTS_EXPRESS;
             return 0;
         }
 
@@ -249,27 +253,52 @@ static int dca_parse_params(DCAParseContext *pc1, const uint8_t *buf,
 
             *sample_rate = asset->max_sample_rate;
             *duration = (1 + (*sample_rate > 96000)) << nsamples_log2;
+            *profile = FF_PROFILE_DTS_HD_MA;
             return 0;
         }
 
         return AVERROR_INVALIDDATA;
     }
 
-    if ((ret = avpriv_dca_convert_bitstream(buf, 12, hdr, 12)) < 0)
+    if ((ret = avpriv_dca_convert_bitstream(buf, DCA_CORE_FRAME_HEADER_SIZE,
+                                            hdr, DCA_CORE_FRAME_HEADER_SIZE)) < 0)
         return ret;
+    if (avpriv_dca_parse_core_frame_header(&h, hdr, ret) < 0)
+        return AVERROR_INVALIDDATA;
 
-    init_get_bits(&gb, hdr, 96);
+    *duration = h.npcmblocks * DCA_PCMBLOCK_SAMPLES;
+    *sample_rate = avpriv_dca_sample_rates[h.sr_code];
+    if (*profile != FF_PROFILE_UNKNOWN)
+        return 0;
+
+    *profile = FF_PROFILE_DTS;
+    if (h.ext_audio_present) {
+        switch (h.ext_audio_type) {
+        case DCA_EXT_AUDIO_XCH:
+        case DCA_EXT_AUDIO_XXCH:
+            *profile = FF_PROFILE_DTS_ES;
+            break;
+        case DCA_EXT_AUDIO_X96:
+            *profile = FF_PROFILE_DTS_96_24;
+            break;
+        }
+    }
 
-    skip_bits_long(&gb, 39);
-    sample_blocks = get_bits(&gb, 7) + 1;
-    if (sample_blocks < 8)
-        return AVERROR_INVALIDDATA;
-    *duration = 256 * (sample_blocks / 8);
+    frame_size = FFALIGN(h.frame_size, 4);
+    if (buf_size - 4 < frame_size)
+        return 0;
 
-    skip_bits(&gb, 20);
-    *sample_rate = avpriv_dca_sample_rates[get_bits(&gb, 4)];
-    if (*sample_rate == 0)
-        return AVERROR_INVALIDDATA;
+    buf      += frame_size;
+    buf_size -= frame_size;
+    if (AV_RB32(buf) != DCA_SYNCWORD_SUBSTREAM)
+        return 0;
+    if (ff_dca_exss_parse(&pc1->exss, buf, buf_size) < 0)
+        return 0;
+
+    if (asset->extension_mask & DCA_EXSS_XLL)
+        *profile = FF_PROFILE_DTS_HD_MA;
+    else if (asset->extension_mask & (DCA_EXSS_XBR | DCA_EXSS_XXCH | DCA_EXSS_X96))
+        *profile = FF_PROFILE_DTS_HD_HRA;
 
     return 0;
 }
@@ -302,7 +331,7 @@ static int dca_parse(AVCodecParserContext *s, AVCodecContext *avctx,
     }
 
     /* read the duration and sample rate from the frame header */
-    if (!dca_parse_params(pc1, buf, buf_size, &duration, &sample_rate)) {
+    if (!dca_parse_params(pc1, buf, buf_size, &duration, &sample_rate, &avctx->profile)) {
         if (!avctx->sample_rate)
             avctx->sample_rate = sample_rate;
         s->duration = av_rescale(duration, avctx->sample_rate, sample_rate);