diff --git a/configure.ac.in b/configure.ac.in index e5830c61ab..6f9422680c 100644 --- a/configure.ac.in +++ b/configure.ac.in @@ -1393,7 +1393,7 @@ if test "x${enable_vorbis}" != "xno" then AC_CHECK_HEADERS(vorbis/codec.h, [ PLUGINS="${PLUGINS} vorbis" - LDFLAGS_vorbis="${LDFLAGS_vorbis} -lvorbis" + LDFLAGS_vorbis="${LDFLAGS_vorbis} -lvorbis -logg" ],[]) fi diff --git a/include/vlc_threads.h b/include/vlc_threads.h index 88f89ce1f9..e7e09b3325 100644 --- a/include/vlc_threads.h +++ b/include/vlc_threads.h @@ -3,7 +3,7 @@ * This header provides portable declarations for mutexes & conditions ***************************************************************************** * Copyright (C) 1999, 2002 VideoLAN - * $Id: vlc_threads.h,v 1.15 2002/10/20 12:23:47 massiot Exp $ + * $Id: vlc_threads.h,v 1.16 2002/10/28 22:31:50 gbazin Exp $ * * Authors: Jean-Marc Dressler * Samuel Hocevar @@ -76,8 +76,8 @@ #elif defined(WIN32) # define VLC_THREAD_PRIORITY_LOW 0 -# define VLC_THREAD_PRIORITY_INPUT THREAD_PRIORITY_ABOVE_NORMAL -# define VLC_THREAD_PRIORITY_AUDIO THREAD_PRIORITY_ABOVE_NORMAL +# define VLC_THREAD_PRIORITY_INPUT THREAD_PRIORITY_TIME_CRITICAL +# define VLC_THREAD_PRIORITY_AUDIO THREAD_PRIORITY_HIGHEST # define VLC_THREAD_PRIORITY_VIDEO 0 # define VLC_THREAD_PRIORITY_OUTPUT THREAD_PRIORITY_ABOVE_NORMAL diff --git a/modules/audio_output/directx.c b/modules/audio_output/directx.c index fb3d4262d5..3f4ee3f160 100644 --- a/modules/audio_output/directx.c +++ b/modules/audio_output/directx.c @@ -2,7 +2,7 @@ * directx.c: Windows DirectX audio output method ***************************************************************************** * Copyright (C) 2001 VideoLAN - * $Id: directx.c,v 1.4 2002/10/20 12:23:47 massiot Exp $ + * $Id: directx.c,v 1.5 2002/10/28 22:31:49 gbazin Exp $ * * Authors: Gildas Bazin * @@ -48,6 +48,13 @@ #include DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); +/***************************************************************************** + * Useful macros + *****************************************************************************/ +#ifndef WAVE_FORMAT_IEEE_FLOAT +# define WAVE_FORMAT_IEEE_FLOAT 0x0003 +#endif + /***************************************************************************** * notification_thread_t: DirectX event thread *****************************************************************************/ @@ -82,8 +89,6 @@ struct aout_sys_t HINSTANCE hdsound_dll; /* handle of the opened dsound dll */ - vlc_mutex_t buffer_lock; /* audio buffer lock */ - notification_thread_t * p_notif; /* DirectSoundThread id */ }; @@ -139,7 +144,6 @@ static int OpenAudio( vlc_object_t *p_this ) p_aout->output.p_sys->p_dsbuffer = NULL; p_aout->output.p_sys->p_dsnotify = NULL; p_aout->output.p_sys->p_notif = NULL; - vlc_mutex_init( p_aout, &p_aout->output.p_sys->buffer_lock ); p_aout->output.pf_play = Play; aout_VolumeSoftInit( p_aout ); @@ -177,17 +181,19 @@ static int OpenAudio( vlc_object_t *p_this ) p_aout->output.p_sys->p_notif->p_events[1].hEventNotify = CreateEvent( NULL, FALSE, FALSE, NULL ); - vlc_mutex_lock( &p_aout->output.p_sys->buffer_lock ); - /* then create a new secondary buffer */ + p_aout->output.output.i_format = VLC_FOURCC('f','l','3','2'); if( DirectxCreateSecondaryBuffer( p_aout ) ) { - msg_Err( p_aout, "cannot create buffer" ); - vlc_mutex_unlock( &p_aout->output.p_sys->buffer_lock ); - return 1; - } + msg_Err( p_aout, "cannot create WAVE_FORMAT_IEEE_FLOAT buffer" ); - vlc_mutex_unlock( &p_aout->output.p_sys->buffer_lock ); + p_aout->output.output.i_format = VLC_FOURCC('s','1','6','l'); + if( DirectxCreateSecondaryBuffer( p_aout ) ) + { + msg_Err( p_aout, "cannot create WAVE_FORMAT_PCM buffer" ); + return 1; + } + } /* start playing the buffer */ dsresult = IDirectSoundBuffer_Play( p_aout->output.p_sys->p_dsbuffer, @@ -211,7 +217,8 @@ static int OpenAudio( vlc_object_t *p_this ) msg_Dbg( p_aout, "creating DirectSoundThread" ); if( vlc_thread_create( p_aout->output.p_sys->p_notif, "DirectSound Notification Thread", - DirectSoundThread, VLC_THREAD_PRIORITY_OUTPUT, 1 ) ) + DirectSoundThread, + THREAD_PRIORITY_TIME_CRITICAL, 1 ) ) { msg_Err( p_aout, "cannot create DirectSoundThread" ); goto error; @@ -361,23 +368,34 @@ static int DirectxCreateSecondaryBuffer( aout_instance_t *p_aout ) /* First set the buffer format */ memset(&waveformat, 0, sizeof(WAVEFORMATEX)); - waveformat.wFormatTag = WAVE_FORMAT_PCM; + switch( p_aout->output.output.i_format ) + { + case VLC_FOURCC('s','1','6','l'): + waveformat.wFormatTag = WAVE_FORMAT_PCM; + waveformat.wBitsPerSample = 16; + break; + case VLC_FOURCC('f','l','3','2'): + waveformat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + waveformat.wBitsPerSample = sizeof(float) * 8; + break; + } waveformat.nChannels = i_nb_channels; waveformat.nSamplesPerSec = p_aout->output.output.i_rate; - waveformat.wBitsPerSample = 16; waveformat.nBlockAlign = waveformat.wBitsPerSample / 8 * waveformat.nChannels; waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; + aout_FormatPrepare( &p_aout->output.output ); + /* Then fill in the descriptor */ memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */ | DSBCAPS_CTRLPOSITIONNOTIFY /* We need notification */ | DSBCAPS_GLOBALFOCUS; /* Allows background playing */ - dsbdesc.dwBufferBytes = FRAME_SIZE * 2 /* frames*/ * /* buffer size */ - sizeof(s16) * i_nb_channels; + dsbdesc.dwBufferBytes = FRAME_SIZE * 2 /* frames*/ /* buffer size */ + * p_aout->output.output.i_bytes_per_frame; dsbdesc.lpwfxFormat = &waveformat; if( IDirectSound_CreateSoundBuffer( p_aout->output.p_sys->p_dsobject, @@ -390,8 +408,8 @@ static int DirectxCreateSecondaryBuffer( aout_instance_t *p_aout ) } /* backup the size of a frame */ - p_aout->output.p_sys->p_notif->i_buffer_size = FRAME_SIZE * sizeof(s16) - * i_nb_channels; + p_aout->output.p_sys->p_notif->i_buffer_size = FRAME_SIZE * + p_aout->output.output.i_bytes_per_frame; memset(&dsbcaps, 0, sizeof(DSBCAPS)); dsbcaps.dwSize = sizeof(DSBCAPS); @@ -423,7 +441,7 @@ static int DirectxCreateSecondaryBuffer( aout_instance_t *p_aout ) msg_Err( p_aout, "cannot set position Notification" ); goto error; } - p_aout->output.output.i_format = AOUT_FMT_S16_NE; + p_aout->output.i_nb_samples = FRAME_SIZE; return 0; @@ -492,18 +510,14 @@ static void DirectSoundThread( notification_thread_t *p_notif ) void *p_write_position, *p_wrap_around; long l_bytes1, l_bytes2; aout_buffer_t * p_buffer; + long l_play_position; /* wait for the position notification */ i_which_event = WaitForMultipleObjects( 2, notification_events, 0, INFINITE ) - WAIT_OBJECT_0; - vlc_mutex_lock( &p_aout->output.p_sys->buffer_lock ); - if( p_notif->b_die ) - { - vlc_mutex_unlock( &p_aout->output.p_sys->buffer_lock ); break; - } /* Before copying anything, we have to lock the buffer */ dsresult = IDirectSoundBuffer_Lock( @@ -533,13 +547,35 @@ static void DirectSoundThread( notification_thread_t *p_notif ) if( dsresult != DS_OK ) { msg_Warn( p_notif, "cannot lock buffer" ); - vlc_mutex_unlock( &p_aout->output.p_sys->buffer_lock ); continue; } - /* We also take into account the latency instead of just mdate() */ + /* We take into account the current latency */ + if( IDirectSoundBuffer_GetCurrentPosition( + p_aout->output.p_sys->p_dsbuffer, + &l_play_position, NULL ) == DS_OK ) + { + if( l_play_position > (i_which_event * FRAME_SIZE) + && l_play_position < ((i_which_event+1) * FRAME_SIZE) ) + { + l_play_position = FRAME_SIZE - ( l_play_position / + p_aout->output.output.i_bytes_per_frame % + FRAME_SIZE ); + } + else + { + l_play_position = 2 * FRAME_SIZE - ( l_play_position / + p_aout->output.output.i_bytes_per_frame % + FRAME_SIZE ); + } + } + else + { + l_play_position = FRAME_SIZE; + } + p_buffer = aout_OutputNextBuffer( p_aout, - mdate() + 1000000 / p_aout->output.output.i_rate * FRAME_SIZE, + mdate() + 1000000 / p_aout->output.output.i_rate * l_play_position, VLC_FALSE ); /* Now do the actual memcpy into the circular buffer */ @@ -562,8 +598,6 @@ static void DirectSoundThread( notification_thread_t *p_notif ) IDirectSoundBuffer_Unlock( p_aout->output.p_sys->p_dsbuffer, p_write_position, l_bytes1, p_wrap_around, l_bytes2 ); - vlc_mutex_unlock( &p_aout->output.p_sys->buffer_lock ); - } /* free the events */ @@ -571,5 +605,4 @@ static void DirectSoundThread( notification_thread_t *p_notif ) CloseHandle( notification_events[1] ); msg_Dbg( p_notif, "DirectSoundThread exiting" ); - } diff --git a/modules/audio_output/waveout.c b/modules/audio_output/waveout.c index 35f7d74f75..2a86064703 100644 --- a/modules/audio_output/waveout.c +++ b/modules/audio_output/waveout.c @@ -2,7 +2,7 @@ * waveout.c : Windows waveOut plugin for vlc ***************************************************************************** * Copyright (C) 2001 VideoLAN - * $Id: waveout.c,v 1.9 2002/10/20 12:23:47 massiot Exp $ + * $Id: waveout.c,v 1.10 2002/10/28 22:31:49 gbazin Exp $ * * Authors: Gildas Bazin * @@ -37,7 +37,15 @@ #include #include -#define FRAME_SIZE 2048 /* The size is in samples, not in bytes */ +#define FRAME_SIZE 1024 /* The size is in samples, not in bytes */ +#define FRAMES_NUM 4 + +/***************************************************************************** + * Useful macros + *****************************************************************************/ +#ifndef WAVE_FORMAT_IEEE_FLOAT +# define WAVE_FORMAT_IEEE_FLOAT 0x0003 +#endif /***************************************************************************** * Local prototypes @@ -76,7 +84,7 @@ struct aout_sys_t WAVEFORMATEX waveformat; /* audio format */ - WAVEHDR waveheader[2]; + WAVEHDR waveheader[FRAMES_NUM]; int i_buffer_size; @@ -91,8 +99,7 @@ struct aout_sys_t static int Open( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; - aout_buffer_t *p_buffer; - int i_nb_channels; + int i_nb_channels, i; /* Allocate structure */ p_aout->output.p_sys = malloc( sizeof( aout_sys_t ) ); @@ -116,29 +123,28 @@ static int Open( vlc_object_t *p_this ) /* We need to open the device with default values to be sure it is * available */ - if ( OpenWaveOut( p_aout, WAVE_FORMAT_PCM, i_nb_channels, + p_aout->output.output.i_format = VLC_FOURCC('f','l','3','2'); + if ( OpenWaveOut( p_aout, WAVE_FORMAT_IEEE_FLOAT, i_nb_channels, p_aout->output.output.i_rate ) ) { - msg_Err( p_aout, "cannot open waveout audio device with output " - "rate (%i)", - p_aout->output.output.i_rate ); - return VLC_EGENERIC; + msg_Err( p_aout, "Audio device doesn't allow WAVE_FORMAT_IEEE_FLOAT" ); + p_aout->output.output.i_format = VLC_FOURCC('s','1','6','l'); if ( OpenWaveOut( p_aout, WAVE_FORMAT_PCM, i_nb_channels, - 44100 ) ) + p_aout->output.output.i_rate ) ) { - msg_Err( p_aout, "cannot open waveout audio device with output " - "rate (44100)" ); + msg_Err( p_aout, "cannot open waveout audio device" ); return VLC_EGENERIC; } - p_aout->output.output.i_rate = 44100; } waveOutReset( p_aout->output.p_sys->h_waveout ); /* Calculate the frame size in bytes */ - p_aout->output.p_sys->i_buffer_size = FRAME_SIZE * sizeof(s16) - * p_aout->output.p_sys->waveformat.nChannels; + p_aout->output.i_nb_samples = FRAME_SIZE; + aout_FormatPrepare( &p_aout->output.output ); + p_aout->output.p_sys->i_buffer_size = FRAME_SIZE * + p_aout->output.output.i_bytes_per_frame; /* Allocate silence buffer */ p_aout->output.p_sys->p_silence_buffer = calloc( p_aout->output.p_sys->i_buffer_size, 1 ); @@ -148,20 +154,13 @@ static int Open( vlc_object_t *p_this ) return 1; } - p_aout->output.output.i_format = AOUT_FMT_S16_NE; - p_aout->output.i_nb_samples = FRAME_SIZE; - /* We need to kick off the playback in order to have the callback properly * working */ - PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout, - &p_aout->output.p_sys->waveheader[0], NULL ); - - p_buffer = aout_OutputNextBuffer( p_aout, - mdate() + 1000000 / p_aout->output.output.i_rate * FRAME_SIZE, - VLC_FALSE ); - PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout, - &p_aout->output.p_sys->waveheader[1], p_buffer ); - + for( i = 0; i < FRAMES_NUM; i++ ) + { + PlayWaveOut( p_aout, p_aout->output.p_sys->h_waveout, + &p_aout->output.p_sys->waveheader[i], NULL ); + } return 0; } @@ -183,7 +182,16 @@ static void Close( vlc_object_t *p_this ) aout_instance_t *p_aout = (aout_instance_t *)p_this; /* Before calling waveOutClose we must reset the device */ - waveOutReset( p_aout->output.p_sys->h_waveout ); + p_aout->b_die = VLC_TRUE; + //Hmmm, waveOutReset never seems to return... why ??? + //waveOutReset( p_aout->output.p_sys->h_waveout ); + + /* Wait for the waveout buffers to be freed */ + while( !(p_aout->output.p_sys->waveheader[0].dwFlags & WHDR_DONE) || + !(p_aout->output.p_sys->waveheader[1].dwFlags & WHDR_DONE) ) + { + msleep( 1000 ); + } /* Close the device */ if( waveOutClose( p_aout->output.p_sys->h_waveout ) != MMSYSERR_NOERROR ) @@ -209,7 +217,17 @@ static int OpenWaveOut( aout_instance_t *p_aout, int i_format, p_aout->output.p_sys->waveformat.wFormatTag = i_format; p_aout->output.p_sys->waveformat.nChannels = i_channels; p_aout->output.p_sys->waveformat.nSamplesPerSec = i_rate; - p_aout->output.p_sys->waveformat.wBitsPerSample = 16; + + switch( i_format ) + { + case WAVE_FORMAT_PCM: + p_aout->output.p_sys->waveformat.wBitsPerSample = 16; + break; + case WAVE_FORMAT_IEEE_FLOAT: + p_aout->output.p_sys->waveformat.wBitsPerSample = sizeof(float) * 8; + break; + } + p_aout->output.p_sys->waveformat.nBlockAlign = p_aout->output.p_sys->waveformat.wBitsPerSample / 8 * i_channels; p_aout->output.p_sys->waveformat.nAvgBytesPerSec = @@ -290,7 +308,9 @@ static void CALLBACK WaveOutCallback( HWAVEOUT h_waveout, UINT uMsg, if( p_waveheader->dwUser ) aout_BufferFree( (aout_buffer_t *)p_waveheader->dwUser ); - /* Take into account WaveOut latency instead of just mdate() */ + if( p_aout->b_die ) return; + + /* Take into account WaveOut latency ( 1 FRAME ) */ p_buffer = aout_OutputNextBuffer( p_aout, mdate() + 1000000 / p_aout->output.output.i_rate * FRAME_SIZE, VLC_FALSE );