Index: modules/audio_output/portaudio.c =================================================================== --- modules/audio_output/portaudio.c (revision 9254) +++ modules/audio_output/portaudio.c (working copy) @@ -40,6 +40,28 @@ # define PORTAUDIO_IS_SERIOUSLY_BROKEN 1 #endif +#ifndef SPEAKER_FRONT_LEFT +# define SPEAKER_FRONT_LEFT 0x1 +# define SPEAKER_FRONT_RIGHT 0x2 +# define SPEAKER_FRONT_CENTER 0x4 +# define SPEAKER_LOW_FREQUENCY 0x8 +# define SPEAKER_BACK_LEFT 0x10 +# define SPEAKER_BACK_RIGHT 0x20 +# define SPEAKER_FRONT_LEFT_OF_CENTER 0x40 +# define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80 +# define SPEAKER_BACK_CENTER 0x100 +# define SPEAKER_SIDE_LEFT 0x200 +# define SPEAKER_SIDE_RIGHT 0x400 +# define SPEAKER_TOP_CENTER 0x800 +# define SPEAKER_TOP_FRONT_LEFT 0x1000 +# define SPEAKER_TOP_FRONT_CENTER 0x2000 +# define SPEAKER_TOP_FRONT_RIGHT 0x4000 +# define SPEAKER_TOP_BACK_LEFT 0x8000 +# define SPEAKER_TOP_BACK_CENTER 0x10000 +# define SPEAKER_TOP_BACK_RIGHT 0x20000 +# define SPEAKER_RESERVED 0x80000000 +#endif + /***************************************************************************** * aout_sys_t: portaudio audio output method descriptor *****************************************************************************/ @@ -66,8 +88,30 @@ int i_sample_size; PaDeviceIndex i_device_id; const PaDeviceInfo *deviceInfo; + + vlc_bool_t b_chan_reorder; /* do we need channel reordering */ + int pi_chan_table[AOUT_CHAN_MAX]; + uint32_t i_channel_mask; + uint32_t i_bits_per_sample; + uint32_t i_channels; }; +static const uint32_t pi_channels_src[] = + { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, + AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, + AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, + AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 }; +static const uint32_t pi_channels_in[] = + { SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT, + SPEAKER_SIDE_LEFT, SPEAKER_SIDE_RIGHT, + SPEAKER_BACK_LEFT, SPEAKER_BACK_RIGHT, + SPEAKER_FRONT_CENTER, SPEAKER_LOW_FREQUENCY, 0 }; +static const uint32_t pi_channels_out[] = + { SPEAKER_FRONT_LEFT, SPEAKER_FRONT_RIGHT, + SPEAKER_FRONT_CENTER, SPEAKER_LOW_FREQUENCY, + SPEAKER_BACK_LEFT, SPEAKER_BACK_RIGHT, + SPEAKER_SIDE_LEFT, SPEAKER_SIDE_RIGHT, 0 }; + #ifdef PORTAUDIO_IS_SERIOUSLY_BROKEN static vlc_bool_t b_init = 0; static pa_thread_t *pa_thread; @@ -118,6 +162,13 @@ if ( p_buffer != NULL ) { + if( p_sys->b_chan_reorder ) + { + /* Do the channel reordering here */ + aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_nb_bytes, + p_sys->i_channels, p_sys->pi_chan_table, + p_sys->i_bits_per_sample ); + } p_aout->p_vlc->pf_memcpy( outputBuffer, p_buffer->p_buffer, framesPerBuffer * p_sys->i_sample_size ); /* aout_BufferFree may be dangereous here, but then so is @@ -436,7 +487,8 @@ const PaHostErrorInfo* paLastHostErrorInfo = Pa_GetLastHostErrorInfo(); PaStreamParameters paStreamParameters; vlc_value_t val; - int i_channels, i_err; + int i_channels, i_err, i; + uint32_t i_physical_channels, i_channel_mask; if( var_Get( p_aout, "audio-device", &val ) < 0 ) { @@ -481,6 +533,28 @@ aout_FormatPrepare( &p_aout->output.output ); aout_VolumeSoftInit( p_aout ); + /* Check for channel reordering */ + i_physical_channels = p_aout->output.output.i_physical_channels; + i_channel_mask = 0; + for( i = 0; i < sizeof(pi_channels_src)/sizeof(uint32_t); i++ ) + { + if( i_physical_channels & pi_channels_src[i] ) + i_channel_mask |= pi_channels_in[i]; + } + p_aout->output.p_sys->i_channel_mask = i_channel_mask; + p_aout->output.p_sys->i_bits_per_sample = 32; /* forced to paFloat32 */ + p_aout->output.p_sys->i_channels = i_channels; + + p_aout->output.p_sys->b_chan_reorder = + aout_CheckChannelReorder( pi_channels_in, pi_channels_out, + i_channel_mask, i_channels, + p_aout->output.p_sys->pi_chan_table ); + + if( p_aout->output.p_sys->b_chan_reorder ) + { + msg_Dbg( p_aout, "channel reordering needed" ); + } + paStreamParameters.device = p_sys->i_device_id; paStreamParameters.channelCount = i_channels; paStreamParameters.sampleFormat = paFloat32;