From 4b7f1a7ced0e98f2cc698d896f7ebab8d30eaa09 Mon Sep 17 00:00:00 2001 From: Tim Walker Date: Wed, 11 Dec 2013 02:03:32 +0000 Subject: mlp: Parse TrueHD decoder channel modifiers and set the AVMatrixEncoding for each substream. --- libavcodec/mlp.h | 10 ++++++++++ libavcodec/mlp_parser.c | 7 +++++-- libavcodec/mlp_parser.h | 4 ++++ libavcodec/mlpdec.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/libavcodec/mlp.h b/libavcodec/mlp.h index d7711126b8..5a4ee5fc42 100644 --- a/libavcodec/mlp.h +++ b/libavcodec/mlp.h @@ -124,4 +124,14 @@ static inline uint8_t xor_32_to_8(uint32_t value) return value; } +typedef enum THDChannelModifier { + THD_CH_MODIFIER_NOTINDICATED = 0x0, + THD_CH_MODIFIER_STEREO = 0x0, // Stereo (not Dolby Surround) + THD_CH_MODIFIER_LTRT = 0x1, // Dolby Surround + THD_CH_MODIFIER_LBINRBIN = 0x2, // Dolby Headphone + THD_CH_MODIFIER_MONO = 0x3, // Mono or Dual Mono + THD_CH_MODIFIER_NOTSURROUNDEX = 0x1, // Not Dolby Digital EX + THD_CH_MODIFIER_SURROUNDEX = 0x2, // Dolby Digital EX +} THDChannelModifier; + #endif /* AVCODEC_MLP_H */ diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index 1a68014b32..8766bd0c1f 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -169,13 +169,16 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) mh->group1_samplerate = mlp_samplerate(ratebits); mh->group2_samplerate = 0; - skip_bits(gb, 8); + skip_bits(gb, 4); + + mh->channel_modifier_thd_stream0 = get_bits(gb, 2); + mh->channel_modifier_thd_stream1 = get_bits(gb, 2); channel_arrangement = get_bits(gb, 5); mh->channels_thd_stream1 = truehd_channels(channel_arrangement); mh->channel_layout_thd_stream1 = truehd_layout(channel_arrangement); - skip_bits(gb, 2); + mh->channel_modifier_thd_stream2 = get_bits(gb, 2); channel_arrangement = get_bits(gb, 13); mh->channels_thd_stream2 = truehd_channels(channel_arrangement); diff --git a/libavcodec/mlp_parser.h b/libavcodec/mlp_parser.h index e8744266e3..7530facebf 100644 --- a/libavcodec/mlp_parser.h +++ b/libavcodec/mlp_parser.h @@ -39,6 +39,10 @@ typedef struct MLPHeaderInfo int group1_samplerate; ///< Sample rate of first substream int group2_samplerate; ///< Sample rate of second substream (MLP only) + int channel_modifier_thd_stream0; ///< Channel modifier for substream 0 of TrueHD sreams ("2-channel presentation") + int channel_modifier_thd_stream1; ///< Channel modifier for substream 1 of TrueHD sreams ("6-channel presentation") + int channel_modifier_thd_stream2; ///< Channel modifier for substream 2 of TrueHD sreams ("8-channel presentation") + int channels_mlp; ///< Channel count for MLP streams int channels_thd_stream1; ///< Channel count for substream 1 of TrueHD streams ("6-channel presentation") int channels_thd_stream2; ///< Channel count for substream 2 of TrueHD streams ("8-channel presentation") diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 4339b9dbd5..615abf3cb3 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -60,6 +60,8 @@ typedef struct SubStream { uint8_t ch_assign[MAX_CHANNELS]; /// The channel layout for this substream uint64_t ch_layout; + /// The matrix encoding mode for this substream + enum AVMatrixEncoding matrix_encoding; /// Channel coding parameters for channels in the substream ChannelParams channel_params[MAX_CHANNELS]; @@ -374,6 +376,46 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) m->substream[substr].ch_layout = mh.channel_layout_thd_stream1; } + /* Parse the TrueHD decoder channel modifiers and set each substream's + * AVMatrixEncoding accordingly. + * + * The meaning of the modifiers depends on the channel layout: + * + * - THD_CH_MODIFIER_LTRT, THD_CH_MODIFIER_LBINRBIN only apply to 2-channel + * + * - THD_CH_MODIFIER_MONO applies to 1-channel or 2-channel (dual mono) + * + * - THD_CH_MODIFIER_SURROUNDEX, THD_CH_MODIFIER_NOTSURROUNDEX only apply to + * layouts with an Ls/Rs channel pair + */ + for (substr = 0; substr < MAX_SUBSTREAMS; substr++) + m->substream[substr].matrix_encoding = AV_MATRIX_ENCODING_NONE; + if (m->avctx->codec_id == AV_CODEC_ID_TRUEHD) { + if (mh.num_substreams > 2 && + mh.channel_layout_thd_stream2 & AV_CH_SIDE_LEFT && + mh.channel_layout_thd_stream2 & AV_CH_SIDE_RIGHT && + mh.channel_modifier_thd_stream2 == THD_CH_MODIFIER_SURROUNDEX) + m->substream[2].matrix_encoding = AV_MATRIX_ENCODING_DOLBYEX; + + if (mh.num_substreams > 1 && + mh.channel_layout_thd_stream1 & AV_CH_SIDE_LEFT && + mh.channel_layout_thd_stream1 & AV_CH_SIDE_RIGHT && + mh.channel_modifier_thd_stream1 == THD_CH_MODIFIER_SURROUNDEX) + m->substream[1].matrix_encoding = AV_MATRIX_ENCODING_DOLBYEX; + + if (mh.num_substreams > 0) + switch (mh.channel_modifier_thd_stream0) { + case THD_CH_MODIFIER_LTRT: + m->substream[0].matrix_encoding = AV_MATRIX_ENCODING_DOLBY; + break; + case THD_CH_MODIFIER_LBINRBIN: + m->substream[0].matrix_encoding = AV_MATRIX_ENCODING_DOLBYHEADPHONE; + break; + default: + break; + } + } + return 0; } -- cgit v1.2.3