[vlc-devel] [PATCH 2/2] codec: araw: add an option to specify the channel order

Thomas Guillem thomas at gllm.fr
Tue Jan 16 16:27:11 CET 2018


The default channel order is still WG4, but this can be changed to WAVE for the
encoder or the decoder. This can be used by sout commands to use the WAVE
channel order. Example: 'transcode{acodec=s16l,aenc=araw{order=1}}'.
---
 modules/codec/araw.c | 136 +++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 116 insertions(+), 20 deletions(-)

diff --git a/modules/codec/araw.c b/modules/codec/araw.c
index 0d8145527a..2c380f2d37 100644
--- a/modules/codec/araw.c
+++ b/modules/codec/araw.c
@@ -42,8 +42,20 @@
 static int  DecoderOpen ( vlc_object_t * );
 static void DecoderClose( vlc_object_t * );
 
+#define ARAW_ORDER_TEXT N_("PCM channels order")
+
+#define ARAW_CFG_PREFIX "araw-"
+#define ARAW_ORDER_WG4 0
+#define ARAW_ORDER_WAVE 1
+static const int order_list[] = { ARAW_ORDER_WG4, ARAW_ORDER_WAVE };
+static const char *order_list_text[] = {
+  N_("WG4 (DVD) order"),
+  N_("Wave order"),
+};
+
 #ifdef ENABLE_SOUT
 static int  EncoderOpen ( vlc_object_t * );
+static void  EncoderClose ( vlc_object_t * );
 #endif
 
 vlc_module_begin ()
@@ -53,16 +65,25 @@ vlc_module_begin ()
     set_category( CAT_INPUT )
     set_subcategory( SUBCAT_INPUT_ACODEC )
     set_callbacks( DecoderOpen, DecoderClose )
+    add_integer( ARAW_CFG_PREFIX "order", ARAW_ORDER_WG4,
+                 ARAW_ORDER_TEXT, NULL, true )
+    change_integer_list( order_list, order_list_text )
 
 #ifdef ENABLE_SOUT
     /* audio encoder submodule */
     add_submodule ()
     set_description( N_("Raw audio encoder") )
     set_capability( "encoder", 150 )
-    set_callbacks( EncoderOpen, NULL )
+    set_callbacks( EncoderOpen, EncoderClose )
 #endif
 vlc_module_end ()
 
+#ifdef ENABLE_SOUT
+static const char *const ppsz_enc_options[] = {
+    "order", NULL
+};
+#endif
+
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
@@ -72,6 +93,8 @@ static void Flush( decoder_t * );
 struct decoder_sys_t
 {
     void (*decode) (void *, const uint8_t *, unsigned);
+    uint8_t chans_table[AOUT_CHAN_MAX];
+    uint8_t chans_to_reorder;
     size_t framebits;
     date_t end_date;
 };
@@ -106,6 +129,41 @@ static void F64NDecode( void *, const uint8_t *, unsigned );
 static void F64IDecode( void *, const uint8_t *, unsigned );
 static void DAT12Decode( void *, const uint8_t *, unsigned );
 
+static unsigned
+SetupChanOrder( vlc_object_t *p_this, bool decode,
+                  uint32_t mask, uint8_t *restrict table )
+{
+    switch( var_InheritInteger( p_this, ARAW_CFG_PREFIX "order" ) )
+    {
+        case ARAW_ORDER_WAVE:
+        {
+            static const uint32_t wave_order[] = {
+                AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
+                AOUT_CHAN_CENTER, AOUT_CHAN_LFE,
+                AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_REARCENTER,
+                AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, 0
+            };
+            const uint32_t *chans_in;
+            const uint32_t *chans_out;
+            if( decode )
+            {
+                chans_in = wave_order;
+                chans_out = pi_vlc_chan_order_wg4;
+            }
+            else
+            {
+                chans_in = pi_vlc_chan_order_wg4;
+                chans_out = wave_order;
+            }
+            return aout_CheckChannelReorder( chans_in, chans_out, mask, table );
+        }
+        default:
+        case ARAW_ORDER_WG4:
+            return 0;
+    }
+}
+
+
 /*****************************************************************************
  * DecoderOpen: probe the decoder and return score
  *****************************************************************************/
