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

Anssi Hannula anssi.hannula
Mon Dec 27 03:51:06 CET 2010


---
This patch makes the dca decoder provide profile information of the
stream, so that users can easily differentiate between the DTS types.

Couple of things related to this I'm not sure of:
- The values of the profile #defines. In this patch I put them into an
  approximate order of quality, with space in between for future
  profiles. Is this OK, or should I just make them sequential from 0?

- I used FF_PROFILE_DTS. Should FF_PROFILE_DCA be used instead? (we have
  CODEC_ID_DTS but the decoder name is "dca")

And something not directly related to this patch, but future work:
- While I think using the profile value is the best method to handle the
  distinction between DTS and DTS-HD streams, what about DTS Express and
  coreless DTS-HD Master Audio (the latter is not in general use,
  though)? They are both coreless, meaning that they do not work with
  legacy decoders (like ours).
  Some options:
  1. Detect the profile (e.g. FF_PROFILE_DTS_EXPRESS) but fail decode
     with PATCHWELCOME.
  2. Have CODEC_ID_DTS_CORELESS, or CODEC_ID_DTS_EXPRESS. This might be
     problematic with formats that do not differentiate between the
     various DTS variants, though, not sure. Of course we could always
     rely on probing for those (mkv doesn't differentiate, bluray does).

  DTS Express is simply a stream that contains only HD frames that
  contain XSA (Sub Audio) extensions. It is used on e.g. comment tracks.
  We can't decode them currently, but we should have some sort of
  detection for those to allow passthrough or whatever a user might want
  to do with them.
  I've not seen coreless Master Audio (it is only used for professional
  purposes), but I'd guess it would only contain HD frames with XLL
  extensions.
  At the moment, neither is detected as DTS as they don't have the
  regular DTS sync code, only the HD sync code (while regular DTS-HD has
  both).

 libavcodec/avcodec.h |    8 +++++-
 libavcodec/dca.c     |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 1 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 9c111bb..bca1943 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 100
+#define LIBAVCODEC_VERSION_MINOR 101
 #define LIBAVCODEC_VERSION_MICRO  0
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
@@ -2237,6 +2237,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..36b2fa5 100644
--- a/libavcodec/dca.c
+++ b/libavcodec/dca.c
@@ -1287,6 +1287,8 @@ static int dca_decode_frame(AVCodecContext * avctx,
     int16_t *samples = data;
     DCAContext *s = avctx->priv_data;
     int channels;
+    int in_hd = 0;
+    int profile = FF_PROFILE_DTS;
 
 
     s->xch_present = 0;
@@ -1322,6 +1324,8 @@ static int dca_decode_frame(AVCodecContext * avctx,
         switch(bits) {
         case 0x5a5a5a5a: {
             int ext_amode, xch_fsize;
+            if (in_hd)
+                continue;
 
             s->xch_base_channel = s->prim_channels;
 
@@ -1331,6 +1335,8 @@ static int dca_decode_frame(AVCodecContext * avctx,
                (s->frame_size != (get_bits_count(&s->gb) >> 3) - 4 + xch_fsize + 1))
                 continue;
 
+            profile = FFMAX(profile, FF_PROFILE_DTS_ES);
+
             /* skip length-to-end-of-frame field for the moment */
             skip_bits(&s->gb, 10);
 
@@ -1356,12 +1362,69 @@ static int dca_decode_frame(AVCodecContext * avctx,
             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));
+
+            profile = FFMAX(profile, FF_PROFILE_DTS_96_24);
+            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 */
+            profile = FFMAX(profile, FF_PROFILE_DTS_ES);
+            break;
+
+        case 0x655e315e:
+            /* XBR: extended bitrate */
+            if (!in_hd)
+                continue;
+
+            profile = FFMAX(profile, FF_PROFILE_DTS_HD_HRA);
+            break;
+
+        case 0x41a29547:
+            /* XLL: lossless */
+            if (!in_hd)
+                continue;
+
+            profile = FFMAX(profile, FF_PROFILE_DTS_HD_MA);
+            break;
+
+        case DCA_HD_MARKER: {
+            int blownup;
+            int header_size;
+            int hd_size;
+            int start = get_bits_count(&s->gb) - 32;
+            if (in_hd || s->frame_size > (start >> 3))
+                continue;
+
+            skip_bits(&s->gb, 8); // unknown
+            skip_bits(&s->gb, 2); // substream index
+
+            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 (avctx->profile >= FF_PROFILE_DTS_HD_HRA) {
+                /* We've already looked at the HD extension for profile info,
+                 * let's skip it now to avoid checking every byte again. */
+                skip_bits_long(&s->gb, hd_size * 8 - (get_bits_count(&s->gb) - start));
+                profile = avctx->profile;
+            } else {
+                /* Skip the header. Note that this means we can't reliably use any
+                 * audio data inside the HD extension. */
+                skip_bits_long(&s->gb, header_size * 8 - (get_bits_count(&s->gb) - start));
+            }
+
+            in_hd = 1;
             break;
         }
+        }
 
         skip_bits_long(&s->gb, (-get_bits_count(&s->gb)) & 31);
     }
 
+    avctx->profile = profile;
+
     channels = s->prim_channels + !!s->lfe;
 
     if (s->amode<16) {
-- 
1.7.3




More information about the ffmpeg-devel mailing list