[FFmpeg-devel] [PATCH] dca: export profile information on decode

Anssi Hannula anssi.hannula
Wed Dec 29 06:24:09 CET 2010


---

While waiting for that another opinion, here's another take on the
patch, this time with a more noticiable separation of the HD parser.

Does this one look better?

Instead of only checking the first asset, I simply ignore the HD part
if it contains multiple assets or audio or has non-zero substream
index (what do these latter two even mean?). I did this mainly because
I'm not sure how the bitmasks that reside after num_assets behave when
substream index / num_assets / num_audio changes, and I don't know the
exact meanings of those variables.

 libavcodec/avcodec.h |    8 +++-
 libavcodec/dca.c     |  108 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index c803ec6..8833849 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -32,7 +32,7 @@
 #include "libavutil/cpu.h"
 
 #define LIBAVCODEC_VERSION_MAJOR 52
-#define LIBAVCODEC_VERSION_MINOR 101
+#define LIBAVCODEC_VERSION_MINOR 102
 #define LIBAVCODEC_VERSION_MICRO  0
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
@@ -2238,6 +2238,12 @@ typedef struct AVCodecContext {
 #define FF_PROFILE_AAC_SSR  2
 #define FF_PROFILE_AAC_LTP  3
 
+#define FF_PROFILE_DTS         20
+#define FF_PROFILE_DTS_ES      30
+#define FF_PROFILE_DTS_96_24   40
+#define FF_PROFILE_DTS_HD_HRA  50
+#define FF_PROFILE_DTS_HD_MA   60
+
 #define FF_PROFILE_H264_BASELINE    66
 #define FF_PROFILE_H264_MAIN        77
 #define FF_PROFILE_H264_EXTENDED    88
diff --git a/libavcodec/dca.c b/libavcodec/dca.c
index 70aaa4e..f2f7432 100644
--- a/libavcodec/dca.c
+++ b/libavcodec/dca.c
@@ -293,6 +293,8 @@ typedef struct {
     int xch_present;
     int xch_base_channel;       ///< index of first (only) channel containing XCH data
 
+    int profile;
+
     int debug_flag;             ///< used for suppressing repeated error messages output
     DSPContext dsp;
     FFTContext imdct;
@@ -1271,6 +1273,88 @@ static int dca_convert_bitstream(const uint8_t * src, int src_size, uint8_t * ds
 }
 
 /**
+ * Parse extension substream (HD part)
+ */
+static void dca_parse_exss(DCAContext *s)
+{
+    int blownup;
+    int header_size;
+    int hd_size;
+    int exss_start = get_bits_count(&s->gb) - 32;
+    int exss_end;
+
+    skip_bits(&s->gb, 8); // unknown
+    if (get_bits(&s->gb, 2)) { // substream index
+        av_log_ask_for_sample(s->avctx, "Non-zero DTS-HD substream index.");
+        return;
+    }
+
+    blownup = get_bits(&s->gb, 1);
+    header_size = get_bits(&s->gb, 8 + 4 * blownup) + 1;
+    hd_size = get_bits(&s->gb, 16 + 4 * blownup) + 1;
+
+    if (get_bits(&s->gb, 1)) { // static fields present
+        skip_bits(&s->gb, 2); // reference clock code
+        skip_bits(&s->gb, 3); // frame duration code
+        if (get_bits(&s->gb, 1))
+            skip_bits_long(&s->gb, 36); // timestamp
+        if (get_bits(&s->gb, 3)) { // num_audio + 1
+            av_log_ask_for_sample(s->avctx, "DTS-HD num_audio more than 1.");
+            return;
+        }
+        if (get_bits(&s->gb, 3)) { // num_assets + 1
+            av_log_ask_for_sample(s->avctx, "DTS-HD num_assets more than 1.");
+            return;
+        }
+        /* not parsed further */
+    }
+    /* num_audio and num_assets are 1 when static fields are not present */
+
+    /* skip to the beginning of the payload */
+    skip_bits_long(&s->gb, exss_start + header_size * 8 - get_bits_count(&s->gb));
+
+    exss_end = FFMIN(exss_start + hd_size * 8, s->dca_buffer_size * 8);
+
+    while(exss_end - get_bits_count(&s->gb) >= 32) {
+        uint32_t bits = get_bits_long(&s->gb, 32);
+        switch(bits) {
+        case 0x5a5a5a5a:
+            /* XCh: extended channel */
+            s->profile = FFMAX(s->profile, FF_PROFILE_DTS_ES);
+            break;
+
+        case 0x47004a03:
+            /* XXCh: extended channels */
+            s->profile = FFMAX(s->profile, FF_PROFILE_DTS_ES);
+            break;
+
+        case 0x1d95f262:
+            /* X96: 96/24 */
+            s->profile = FFMAX(s->profile, FF_PROFILE_DTS_96_24);
+            break;
+
+        case 0x655e315e:
+            /* XBR: extended bitrate */
+            s->profile = FFMAX(s->profile, FF_PROFILE_DTS_HD_HRA);
+            /* no XLL expected and we don't actually decode any extensions
+             * yet, skip the rest */
+            skip_bits_long(&s->gb, exss_end - get_bits_count(&s->gb));
+            break;
+
+        case 0x41a29547:
+            /* XLL: lossless */
+            s->profile = FFMAX(s->profile, FF_PROFILE_DTS_HD_MA);
+            /* no other extensions expected and we wouldn't use them yet
+             * anyway, skip the rest */
+            skip_bits_long(&s->gb, exss_end - get_bits_count(&s->gb));
+            break;
+        }
+
+        skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
+    }
+}
+
+/**
  * Main frame decoding function
  * FIXME add arguments
  */
@@ -1287,6 +1371,7 @@ static int dca_decode_frame(AVCodecContext * avctx,
     int16_t *samples = data;
     DCAContext *s = avctx->priv_data;
     int channels;
+    int primary_end;
 
 
     s->xch_present = 0;
@@ -1306,6 +1391,8 @@ static int dca_decode_frame(AVCodecContext * avctx,
     avctx->sample_rate = s->sample_rate;
     avctx->bit_rate = s->bit_rate;
 
+    s->profile = FF_PROFILE_DTS;
+
     for (i = 0; i < (s->sample_blocks / 8); i++) {
         dca_decode_block(s, 0, i);
     }
@@ -1316,7 +1403,9 @@ static int dca_decode_frame(AVCodecContext * avctx,
     /* extensions start at 32-bit boundaries into bitstream */
     skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
 
-    while(get_bits_left(&s->gb) >= 32) {
+    primary_end = FFMIN(s->frame_size, s->dca_buffer_size) * 8;
+
+    while(primary_end - get_bits_count(&s->gb) >= 32) {
         uint32_t bits = get_bits_long(&s->gb, 32);
 
         switch(bits) {
@@ -1334,6 +1423,8 @@ static int dca_decode_frame(AVCodecContext * avctx,
             /* skip length-to-end-of-frame field for the moment */
             skip_bits(&s->gb, 10);
 
+            s->profile = FFMAX(s->profile, FF_PROFILE_DTS_ES);
+
             /* extension amode should == 1, number of channels in extension */
             /* AFAIK XCh is not used for more channels */
             if ((ext_amode = get_bits(&s->gb, 4)) != 1) {
@@ -1352,16 +1443,31 @@ static int dca_decode_frame(AVCodecContext * avctx,
             s->xch_present = 1;
             break;
         }
+        case 0x47004a03:
+            /* XXCh: extended channels */
+            /* usually found either in core or HD part in DTS-HD HRA streams,
+             * but not in DTS-ES which contains XCh extensions instead */
+            s->profile = FFMAX(s->profile, FF_PROFILE_DTS_ES);
+            break;
+
         case 0x1d95f262:
             av_log(avctx, AV_LOG_DEBUG, "Possible X96 extension found at %d bits\n", get_bits_count(&s->gb));
             av_log(avctx, AV_LOG_DEBUG, "FSIZE96 = %d bytes\n", get_bits(&s->gb, 12)+1);
             av_log(avctx, AV_LOG_DEBUG, "REVNO = %d\n", get_bits(&s->gb, 4));
+            s->profile = FFMAX(s->profile, FF_PROFILE_DTS_96_24);
             break;
         }
 
         skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
     }
 
+    /* check for ExSS (HD part) */
+    if (s->dca_buffer_size - s->frame_size > 68
+        && get_bits_long(&s->gb, 32) == DCA_HD_MARKER)
+        dca_parse_exss(s);
+
+    avctx->profile = s->profile;
+
     channels = s->prim_channels + !!s->lfe;
 
     if (s->amode<16) {
-- 
1.7.3




More information about the ffmpeg-devel mailing list