aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Walker <tdskywalker@gmail.com>2013-12-11 02:03:32 +0000
committerTim Walker <tdskywalker@gmail.com>2014-01-05 16:41:56 +0100
commit4b7f1a7ced0e98f2cc698d896f7ebab8d30eaa09 (patch)
tree7973beb19a4ce117be284628eda4e18aa3bb6cd2
parent30d70e79a6b4ac7f4eb66446a9da275161ef6ea7 (diff)
downloadffmpeg-4b7f1a7ced0e98f2cc698d896f7ebab8d30eaa09.tar.gz
mlp: Parse TrueHD decoder channel modifiers and set the AVMatrixEncoding for each substream.
-rw-r--r--libavcodec/mlp.h10
-rw-r--r--libavcodec/mlp_parser.c7
-rw-r--r--libavcodec/mlp_parser.h4
-rw-r--r--libavcodec/mlpdec.c42
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;
}