diff options
author | Nick Brereton <nick@nbrereton.net> | 2012-06-20 20:52:46 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-06-28 22:26:15 +0200 |
commit | 16f6c16ac04bb61f468719d6469064a32d65424c (patch) | |
tree | 02976652abed1144bc3d77f01cd24988f4a1458f /libavcodec/dca.c | |
parent | 8d9fd58113fa2953269252575bf5f1edce41e550 (diff) | |
download | ffmpeg-16f6c16ac04bb61f468719d6469064a32d65424c.tar.gz |
Parse & decode DTS XXCH frames
Reviewed-by: Benjamin Larsson <benjamin@southpole.se>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/dca.c')
-rw-r--r-- | libavcodec/dca.c | 108 |
1 files changed, 101 insertions, 7 deletions
diff --git a/libavcodec/dca.c b/libavcodec/dca.c index 76b258bf05..3cd161cbe6 100644 --- a/libavcodec/dca.c +++ b/libavcodec/dca.c @@ -376,6 +376,10 @@ typedef struct { int xch_present; ///< XCh extension present and valid int xch_base_channel; ///< index of first (only) channel containing XCH data + /* XXCH extension information */ + int xxch_spk_layout; + int xxch_nbits_spk_mask; + /* ExSS header parser */ int static_fields; ///< static fields present int mix_metadata; ///< mixing metadata present @@ -462,16 +466,44 @@ static inline void get_array(GetBitContext *gb, int *dst, int len, int bits) *dst++ = get_bits(gb, bits); } -static int dca_parse_audio_coding_header(DCAContext *s, int base_channel) +static int dca_parse_audio_coding_header(DCAContext *s, int base_channel, + int xxch) { int i, j; static const float adj_table[4] = { 1.0, 1.1250, 1.2500, 1.4375 }; static const int bitlen[11] = { 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3 }; static const int thr[11] = { 0, 1, 3, 3, 3, 3, 7, 7, 7, 7, 7 }; + int hdr_pos = 0, hdr_size = 0; + int mask[8]; + + /* xxch has arbitrary sized audio coding headers */ + if (xxch) { + hdr_pos = get_bits_count(&s->gb); + hdr_size = get_bits(&s->gb, 7) + 1; + } s->total_channels = get_bits(&s->gb, 3) + 1 + base_channel; s->prim_channels = s->total_channels; + /* obtain speaker layout mask & mixdown coefficients if applicable */ + if (xxch) { + s->xxch_spk_layout |= get_bits(&s->gb, s->xxch_nbits_spk_mask - 6); + if (get_bits1(&s->gb)) { + get_bits1(&s->gb); + skip_bits(&s->gb, 6); + for (i = base_channel; i < s->prim_channels; i++) { + mask[i] = get_bits(&s->gb, s->xxch_nbits_spk_mask); + } + for (j = base_channel; j < s->prim_channels; j++) { + for (i = 0; i < s->xxch_nbits_spk_mask; i++) { + if (mask[j] & (1 << i)) { + int coeff = get_bits(&s->gb, 7); + } + } + } + } + } + if (s->prim_channels > DCA_PRIM_CHANNELS_MAX) s->prim_channels = DCA_PRIM_CHANNELS_MAX; @@ -508,9 +540,16 @@ static int dca_parse_audio_coding_header(DCAContext *s, int base_channel) if (s->quant_index_huffman[i][j] < thr[j]) s->scalefactor_adj[i][j] = adj_table[get_bits(&s->gb, 2)]; - if (s->crc_present) { - /* Audio header CRC check */ - get_bits(&s->gb, 16); + if (!xxch) { + if (s->crc_present) { + /* Audio header CRC check */ + get_bits(&s->gb, 16); + } + } else { + /* Skip to the end of the header, also ignore CRC if present */ + i = get_bits_count(&s->gb); + if (hdr_pos + 8 * hdr_size > i) + skip_bits_long(&s->gb, hdr_pos + 8 * hdr_size - i); } s->current_subframe = 0; @@ -639,7 +678,7 @@ static int dca_parse_frame_header(DCAContext *s) /* Primary audio coding header */ s->subframes = get_bits(&s->gb, 4) + 1; - return dca_parse_audio_coding_header(s, 0); + return dca_parse_audio_coding_header(s, 0, 0); } @@ -1727,6 +1766,58 @@ static int dca_xbr_parse_frame(DCAContext *s) return 0; } +/* parse initial header for XXCH and dump details */ +static int dca_xxch_decode_frame(DCAContext *s) +{ + int hdr_size, chhdr_crc, spkmsk_bits, num_chsets, core_spk, hdr_pos; + int i, chset, base_channel, chstart, fsize[8]; + + /* assume header word has already been parsed */ + hdr_pos = get_bits_count(&s->gb) - 32; + hdr_size = get_bits(&s->gb, 6) + 1; + chhdr_crc = get_bits1(&s->gb); + spkmsk_bits = get_bits(&s->gb, 5) + 1; + num_chsets = get_bits(&s->gb, 2) + 1; + + for (i = 0; i < num_chsets; i++) + fsize[i] = get_bits(&s->gb, 14) + 1; + + core_spk = get_bits(&s->gb, spkmsk_bits); + + s->xxch_spk_layout = core_spk; + s->xxch_nbits_spk_mask = spkmsk_bits; + + /* skip to the end of the header */ + i = get_bits_count(&s->gb); + if (hdr_pos + hdr_size * 8 > i) + skip_bits_long(&s->gb, hdr_pos + hdr_size * 8 - i); + + for (chset = 0; chset < num_chsets; chset++) { + chstart = get_bits_count(&s->gb); + base_channel = s->prim_channels; + + /* XXCH and Core headers differ, see 6.4.2 "XXCH Channel Set Header" vs. + 5.3.2 "Primary Audio Coding Header", DTS Spec 1.3.1 */ + dca_parse_audio_coding_header(s, base_channel, 1); + + /* decode channel data */ + for (i = 0; i < (s->sample_blocks / 8); i++) { + if (dca_decode_block(s, base_channel, i)) { + av_log(s->avctx, AV_LOG_ERROR, + "Error decoding DTS-XXCH extension\n"); + continue; + } + } + + /* skip to end of this section */ + i = get_bits_count(&s->gb); + if (chstart + fsize[chset] * 8 > i) + skip_bits_long(&s->gb, chstart + fsize[chset] * 8 - i); + } + + return 0; +} + /** * Parse extension substream header (HD) */ @@ -1823,6 +1914,8 @@ static void dca_exss_parse_header(DCAContext *s) if(mkr == 0x655e315e) dca_xbr_parse_frame(s); + else + av_log(s->avctx, AV_LOG_DEBUG, "DTS-MA: unknown marker = 0x%08x\n", mkr); } } @@ -1885,7 +1978,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, /* only scan for extensions if ext_descr was unknown or indicated a * supported XCh extension */ - if (s->core_ext_mask < 0 || s->core_ext_mask & DCA_EXT_XCH) { + if (s->core_ext_mask < 0 || s->core_ext_mask & (DCA_EXT_XCH | DCA_EXT_XXCH)) { /* if ext_descr was unknown, clear s->core_ext_mask so that the * extensions scan can fill it up */ @@ -1923,7 +2016,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, } /* much like core primary audio coding header */ - dca_parse_audio_coding_header(s, s->xch_base_channel); + dca_parse_audio_coding_header(s, s->xch_base_channel, 0); for (i = 0; i < (s->sample_blocks / 8); i++) if ((ret = dca_decode_block(s, s->xch_base_channel, i))) { @@ -1939,6 +2032,7 @@ static int dca_decode_frame(AVCodecContext *avctx, void *data, /* usually found either in core or HD part in DTS-HD HRA streams, * but not in DTS-ES which contains XCh extensions instead */ s->core_ext_mask |= DCA_EXT_XXCH; + dca_xxch_decode_frame(s); break; case 0x1d95f262: { |