[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