00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 extern "C"
00028 {
00029 #include <string.h>
00030 #include <stdlib.h>
00031 #include <errno.h>
00032
00033 #include <vlc/vlc.h>
00034 #include <vlc/aout.h>
00035
00036 #include "aout_internal.h"
00037 }
00038
00039 #include <deschutes/libraries/hdmachinex225/PCMAudioPlayer.h>
00040
00041 #define FRAME_SIZE 4096
00042
00043
00044
00045
00046
00047
00048
00049 struct aout_sys_t
00050 {
00051 u32 nAlignment;
00052 u32 nSizeMultiple;
00053 u32 nBuffers;
00054 u32 nBufferSize;
00055 void ** ppBuffers;
00056 u32 nNextBufferIndex;
00057 PCMAudioPlayer * pPlayer;
00058 };
00059
00060
00061
00062
00063 static int Open ( vlc_object_t * );
00064 static void Close ( vlc_object_t * );
00065
00066 static void Play ( aout_instance_t * );
00067 static int Thread ( aout_instance_t * );
00068
00069 static void InterleaveS16( int16_t *, int16_t * );
00070
00071
00072
00073
00074 vlc_module_begin();
00075 set_shortname( "Roku HD1000" );
00076 set_description( N_("Roku HD1000 audio output") );
00077 set_capability( "audio output", 100 );
00078 set_category( CAT_AUDIO );
00079 set_subcategory( SUBCAT_AUDIO_AOUT );
00080 set_callbacks( Open, Close );
00081 vlc_module_end();
00082
00083
00084
00085
00086 static int Open( vlc_object_t * p_this )
00087 {
00088 aout_instance_t * p_aout = (aout_instance_t *)p_this;
00089 struct aout_sys_t * p_sys;
00090 PCMAudioPlayer * pPlayer;
00091 int i_volume;
00092
00093
00094 p_aout->output.p_sys = p_sys =
00095 (aout_sys_t *)malloc( sizeof( aout_sys_t ) );
00096 if( p_aout->output.p_sys == NULL )
00097 {
00098 msg_Err( p_aout, "out of memory" );
00099 return VLC_EGENERIC;
00100 }
00101
00102
00103 p_sys->pPlayer = pPlayer = new PCMAudioPlayer();
00104 if( p_sys->pPlayer == NULL )
00105 {
00106 msg_Err( p_aout, "out of memory" );
00107 free( p_sys );
00108 return VLC_EGENERIC;
00109 }
00110
00111
00112 if( !pPlayer->GetBufferRequirements( p_sys->nAlignment,
00113 p_sys->nSizeMultiple,
00114 p_sys->nBuffers ) )
00115 {
00116 msg_Err( p_aout, "GetBufferRequirements failed" );
00117 delete pPlayer;
00118 free( p_sys );
00119 return VLC_EGENERIC;
00120 }
00121
00122 p_sys->nBuffers = __MIN( p_sys->nBuffers, 4 );
00123
00124 p_sys->ppBuffers = (void **)malloc( p_sys->nBuffers * sizeof( void * ) );
00125 if( p_sys->ppBuffers == NULL )
00126 {
00127 msg_Err( p_aout, "out of memory" );
00128 delete pPlayer;
00129 free( p_sys );
00130 return VLC_EGENERIC;
00131 }
00132
00133
00134 p_sys->nBufferSize = FRAME_SIZE * 4;
00135 if( !pPlayer->Open( p_sys->nBuffers, p_sys->nBufferSize,
00136 p_sys->ppBuffers ) )
00137 {
00138 msg_Err( p_aout, "Open failed" );
00139 delete pPlayer;
00140 free( p_sys->ppBuffers );
00141 free( p_sys );
00142 return VLC_EGENERIC;
00143 }
00144
00145 p_sys->nNextBufferIndex = 0;
00146
00147 if( !pPlayer->SetSampleRate( p_aout->output.output.i_rate ) )
00148 {
00149 p_aout->output.output.i_rate = 44100;
00150 if( !pPlayer->SetSampleRate( p_aout->output.output.i_rate ) )
00151 {
00152 msg_Err( p_aout, "SetSampleRate failed" );
00153 pPlayer->Close();
00154 delete pPlayer;
00155 free( p_sys->ppBuffers );
00156 free( p_sys );
00157 return VLC_EGENERIC;
00158 }
00159 }
00160
00161 p_aout->output.output.i_format = AOUT_FMT_S16_NE;
00162 p_aout->output.i_nb_samples = FRAME_SIZE;
00163 p_aout->output.output.i_physical_channels
00164 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
00165 p_aout->output.pf_play = Play;
00166 aout_VolumeSoftInit( p_aout );
00167
00168 i_volume = config_GetInt( p_aout->p_vlc, "volume" );
00169 pPlayer->SetVolume( (u32)__MIN( i_volume * 64, 0xFFFF ) );
00170
00171
00172 if( vlc_thread_create( p_aout, "aout", Thread,
00173 VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
00174 {
00175 msg_Err( p_aout, "cannot create OSS thread (%s)", strerror(errno) );
00176 pPlayer->Close();
00177 delete pPlayer;
00178 free( p_sys->ppBuffers );
00179 free( p_sys );
00180 return VLC_ETHREAD;
00181 }
00182
00183 return VLC_SUCCESS;
00184 }
00185
00186
00187
00188
00189 static void Close( vlc_object_t * p_this )
00190 {
00191 u32 i;
00192 aout_instance_t * p_aout = (aout_instance_t *)p_this;
00193 struct aout_sys_t * p_sys = p_aout->output.p_sys;
00194
00195 p_aout->b_die = VLC_TRUE;
00196 vlc_thread_join( p_aout );
00197 p_aout->b_die = VLC_FALSE;
00198
00199 do
00200 {
00201 i = p_sys->pPlayer->WaitForBuffer();
00202 } while( i != 0 && i != p_sys->nBuffers );
00203
00204 p_sys->pPlayer->Close();
00205 delete p_sys->pPlayer;
00206
00207 free( p_sys->ppBuffers );
00208 free( p_sys );
00209 }
00210
00211
00212
00213
00214 static void Play( aout_instance_t * p_aout )
00215 {
00216 }
00217
00218
00219
00220
00221 static int Thread( aout_instance_t * p_aout )
00222 {
00223 aout_buffer_t * p_buffer;
00224 struct aout_sys_t * p_sys = p_aout->output.p_sys;
00225 PCMAudioPlayer * pPlayer = p_sys->pPlayer;
00226
00227 while( !p_aout->b_die )
00228 {
00229 pPlayer->WaitForBuffer();
00230
00231 vlc_mutex_lock( &p_aout->output_fifo_lock );
00232 p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
00233 vlc_mutex_unlock( &p_aout->output_fifo_lock );
00234
00235 #define i p_sys->nNextBufferIndex
00236 if( p_buffer == NULL )
00237 {
00238 p_aout->p_vlc->pf_memset( p_sys->ppBuffers[ i ], 0,
00239 p_sys->nBufferSize );
00240 }
00241 else
00242 {
00243 InterleaveS16( (int16_t *)p_buffer->p_buffer,
00244 (int16_t *)p_sys->ppBuffers[ i ] );
00245 aout_BufferFree( p_buffer );
00246 }
00247
00248 if( !pPlayer->QueueBuffer( (s16 *)p_sys->ppBuffers[ i ],
00249 p_sys->nBufferSize / 2 ) )
00250 {
00251 msg_Err( p_aout, "QueueBuffer failed" );
00252 }
00253
00254 i = (i + 1) % p_sys->nBuffers;
00255 #undef i
00256 }
00257
00258 return VLC_SUCCESS;
00259 }
00260
00261
00262
00263
00264 static void InterleaveS16( int16_t * p_in, int16_t * p_out )
00265 {
00266 for( int i = 0; i < FRAME_SIZE; i++ )
00267 {
00268 p_out[ i * 2 + 0 ] = p_in[ i * 2 + 1 ];
00269 p_out[ i * 2 + 1 ] = p_in[ i * 2 + 0 ];
00270 }
00271 }