[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