[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