@@ -285,13 +343,19 @@ static int DecoderOpen( vlc_object_t *p_this )
         else
             p_dec->fmt_out.audio.i_physical_channels =
                                   pi_channels_maps[p_dec->fmt_in.audio.i_channels];
+        p_sys->chans_to_reorder =
+            SetupChanOrder( p_this, false, p_dec->fmt_out.audio.i_physical_channels,
+                            p_sys->chans_table );
     }
     else
     {
         /* Unknown channel map, let the aout/filters decide what to do */
         p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
         p_dec->fmt_out.audio.i_physical_channels = 0;
+        p_sys->chans_to_reorder = 0;
     }
+
+
     aout_FormatPrepare( &p_dec->fmt_out.audio );
 
     p_sys->decode = decode;
@@ -370,6 +434,11 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
         p_block->i_buffer = samples * (p_sys->framebits / 8);
     }
 
+    if( p_sys->chans_to_reorder )
+        aout_ChannelReorder( p_block->p_buffer, p_block->i_buffer,
+                             p_sys->chans_to_reorder, p_sys->chans_table,
+                             p_dec->fmt_out.i_codec );
+
     p_block->i_pts = date_Get( &p_sys->end_date );
     p_block->i_length = date_Increment( &p_sys->end_date, samples )
                       - p_block->i_pts;
@@ -652,6 +721,13 @@ static void DecoderClose( vlc_object_t *p_this )
 }
 
 #ifdef ENABLE_SOUT
+struct encoder_sys_t
+{
+    void (*encode)(void *, const uint8_t *, unsigned);
+    uint8_t chans_table[AOUT_CHAN_MAX];
+    uint8_t chans_to_reorder;
+};
+
 /* NOTE: Output buffers are always aligned since they are allocated by the araw plugin.
  * Contrary to the decoder, the encoder can also assume that input buffers are aligned,
  * since decoded audio blocks must always be aligned. */
@@ -805,14 +881,18 @@ static block_t *Encode( encoder_t *enc, block_t *in )
     out->i_pts        = in->i_pts;
     out->i_length     = in->i_length;
 
-    void (*encode)(void *, const uint8_t *, unsigned) = (void *)enc->p_sys;
-    if( encode != NULL )
-        encode( out->p_buffer, in->p_buffer, in->i_nb_samples
-                                             * enc->fmt_out.audio.i_channels );
+    encoder_sys_t *p_sys = enc->p_sys;
+    if( p_sys->encode != NULL )
+        p_sys->encode( out->p_buffer, in->p_buffer, in->i_nb_samples
+                       * enc->fmt_out.audio.i_channels );
     else {
         assert( out->i_buffer >= in->i_buffer );
         memcpy( out->p_buffer, in->p_buffer, in->i_buffer );
     }
+    if( p_sys->chans_to_reorder )
+        aout_ChannelReorder( out->p_buffer, out->i_buffer,
+                             p_sys->chans_to_reorder, p_sys->chans_table,
+                             enc->fmt_out.i_codec );
     return out;
 }
 
