mlp: Parse TrueHD decoder channel modifiers and set the AVMatrixEncoding for each...
authorTim Walker <tdskywalker@gmail.com>
Wed, 11 Dec 2013 02:03:32 +0000 (02:03 +0000)
committerTim Walker <tdskywalker@gmail.com>
Sun, 5 Jan 2014 15:41:56 +0000 (16:41 +0100)
libavcodec/mlp.h
libavcodec/mlp_parser.c
libavcodec/mlp_parser.h
libavcodec/mlpdec.c

index d771112..5a4ee5f 100644 (file)
@@ -124,4 +124,14 @@ static inline uint8_t xor_32_to_8(uint32_t value)
     return 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 */
 #endif /* AVCODEC_MLP_H */
index 1a68014..8766bd0 100644 (file)
@@ -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;
 
         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);
 
 
         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);
 
         channel_arrangement            = get_bits(gb, 13);
         mh->channels_thd_stream2       = truehd_channels(channel_arrangement);
index e874426..7530fac 100644 (file)
@@ -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 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")
     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")
index 4339b9d..615abf3 100644 (file)
@@ -60,6 +60,8 @@ typedef struct SubStream {
     uint8_t     ch_assign[MAX_CHANNELS];
     /// The channel layout for this substream
     uint64_t    ch_layout;
     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];
 
     /// 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;
     }
 
         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;
 }
 
     return 0;
 }