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

Thomas Guillem thomas at gllm.fr
Tue Jan 16 17:13:09 CET 2018



On Tue, Jan 16, 2018, at 17:06, Rémi Denis-Courmont wrote:
> Le 16 janvier 2018 17:27:11 GMT+02:00, Thomas Guillem <thomas at gllm.fr> a écrit :
> >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
> >
> >_______________________________________________
> >vlc-devel mailing list
> >To unsubscribe or modify your subscription options:
> >https://mailman.videolan.org/listinfo/vlc-devel
> 
> Supporting multiple channel orders is pretty pointless IMO. It adds a 
> lot of complexity for negligible performance gains.
> 
> We have a lot of pain with RGB masks... I would rather not reproduce 
> that mistake with audio.

This is the only way we found to have multiple channels on chromecast because:

 - Google just removed AAC multiple channels support few months ago with an update (licensing issue ?).
 - Our vorbis encoder is too slow
 - avcodec vorbis encoder is experimental and works only with stereo
 - chromecast devices are too slow decoding Opus 5.1 (make everything slow)
 - Live streaming FLAC 5.1 doesn't work. Don't know if the problem come from us.

> -- 
> Remi Denis-Courmont
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list