@@ -822,66 +902,76 @@ static block_t *Encode( encoder_t *enc, block_t *in )
 static int EncoderOpen( vlc_object_t *p_this )
 {
     encoder_t *p_enc = (encoder_t *)p_this;
-    void (*encode)(void *, const uint8_t *, unsigned) = NULL;
+
+    config_ChainParse( p_this, ARAW_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
+
+    struct encoder_sys_t *p_sys = malloc(sizeof(struct encoder_sys_t));
+    if( !p_sys )
+        return VLC_ENOMEM;
+
+    p_sys->chans_to_reorder =
+        SetupChanOrder( p_this, false, p_enc->fmt_in.audio.i_physical_channels,
+                        p_sys->chans_table );
+    p_sys->encode = NULL;
 
     switch( p_enc->fmt_out.i_codec )
     {
     case VLC_CODEC_S8:
-        encode = S8Decode;
+        p_sys->encode = S8Decode;
         /* fall through */
     case VLC_CODEC_U8:
         p_enc->fmt_in.i_codec = VLC_CODEC_U8;
         p_enc->fmt_out.audio.i_bitspersample = 8;
         break;
     case VLC_CODEC_U16I:
-        encode = U16IEncode;
+        p_sys->encode = U16IEncode;
         p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
         p_enc->fmt_out.audio.i_bitspersample = 16;
         break;
     case VLC_CODEC_U16N:
-        encode = U16NEncode;
+        p_sys->encode = U16NEncode;
         p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
         p_enc->fmt_out.audio.i_bitspersample = 16;
         break;
     case VLC_CODEC_S16I:
-        encode = S16IDecode;
+        p_sys->encode = S16IDecode;
         /* fall through */
     case VLC_CODEC_S16N:
         p_enc->fmt_in.i_codec = VLC_CODEC_S16N;
         p_enc->fmt_out.audio.i_bitspersample = 16;
         break;
     case VLC_CODEC_U24B:
-        encode = U24BEncode;
+        p_sys->encode = U24BEncode;
         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
         p_enc->fmt_out.audio.i_bitspersample = 24;
         break;
     case VLC_CODEC_U24L:
-        encode = U24LEncode;
+        p_sys->encode = U24LEncode;
         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
         p_enc->fmt_out.audio.i_bitspersample = 24;
         break;
     case VLC_CODEC_S24B:
-        encode = S24BEncode;
+        p_sys->encode = S24BEncode;
         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
         p_enc->fmt_out.audio.i_bitspersample = 24;
         break;
     case VLC_CODEC_S24L:
-        encode = S24LEncode;
+        p_sys->encode = S24LEncode;
         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
         p_enc->fmt_out.audio.i_bitspersample = 24;
         break;
     case VLC_CODEC_U32I:
-        encode = U32IEncode;
+        p_sys->encode = U32IEncode;
         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
         p_enc->fmt_out.audio.i_bitspersample = 32;
         break;
     case VLC_CODEC_U32N:
-        encode = U32NEncode;
+        p_sys->encode = U32NEncode;
         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
         p_enc->fmt_out.audio.i_bitspersample = 32;
         break;
     case VLC_CODEC_S32I:
-        encode = S32IEncode;
+        p_sys->encode = S32IEncode;
         /* fall through */
     case VLC_CODEC_S32N:
         p_enc->fmt_in.i_codec = VLC_CODEC_S32N;
@@ -892,7 +982,7 @@ static int EncoderOpen( vlc_object_t *p_this )
 #else
     case VLC_CODEC_F32B:
 #endif
-        encode = F32IEncode;
+        p_sys->encode = F32IEncode;
         /* fall through */
     case VLC_CODEC_FL32:
         p_enc->fmt_in.i_codec = VLC_CODEC_FL32;
@@ -903,7 +993,7 @@ static int EncoderOpen( vlc_object_t *p_this )
 #else
     case VLC_CODEC_F64B:
 #endif
-        encode = F64IEncode;
+        p_sys->encode = F64IEncode;
         /* fall through */
     case VLC_CODEC_FL64:
         p_enc->fmt_in.i_codec = VLC_CODEC_FL64;
@@ -913,7 +1003,7 @@ static int EncoderOpen( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
-    p_enc->p_sys = (void *)encode;
+    p_enc->p_sys = p_sys;
     p_enc->pf_encode_audio = Encode;
     p_enc->fmt_out.audio.i_bytes_per_frame =
         (p_enc->fmt_out.audio.i_bitspersample / 8) *
@@ -929,4 +1019,10 @@ static int EncoderOpen( vlc_object_t *p_this )
 
     return VLC_SUCCESS;
 }
+
+static void  EncoderClose ( vlc_object_t *p_this )
+{
+    encoder_t *p_enc = (encoder_t *)p_this;
+    free( p_enc->p_sys );
+}
 #endif /* ENABLE_SOUT */
-- 
2.11.0



More information about the vlc-devel mailing list