Commit 85c3dbc4 authored by Gildas Bazin's avatar Gildas Bazin

* Big rewrite of the DirectX audio plugin. The audio output is now (almost)
    perfect on Win32.
* Fixed a bug in ac3dec_CreateThread() in ac3_decoder_thread.
* On Win32, open() will now open files in binary mode by default.
* A few minor changes to vout_xvideo.c
parent f65e5509
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* aout_directx.c: Windows DirectX audio output method * aout_directx.c: Windows DirectX audio output method
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: aout_directx.c,v 1.8 2001/07/30 18:56:36 gbazin Exp $ * $Id: aout_directx.c,v 1.9 2001/08/05 15:32:46 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -24,12 +24,6 @@ ...@@ -24,12 +24,6 @@
#define MODULE_NAME directx #define MODULE_NAME directx
#include "modules_inner.h" #include "modules_inner.h"
/* The most important thing to do for now is to fix the audio bug we've got
* on startup: the audio will start later than the video (sometimes) and
* is trying to catching up with it.
* At first sight it seems to be a scheduling problem
*/
/***************************************************************************** /*****************************************************************************
* Preamble * Preamble
...@@ -81,12 +75,24 @@ typedef struct aout_sys_s ...@@ -81,12 +75,24 @@ typedef struct aout_sys_s
* takes care of mixing all the * takes care of mixing all the
* secondary buffers into the primary) */ * secondary buffers into the primary) */
LPDIRECTSOUNDNOTIFY p_dsnotify; /* the position notify interface */
HINSTANCE hdsound_dll; /* handle of the opened dsound dll */ HINSTANCE hdsound_dll; /* handle of the opened dsound dll */
long l_buffer_size; /* secondary sound buffer size */ long l_buffer_size; /* secondary sound buffer size */
long l_write_position; /* next write position for the buffer */ long l_write_position; /* next write position for the buffer */
boolean_t b_active; volatile boolean_t b_buffer_underflown; /* buffer underflow detection */
volatile long l_data_played_from_beginning; /* for underflow detection */
volatile long l_data_written_from_beginning; /* for underflow detection */
vlc_mutex_t buffer_lock; /* audio buffer lock */
vlc_thread_t notification_thread_id; /* DirectSoundThread id */
DSBPOSITIONNOTIFY notification_events[2]; /* play notification events */
boolean_t b_notification_thread_die; /* flag to kill the thread */
} aout_sys_t; } aout_sys_t;
...@@ -102,8 +108,10 @@ static void aout_Play ( aout_thread_t *p_aout, ...@@ -102,8 +108,10 @@ static void aout_Play ( aout_thread_t *p_aout,
static void aout_Close ( aout_thread_t *p_aout ); static void aout_Close ( aout_thread_t *p_aout );
/* local functions */ /* local functions */
static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout ); static int DirectxCreateSecondaryBuffer ( aout_thread_t *p_aout );
static int DirectxInitDSound( aout_thread_t *p_aout ); static void DirectxDestroySecondaryBuffer( aout_thread_t *p_aout );
static int DirectxInitDSound ( aout_thread_t *p_aout );
static void DirectSoundThread ( aout_thread_t *p_aout );
/***************************************************************************** /*****************************************************************************
* Functions exported as capabilities. They are declared as static so that * Functions exported as capabilities. They are declared as static so that
...@@ -144,7 +152,6 @@ static int aout_Open( aout_thread_t *p_aout ) ...@@ -144,7 +152,6 @@ static int aout_Open( aout_thread_t *p_aout )
{ {
HRESULT dsresult; HRESULT dsresult;
DSBUFFERDESC dsbuffer_desc; DSBUFFERDESC dsbuffer_desc;
WAVEFORMATEX waveformat;
intf_WarnMsg( 3, "aout: DirectX aout_Open "); intf_WarnMsg( 3, "aout: DirectX aout_Open ");
...@@ -161,6 +168,12 @@ static int aout_Open( aout_thread_t *p_aout ) ...@@ -161,6 +168,12 @@ static int aout_Open( aout_thread_t *p_aout )
p_aout->p_sys->p_dsobject = NULL; p_aout->p_sys->p_dsobject = NULL;
p_aout->p_sys->p_dsbuffer_primary = NULL; p_aout->p_sys->p_dsbuffer_primary = NULL;
p_aout->p_sys->p_dsbuffer = NULL; p_aout->p_sys->p_dsbuffer = NULL;
p_aout->p_sys->p_dsnotify = NULL;
p_aout->p_sys->b_notification_thread_die = 0;
p_aout->p_sys->l_data_written_from_beginning = 0;
p_aout->p_sys->l_data_played_from_beginning = 0;
vlc_mutex_init( &p_aout->p_sys->buffer_lock );
p_aout->psz_device = 0; p_aout->psz_device = 0;
p_aout->i_format = AOUT_FORMAT_DEFAULT; p_aout->i_format = AOUT_FORMAT_DEFAULT;
...@@ -194,42 +207,25 @@ static int aout_Open( aout_thread_t *p_aout ) ...@@ -194,42 +207,25 @@ static int aout_Open( aout_thread_t *p_aout )
return( 1 ); return( 1 );
} }
/* Set Direct Sound primary buffer format because the default value set by
* Windows is usually not the high quality value */
memset(&waveformat, 0, sizeof(WAVEFORMATEX));
waveformat.wFormatTag = WAVE_FORMAT_PCM;
waveformat.nChannels = 2;
waveformat.nSamplesPerSec = 44100;
waveformat.wBitsPerSample = 16;
waveformat.nBlockAlign = waveformat.wBitsPerSample / 8 *
waveformat.nChannels;
waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec *
waveformat.nBlockAlign;
dsresult = IDirectSoundBuffer_SetFormat(p_aout->p_sys->p_dsbuffer_primary, /* Now we need to setup DirectSound play notification */
&waveformat);
if( dsresult != DS_OK )
{
intf_WarnMsg( 3, "aout: can't set primary buffer format");
}
#if 0 /* first we need to create the notification events */
/* ensure the primary buffer is playing. We won't actually hear anything p_aout->p_sys->notification_events[0].hEventNotify =
* until the secondary buffer is playing */ CreateEvent( NULL, FALSE, FALSE, NULL );
dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer_primary, p_aout->p_sys->notification_events[1].hEventNotify =
0, CreateEvent( NULL, FALSE, FALSE, NULL );
0,
DSBPLAY_LOOPING); /* then launch the notification thread */
if( dsresult != DS_OK ) intf_WarnMsg( 3, "aout: aout_Open creating DirectSoundThread" );
if( vlc_thread_create( &p_aout->p_sys->notification_thread_id,
"DirectSound Notification Thread",
(void *) DirectSoundThread, (void *) p_aout) )
{ {
intf_WarnMsg( 3, "aout: can't play direct sound primary buffer "); intf_ErrMsg( "aout error: can't create DirectSoundThread" );
IDirectSound_Release( p_aout->p_sys->p_dsbuffer_primary ); intf_ErrMsg("aout error: %s", strerror(ENOMEM));
IDirectSound_Release( p_aout->p_sys->p_dsobject ); /* Let's go on anyway */
p_aout->p_sys->p_dsobject = NULL;
p_aout->p_sys->p_dsbuffer_primary = NULL;
return( 1 );
} }
#endif
return( 0 ); return( 0 );
} }
...@@ -244,24 +240,64 @@ static int aout_Open( aout_thread_t *p_aout ) ...@@ -244,24 +240,64 @@ static int aout_Open( aout_thread_t *p_aout )
static int aout_SetFormat( aout_thread_t *p_aout ) static int aout_SetFormat( aout_thread_t *p_aout )
{ {
HRESULT dsresult; HRESULT dsresult;
WAVEFORMATEX *p_waveformat;
unsigned long i_size_struct;
intf_WarnMsg( 3, "aout: DirectX aout_SetFormat "); intf_WarnMsg( 3, "aout: DirectX aout_SetFormat ");
/* first release the current secondary buffer */ /* Set the format of Direct Sound primary buffer */
if( p_aout->p_sys->p_dsbuffer != NULL )
/* first we need to know the current format */
dsresult = IDirectSoundBuffer_GetFormat( p_aout->p_sys->p_dsbuffer_primary,
NULL, 0, &i_size_struct );
if( dsresult == DS_OK )
{ {
IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer ); p_waveformat = malloc( i_size_struct );
p_aout->p_sys->p_dsbuffer = NULL; dsresult = IDirectSoundBuffer_GetFormat(
p_aout->p_sys->p_dsbuffer_primary,
p_waveformat, i_size_struct,
NULL );
} }
/* then create a new secondary buffer */ if( dsresult == DS_OK )
dsresult = DirectxCreateSecondaryBuffer( p_aout ); {
/* Here we'll change the format */
p_waveformat->nChannels = 2;
p_waveformat->nSamplesPerSec = (p_aout->l_rate < 44100) ? 44100
: p_aout->l_rate;
p_waveformat->wBitsPerSample = 16;
p_waveformat->nBlockAlign = p_waveformat->wBitsPerSample / 8 *
p_waveformat->nChannels;
p_waveformat->nAvgBytesPerSec = p_waveformat->nSamplesPerSec *
p_waveformat->nBlockAlign;
dsresult = IDirectSoundBuffer_SetFormat(
p_aout->p_sys->p_dsbuffer_primary,
p_waveformat );
}
else intf_WarnMsg( 3, "aout: can't get primary buffer format" );
if( dsresult != DS_OK ) if( dsresult != DS_OK )
intf_WarnMsg( 3, "aout: can't set primary buffer format" );
/* Now we need to take care of Direct Sound secondary buffer */
vlc_mutex_lock( &p_aout->p_sys->buffer_lock );
/* first release the current secondary buffer */
DirectxDestroySecondaryBuffer( p_aout );
/* then create a new secondary buffer */
if( DirectxCreateSecondaryBuffer( p_aout ) )
{ {
intf_WarnMsg( 3, "aout: DirectX aout_SetFormat cannot create buffer"); intf_WarnMsg( 3, "aout: DirectX aout_SetFormat cannot create buffer");
vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
return( 1 ); return( 1 );
} }
vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
p_aout->i_latency = 0; p_aout->i_latency = 0;
return( 0 ); return( 0 );
...@@ -270,48 +306,35 @@ static int aout_SetFormat( aout_thread_t *p_aout ) ...@@ -270,48 +306,35 @@ static int aout_SetFormat( aout_thread_t *p_aout )
/***************************************************************************** /*****************************************************************************
* aout_GetBufInfo: buffer status query * aout_GetBufInfo: buffer status query
***************************************************************************** *****************************************************************************
* returns the number of bytes in the audio buffer compared to the size of * returns the number of bytes in the audio buffer that have not yet been
* l_buffer_limit... * sent to the sound device.
*****************************************************************************/ *****************************************************************************/
static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit ) static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit )
{ {
long l_play_position, l_notused, l_result; long l_play_position, l_notused, l_result;
HRESULT dsresult; HRESULT dsresult;
dsresult = IDirectSoundBuffer_GetCurrentPosition(p_aout->p_sys->p_dsbuffer, if( p_aout->p_sys->b_buffer_underflown )
&l_play_position, &l_notused);
if( dsresult == DSERR_BUFFERLOST )
{
IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
dsresult = IDirectSoundBuffer_GetCurrentPosition(
p_aout->p_sys->p_dsbuffer,
&l_play_position, &l_notused
);
}
if( dsresult != DS_OK )
{ {
intf_WarnMsg(3,"aout: DirectX aout_GetBufInfo cannot get current pos"); intf_WarnMsg( 3, "aout: DirectX aout_GetBufInfo underflow");
return( l_buffer_limit ); return( l_buffer_limit );
} }
#if 0 dsresult = IDirectSoundBuffer_GetCurrentPosition(p_aout->p_sys->p_dsbuffer,
/* temporary hack. When you start playing a new file, the play position &l_play_position, &l_notused);
* doesn't start changing immediatly, even though sound is already if( dsresult != DS_OK )
* playing from the sound card */
if( l_play_position == 0 )
{ {
intf_WarnMsg( 5, "aout: DirectX aout_GetBufInfo: %li", l_buffer_limit); intf_WarnMsg(3,"aout: DirectX aout_GetBufInfo cannot get current pos");
return( l_buffer_limit ); return( l_buffer_limit );
} }
#endif
l_result = (p_aout->p_sys->l_write_position >= l_play_position) ? l_result = (p_aout->p_sys->l_write_position >= l_play_position) ?
(p_aout->p_sys->l_write_position - l_play_position) /2 (p_aout->p_sys->l_write_position - l_play_position)
: (p_aout->p_sys->l_buffer_size - l_play_position : (p_aout->p_sys->l_buffer_size - l_play_position
+ p_aout->p_sys->l_write_position) /2 ; + p_aout->p_sys->l_write_position);
#if 0 #if 0
intf_WarnMsg( 5, "aout: DirectX aout_GetBufInfo: %li", l_result); intf_WarnMsg( 3, "aout: DirectX aout_GetBufInfo: %li", l_result);
#endif #endif
return l_result; return l_result;
} }
...@@ -320,58 +343,40 @@ static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit ) ...@@ -320,58 +343,40 @@ static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit )
* aout_Play: play a sound buffer * aout_Play: play a sound buffer
***************************************************************************** *****************************************************************************
* This function writes a buffer of i_length bytes * This function writes a buffer of i_length bytes
* Don't forget that DirectSound buffers are circular buffers.
*****************************************************************************/ *****************************************************************************/
static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size ) static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
{ {
VOID *p_write_position, *p_start_buffer; VOID *p_write_position, *p_start_buffer;
long l_bytes1, l_bytes2; long l_bytes1, l_bytes2, l_play_position;
long l_play_position, l_notused, l_buffer_free_length;
HRESULT dsresult; HRESULT dsresult;
/* We want to copy data to the circular sound buffer, so we first need to /* protect buffer access (because of DirectSoundThread) */
* find out were in the buffer we can write our data */ vlc_mutex_lock( &p_aout->p_sys->buffer_lock );
dsresult = IDirectSoundBuffer_GetCurrentPosition(p_aout->p_sys->p_dsbuffer,
&l_play_position, if( p_aout->p_sys->b_buffer_underflown )
&l_notused);
if( dsresult == DSERR_BUFFERLOST )
{ {
IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer ); /* reset the position to the beginning of the buffer */
dsresult = IDirectSoundBuffer_SetCurrentPosition(
p_aout->p_sys->p_dsbuffer, 1024 );
/* there has been an underflow so we need to play the new sample
* as soon as possible. This is why we query the play position */
dsresult = IDirectSoundBuffer_GetCurrentPosition( dsresult = IDirectSoundBuffer_GetCurrentPosition(
p_aout->p_sys->p_dsbuffer, p_aout->p_sys->p_dsbuffer,
&l_play_position, &l_notused &l_play_position,
); &p_aout->p_sys->l_write_position );
}
if( dsresult != DS_OK ) if( dsresult != DS_OK )
{ {
intf_WarnMsg( 3, "aout: DirectX aout_Play can'get buffer position"); intf_WarnMsg( 3, "aout: aout_Play can'get buffer position");
p_aout->p_sys->l_write_position = 0;
} }
#if 1 /* reinitialise the underflow detection counters */
/* check that we are not overflowing the circular buffer (everything should p_aout->p_sys->l_data_written_from_beginning = 0;
* be alright but just in case) */ p_aout->p_sys->l_data_played_from_beginning =
l_buffer_free_length = l_play_position - p_aout->p_sys->l_write_position; -(p_aout->p_sys->l_write_position % (p_aout->p_sys->l_buffer_size/2));
if( l_buffer_free_length <= 0 ) p_aout->p_sys->b_buffer_underflown = 0;
l_buffer_free_length += p_aout->p_sys->l_buffer_size;
if( i_size > l_buffer_free_length )
{
intf_WarnMsg( 3, "aout: DirectX aout_Play buffer overflow: size %i, free %i !!!", i_size, l_buffer_free_length);
intf_WarnMsg( 3, "aout: DirectX aout_Play buffer overflow: writepos %i, readpos %i !!!", p_aout->p_sys->l_write_position, l_play_position);
/*i_size = l_buffer_free_length;*/
/* Update the write pointer */
p_aout->p_sys->l_write_position = l_notused;
}
else
{
#if 0
intf_WarnMsg( 4, "aout: DirectX aout_Play buffer: size %i, free %i !!!"
, i_size, l_buffer_free_length);
intf_WarnMsg( 4, "aout: DirectX aout_Play buffer: writepos %i, readpos %i !!!", p_aout->p_sys->l_write_position, l_play_position);
#endif
} }
#endif
/* Before copying anything, we have to lock the buffer */ /* Before copying anything, we have to lock the buffer */
dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer, dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
...@@ -398,10 +403,11 @@ static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size ) ...@@ -398,10 +403,11 @@ static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
if( dsresult != DS_OK ) if( dsresult != DS_OK )
{ {
intf_WarnMsg( 3, "aout: DirectX aout_Play can't lock buffer"); intf_WarnMsg( 3, "aout: DirectX aout_Play can't lock buffer");
vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
return; return;
} }
/* Now do the actual memcopy (two memcpy because the buffer is circular) */ /* Now do the actual memcpy (two memcpy because the buffer is circular) */
memcpy( p_write_position, buffer, l_bytes1 ); memcpy( p_write_position, buffer, l_bytes1 );
if( p_start_buffer != NULL ) if( p_start_buffer != NULL )
{ {
...@@ -415,6 +421,9 @@ static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size ) ...@@ -415,6 +421,9 @@ static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
/* Update the write position index of the buffer*/ /* Update the write position index of the buffer*/
p_aout->p_sys->l_write_position += i_size; p_aout->p_sys->l_write_position += i_size;
p_aout->p_sys->l_write_position %= p_aout->p_sys->l_buffer_size; p_aout->p_sys->l_write_position %= p_aout->p_sys->l_buffer_size;
p_aout->p_sys->l_data_written_from_beginning += i_size;
vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
/* The play function has no effect if the buffer is already playing */ /* The play function has no effect if the buffer is already playing */
dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer, dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer,
...@@ -445,18 +454,14 @@ static void aout_Close( aout_thread_t *p_aout ) ...@@ -445,18 +454,14 @@ static void aout_Close( aout_thread_t *p_aout )
intf_WarnMsg( 3, "aout: DirectX aout_Close "); intf_WarnMsg( 3, "aout: DirectX aout_Close ");
/* make sure the buffer isn't playing */ /* kill the position notification thread */
if( p_aout->p_sys->p_dsbuffer != NULL ) p_aout->p_sys->b_notification_thread_die = 1;
{ SetEvent( p_aout->p_sys->notification_events[0].hEventNotify );
IDirectSoundBuffer_Stop( p_aout->p_sys->p_dsbuffer ); vlc_thread_join( p_aout->p_sys->notification_thread_id );
} vlc_mutex_destroy( &p_aout->p_sys->buffer_lock );
/* first release the secondary buffer */ /* release the secondary buffer */
if( p_aout->p_sys->p_dsbuffer != NULL ) DirectxDestroySecondaryBuffer( p_aout );
{
IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer );
p_aout->p_sys->p_dsbuffer = NULL;
}
/* then release the primary buffer */ /* then release the primary buffer */
if( p_aout->p_sys->p_dsbuffer_primary != NULL ) if( p_aout->p_sys->p_dsbuffer_primary != NULL )
...@@ -576,6 +581,7 @@ static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout ) ...@@ -576,6 +581,7 @@ static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout )
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */ dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2/* Better position accuracy */
| DSBCAPS_CTRLPOSITIONNOTIFY /* We need notification */
| DSBCAPS_GLOBALFOCUS; /* Allows background playing */ | DSBCAPS_GLOBALFOCUS; /* Allows background playing */
dsbdesc.dwBufferBytes = waveformat.nAvgBytesPerSec * 2; /* 2 sec buffer */ dsbdesc.dwBufferBytes = waveformat.nAvgBytesPerSec * 2; /* 2 sec buffer */
dsbdesc.lpwfxFormat = &waveformat; dsbdesc.lpwfxFormat = &waveformat;
...@@ -596,8 +602,179 @@ static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout ) ...@@ -596,8 +602,179 @@ static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout )
IDirectSoundBuffer_GetCaps( p_aout->p_sys->p_dsbuffer, &dsbcaps ); IDirectSoundBuffer_GetCaps( p_aout->p_sys->p_dsbuffer, &dsbcaps );
p_aout->p_sys->l_buffer_size = dsbcaps.dwBufferBytes; p_aout->p_sys->l_buffer_size = dsbcaps.dwBufferBytes;
p_aout->p_sys->l_write_position = 0; p_aout->p_sys->l_write_position = 0;
intf_WarnMsg( 3, "aout: DirectX DirectxCreateSecondaryBuffer: %li", intf_WarnMsg( 3, "aout: DirectX DirectxCreateSecondaryBuffer: %li",
p_aout->p_sys->l_buffer_size); p_aout->p_sys->l_buffer_size);
/* Now the secondary buffer is created, we need to setup its position
* notification */
p_aout->p_sys->notification_events[0].dwOffset = 0; /* notif position */
p_aout->p_sys->notification_events[1].dwOffset = dsbcaps.dwBufferBytes / 2;
/* Get the IDirectSoundNotify interface */
if FAILED( IDirectSoundBuffer_QueryInterface( p_aout->p_sys->p_dsbuffer,
&IID_IDirectSoundNotify,
(LPVOID *)&p_aout->p_sys->p_dsnotify ) )
{
intf_WarnMsg( 3, "aout: DirectX can't get Notify interface" );
/* Go on anyway */
p_aout->p_sys->p_dsnotify = NULL;
return( 0 ); return( 0 );
}
if FAILED( IDirectSoundNotify_SetNotificationPositions(
p_aout->p_sys->p_dsnotify,
2,
p_aout->p_sys->notification_events ) )
{
intf_WarnMsg( 3, "aout: DirectX can't set position Notification" );
/* Go on anyway */
}
return( 0 );
}
/*****************************************************************************
* DirectxCreateSecondaryBuffer
*****************************************************************************
* This function destroy the secondary buffer.
*****************************************************************************/
static void DirectxDestroySecondaryBuffer( aout_thread_t *p_aout )
{
/* make sure the buffer isn't playing */
if( p_aout->p_sys->p_dsbuffer != NULL )
{
IDirectSoundBuffer_Stop( p_aout->p_sys->p_dsbuffer );
}
if( p_aout->p_sys->p_dsnotify != NULL )
{
IDirectSoundNotify_Release( p_aout->p_sys->p_dsnotify );
p_aout->p_sys->p_dsnotify = NULL;
}
if( p_aout->p_sys->p_dsbuffer != NULL )
{
IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer );
p_aout->p_sys->p_dsbuffer = NULL;
}
} }
/*****************************************************************************
* DirectSoundThread: this thread will capture play notification events.
*****************************************************************************
* As Direct Sound uses circular buffers, we need to use event notification to
* manage them.
* Using event notification implies blocking the thread until the event is
* signaled so we really need to run this in a separate thread.
*****************************************************************************/
static void DirectSoundThread( aout_thread_t *p_aout )
{
HANDLE notification_events[2];
VOID *p_write_position, *p_start_buffer;
long l_bytes1, l_bytes2;
HRESULT dsresult;
long l_buffer_size, l_play_position, l_data_in_buffer;
notification_events[0]=p_aout->p_sys->notification_events[0].hEventNotify;
notification_events[1]=p_aout->p_sys->notification_events[1].hEventNotify;
/* this thread must be high-priority */
if( !SetThreadPriority( GetCurrentThread(),
THREAD_PRIORITY_ABOVE_NORMAL ) )
{
intf_WarnMsg( 3, "aout: DirectSoundThread could not renice itself" );
}
intf_WarnMsg( 3, "aout: DirectSoundThread ready" );
while( !p_aout->p_sys->b_notification_thread_die )
{
/* wait for the position notification */
l_play_position = WaitForMultipleObjects( 2, notification_events,
0, INFINITE );
vlc_mutex_lock( &p_aout->p_sys->buffer_lock );
if( p_aout->p_sys->b_notification_thread_die )
{
break;
}
/* check for buffer underflow (bodge for wrap around) */
l_buffer_size = p_aout->p_sys->l_buffer_size;
l_play_position = (l_play_position - WAIT_OBJECT_0) * l_buffer_size/2;
p_aout->p_sys->l_data_played_from_beginning += (l_buffer_size/2);
l_data_in_buffer = p_aout->p_sys->l_data_written_from_beginning -
p_aout->p_sys->l_data_played_from_beginning;
/* detect wrap-around */
if( l_data_in_buffer < (-l_buffer_size/2) )
{
l_data_in_buffer += l_buffer_size;
}
/* detect underflow */
if( l_data_in_buffer <= 0 )
{
intf_WarnMsg(3,"aout: DirectSoundThread underflow");
p_aout->p_sys->b_buffer_underflown = 1;
p_aout->p_sys->l_write_position =
(l_play_position + l_buffer_size/2) % l_buffer_size;
l_data_in_buffer = l_buffer_size / 2;
}
/* Clear the data which has already been played */
/* Before copying anything, we have to lock the buffer */
dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
p_aout->p_sys->l_write_position, /* Offset of lock start */
l_buffer_size - l_data_in_buffer, /* Number of bytes */
&p_write_position, /* Address of lock start */
&l_bytes1, /* Count of bytes locked before wrap around */
&p_start_buffer, /* Buffer adress (if wrap around) */
&l_bytes2, /* Count of bytes after wrap around */
0); /* Flags */
if( dsresult == DSERR_BUFFERLOST )
{
IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
dsresult = IDirectSoundBuffer_Lock( p_aout->p_sys->p_dsbuffer,
p_aout->p_sys->l_write_position,
l_buffer_size - l_data_in_buffer,
&p_write_position,
&l_bytes1,
&p_start_buffer,
&l_bytes2,
0);
}
if( dsresult != DS_OK )
{
intf_WarnMsg( 3, "aout: DirectX aout_Play can't lock buffer");
vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
return;
}
/* Now do the actual memcpy (two because the buffer is circular) */
memset( p_write_position, 0, l_bytes1 );
if( p_start_buffer != NULL )
{
memset( p_start_buffer, 0, l_bytes2 );
}
/* Now the data has been copied, unlock the buffer */
IDirectSoundBuffer_Unlock( p_aout->p_sys->p_dsbuffer,
p_write_position, l_bytes1, p_start_buffer, l_bytes2 );
vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
}
/* free the events */
CloseHandle( notification_events[0] );
CloseHandle( notification_events[1] );
intf_WarnMsg( 3, "aout: DirectSoundThread exiting" );
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vout_directx.c: Windows DirectX video output display method * vout_directx.c: Windows DirectX video output display method
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vout_directx.c,v 1.9 2001/07/30 00:53:04 sam Exp $ * $Id: vout_directx.c,v 1.10 2001/08/05 15:32:46 gbazin Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -202,7 +202,7 @@ static int vout_Create( vout_thread_t *p_vout ) ...@@ -202,7 +202,7 @@ static int vout_Create( vout_thread_t *p_vout )
* DirectXEventThread will take care of the creation of the video * DirectXEventThread will take care of the creation of the video
* window (because PeekMessage has to be called from the same thread which * window (because PeekMessage has to be called from the same thread which
* created the window). */ * created the window). */
intf_WarnMsg( 3, "vout : vout_Create creating DirectXEventThread" ); intf_WarnMsg( 3, "vout: vout_Create creating DirectXEventThread" );
if( vlc_thread_create( &p_vout->p_sys->event_thread_id, if( vlc_thread_create( &p_vout->p_sys->event_thread_id,
"DirectX Events Thread", "DirectX Events Thread",
(void *) DirectXEventThread, (void *) p_vout) ) (void *) DirectXEventThread, (void *) p_vout) )
...@@ -475,6 +475,7 @@ static void vout_Display( vout_thread_t *p_vout ) ...@@ -475,6 +475,7 @@ static void vout_Display( vout_thread_t *p_vout )
{ {
DDSURFACEDESC ddsd; DDSURFACEDESC ddsd;
HRESULT dxresult; HRESULT dxresult;
int i; int i;
int i_image_width; int i_image_width;
int i_image_height; int i_image_height;
...@@ -505,6 +506,7 @@ static void vout_Display( vout_thread_t *p_vout ) ...@@ -505,6 +506,7 @@ static void vout_Display( vout_thread_t *p_vout )
{ {
RECT rect_window; RECT rect_window;
POINT point_window; POINT point_window;
DDBLTFX ddbltfx;
/* Nothing yet */ /* Nothing yet */
if( p_vout->p_sys->p_surface == NULL ) if( p_vout->p_sys->p_surface == NULL )
...@@ -539,17 +541,24 @@ static void vout_Display( vout_thread_t *p_vout ) ...@@ -539,17 +541,24 @@ static void vout_Display( vout_thread_t *p_vout )
rect_window.bottom = point_window.y; rect_window.bottom = point_window.y;
/* We want to keep the aspect ratio of the video */ /* We want to keep the aspect ratio of the video */
if( !p_vout->b_scale ) /* kuldge */ #if 0
if( p_vout->b_scale )
{ {
DirectXKeepAspectRatio( p_vout, &rect_window ); DirectXKeepAspectRatio( p_vout, &rect_window );
} }
#endif
/* We ask for the "NOTEARING" option */
memset( &ddbltfx, 0, sizeof(DDBLTFX) );
ddbltfx.dwSize = sizeof(DDBLTFX);
ddbltfx.dwDDFX = DDBLTFX_NOTEARING;
/* Blit video surface to display */ /* Blit video surface to display */
dxresult = IDirectDrawSurface3_Blt(p_vout->p_sys->p_display, dxresult = IDirectDrawSurface3_Blt(p_vout->p_sys->p_display,
&rect_window, &rect_window,
p_vout->p_sys->p_surface, p_vout->p_sys->p_surface,
NULL, NULL,
0, NULL ); 0, &ddbltfx );
if( dxresult != DD_OK ) if( dxresult != DD_OK )
{ {
intf_WarnMsg( 3, "vout: could not Blit the surface" ); intf_WarnMsg( 3, "vout: could not Blit the surface" );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vout_xvideo.c: Xvideo video output display method * vout_xvideo.c: Xvideo video output display method
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000, 2001 VideoLAN * Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
* $Id: vout_xvideo.c,v 1.24 2001/08/03 16:04:17 gbazin Exp $ * $Id: vout_xvideo.c,v 1.25 2001/08/05 15:32:46 gbazin Exp $
* *
* Authors: Shane Harper <shanegh@optusnet.com.au> * Authors: Shane Harper <shanegh@optusnet.com.au>
* Vincent Seguin <seguin@via.ecp.fr> * Vincent Seguin <seguin@via.ecp.fr>
...@@ -287,35 +287,16 @@ static int vout_Create( vout_thread_t *p_vout ) ...@@ -287,35 +287,16 @@ static int vout_Create( vout_thread_t *p_vout )
return( 1 ); return( 1 );
} }
/* Spawn base window - this window will include the video output window, /* Check we have access to a video port */
* but also command buttons, subtitles and other indicators */ if( (p_vout->p_sys->xv_port = XVideoGetPort(p_vout->p_sys->p_display)) <0 )
if( XVideoCreateWindow( p_vout ) )
{
intf_ErrMsg( "vout error: cannot create XVideo window" );
XCloseDisplay( p_vout->p_sys->p_display );
free( p_vout->p_sys );
return( 1 );
}
if( (p_vout->p_sys->xv_port = XVideoGetPort( p_vout->p_sys->p_display ))<0 )
{ {
intf_ErrMsg( "vout error: cannot get XVideo port" ); intf_ErrMsg( "vout error: cannot get XVideo port" );
XVideoDestroyWindow( p_vout );
XCloseDisplay( p_vout->p_sys->p_display ); XCloseDisplay( p_vout->p_sys->p_display );
free( p_vout->p_sys ); free( p_vout->p_sys );
return 1; return 1;
} }
intf_DbgMsg( "Using xv port %d" , p_vout->p_sys->xv_port ); intf_DbgMsg( "Using xv port %d" , p_vout->p_sys->xv_port );
/* p_vout->pf_setbuffers( p_vout, NULL, NULL ); */
#if 0
/* XXX The brightness and contrast values should be read from environment
* XXX variables... */
XVideoSetAttribute( p_vout, "XV_BRIGHTNESS", 0.5 );
XVideoSetAttribute( p_vout, "XV_CONTRAST", 0.5 );
#endif
/* Create blank cursor (for mouse cursor autohiding) */ /* Create blank cursor (for mouse cursor autohiding) */
p_vout->p_sys->b_mouse_pointer_visible = 1; p_vout->p_sys->b_mouse_pointer_visible = 1;
p_vout->p_sys->cursor_pixmap = XCreatePixmap( p_vout->p_sys->p_display, p_vout->p_sys->cursor_pixmap = XCreatePixmap( p_vout->p_sys->p_display,
...@@ -340,6 +321,24 @@ static int vout_Create( vout_thread_t *p_vout ) ...@@ -340,6 +321,24 @@ static int vout_Create( vout_thread_t *p_vout )
&cursor_color, &cursor_color,
&cursor_color, 1, 1 ); &cursor_color, 1, 1 );
/* Spawn base window - this window will include the video output window,
* but also command buttons, subtitles and other indicators */
if( XVideoCreateWindow( p_vout ) )
{
intf_ErrMsg( "vout error: cannot create XVideo window" );
XCloseDisplay( p_vout->p_sys->p_display );
free( p_vout->p_sys );
return( 1 );
}
/* p_vout->pf_setbuffers( p_vout, NULL, NULL ); */
#if 0
/* XXX The brightness and contrast values should be read from environment
* XXX variables... */
XVideoSetAttribute( p_vout, "XV_BRIGHTNESS", 0.5 );
XVideoSetAttribute( p_vout, "XV_CONTRAST", 0.5 );
#endif
/* Disable screen saver and return */ /* Disable screen saver and return */
XVideoDisableScreenSaver( p_vout ); XVideoDisableScreenSaver( p_vout );
...@@ -938,6 +937,13 @@ static int XVideoCreateWindow( vout_thread_t *p_vout ) ...@@ -938,6 +937,13 @@ static int XVideoCreateWindow( vout_thread_t *p_vout )
XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->yuv_window, XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->yuv_window,
ExposureMask ); ExposureMask );
/* If the cursor was formerly blank than blank it again */
if( !p_vout->p_sys->b_mouse_pointer_visible )
{
X11ToggleMousePointer( p_vout );
X11ToggleMousePointer( p_vout );
}
return( 0 ); return( 0 );
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ac3_decoder_thread.c: ac3 decoder thread * ac3_decoder_thread.c: ac3 decoder thread
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: ac3_decoder_thread.c,v 1.35 2001/07/08 23:15:11 reno Exp $ * $Id: ac3_decoder_thread.c,v 1.36 2001/08/05 15:32:46 gbazin Exp $
* *
* Authors: Michel Lespinasse <walken@zoy.org> * Authors: Michel Lespinasse <walken@zoy.org>
* *
...@@ -78,15 +78,17 @@ static void BitstreamCallback ( bit_stream_t *p_bit_stream, ...@@ -78,15 +78,17 @@ static void BitstreamCallback ( bit_stream_t *p_bit_stream,
vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config ) vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config )
{ {
ac3dec_thread_t * p_ac3thread; ac3dec_thread_t * p_ac3thread;
ac3dec_thread_t * p_ac3thread_temp;
intf_DbgMsg( "ac3dec debug: creating ac3 decoder thread" ); intf_DbgMsg( "ac3dec debug: creating ac3 decoder thread" );
/* Allocate the memory needed to store the thread's structure */ /* Allocate the memory needed to store the thread's structure */
p_ac3thread = (ac3dec_thread_t *)malloc(sizeof(ac3dec_thread_t)); p_ac3thread_temp = (ac3dec_thread_t *)malloc(sizeof(ac3dec_thread_t) + 15);
/* We need to be 16 bytes aligned */ /* We need to be 16 bytes aligned */
p_ac3thread->ac3thread = (int)p_ac3thread & (-15); p_ac3thread = (ac3dec_thread_t *)(((unsigned long)p_ac3thread_temp + 15)
p_ac3thread = (ac3dec_thread_t *)p_ac3thread->ac3thread; & ~0xFUL );
p_ac3thread->ac3thread = p_ac3thread_temp;
if(p_ac3thread == NULL) if(p_ac3thread == NULL)
{ {
...@@ -110,7 +112,7 @@ vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config ) ...@@ -110,7 +112,7 @@ vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config )
if( DOWNMIX.p_module == NULL ) if( DOWNMIX.p_module == NULL )
{ {
intf_ErrMsg( "ac3dec error: no suitable downmix module" ); intf_ErrMsg( "ac3dec error: no suitable downmix module" );
free( p_ac3thread ); free( p_ac3thread->ac3thread );
return( 0 ); return( 0 );
} }
...@@ -135,7 +137,7 @@ vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config ) ...@@ -135,7 +137,7 @@ vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config )
{ {
intf_ErrMsg( "ac3dec error: no suitable IMDCT module" ); intf_ErrMsg( "ac3dec error: no suitable IMDCT module" );
module_Unneed( p_ac3thread->ac3_decoder.downmix.p_module ); module_Unneed( p_ac3thread->ac3_decoder.downmix.p_module );
free( p_ac3thread ); free( p_ac3thread->ac3thread );
return( 0 ); return( 0 );
} }
...@@ -163,7 +165,7 @@ vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config ) ...@@ -163,7 +165,7 @@ vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config )
intf_ErrMsg( "ac3dec error: can't spawn ac3 decoder thread" ); intf_ErrMsg( "ac3dec error: can't spawn ac3 decoder thread" );
module_Unneed( p_ac3thread->ac3_decoder.downmix.p_module ); module_Unneed( p_ac3thread->ac3_decoder.downmix.p_module );
module_Unneed( p_ac3thread->ac3_decoder.imdct.p_module ); module_Unneed( p_ac3thread->ac3_decoder.imdct.p_module );
free (p_ac3thread); free (p_ac3thread->ac3thread);
return 0; return 0;
} }
...@@ -341,8 +343,7 @@ static void EndThread (ac3dec_thread_t * p_ac3thread) ...@@ -341,8 +343,7 @@ static void EndThread (ac3dec_thread_t * p_ac3thread)
/* Destroy descriptor */ /* Destroy descriptor */
free( p_ac3thread->p_config ); free( p_ac3thread->p_config );
p_ac3thread = (ac3dec_thread_t *)p_ac3thread->ac3thread; free( p_ac3thread->ac3thread );
free( p_ac3thread );
intf_DbgMsg ("ac3dec debug: ac3 decoder thread %p destroyed", p_ac3thread); intf_DbgMsg ("ac3dec debug: ac3 decoder thread %p destroyed", p_ac3thread);
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ac3_decoder_thread.h : ac3 decoder thread interface * ac3_decoder_thread.h : ac3 decoder thread interface
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: ac3_decoder_thread.h,v 1.8 2001/07/08 23:15:11 reno Exp $ * $Id: ac3_decoder_thread.h,v 1.9 2001/08/05 15:32:46 gbazin Exp $
* *
* Authors: Michel Kaempf <maxx@via.ecp.fr> * Authors: Michel Kaempf <maxx@via.ecp.fr>
* *
...@@ -50,7 +50,8 @@ typedef struct ac3dec_thread_s ...@@ -50,7 +50,8 @@ typedef struct ac3dec_thread_s
* Output properties * Output properties
*/ */
aout_fifo_t * p_aout_fifo; /* stores the decompressed audio frames */ aout_fifo_t * p_aout_fifo; /* stores the decompressed audio frames */
int ac3thread; /* save the old pointer */
struct ac3dec_thread_s * ac3thread; /* save the old pointer */
} ac3dec_thread_t; } ac3dec_thread_t;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* decoders. * decoders.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input.c,v 1.127 2001/07/18 14:21:00 massiot Exp $ * $Id: input.c,v 1.128 2001/08/05 15:32:46 gbazin Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -605,12 +605,8 @@ static void FileOpen( input_thread_t * p_input ) ...@@ -605,12 +605,8 @@ static void FileOpen( input_thread_t * p_input )
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
intf_WarnMsg( 1, "input: opening file `%s'", p_input->p_source ); intf_WarnMsg( 1, "input: opening file `%s'", p_input->p_source );
#if defined( WIN32 )
if( (p_input->i_handle = open( psz_name, O_BINARY ) ) == (-1) )
#else
if( (p_input->i_handle = open( psz_name, if( (p_input->i_handle = open( psz_name,
/*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) ) /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
#endif
{ {
intf_ErrMsg( "input error: cannot open file (%s)", strerror(errno) ); intf_ErrMsg( "input error: cannot open file (%s)", strerror(errno) );
p_input->b_error = 1; p_input->b_error = 1;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* and spawn threads. * and spawn threads.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: main.c,v 1.109 2001/07/30 00:53:05 sam Exp $ * $Id: main.c,v 1.110 2001/08/05 15:32:46 gbazin Exp $
* *
* Authors: Vincent Seguin <seguin@via.ecp.fr> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -287,6 +287,8 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] ) ...@@ -287,6 +287,8 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
*/ */
#if defined( SYS_BEOS ) || defined( SYS_DARWIN ) #if defined( SYS_BEOS ) || defined( SYS_DARWIN )
system_Init( &i_argc, ppsz_argv, ppsz_env ); system_Init( &i_argc, ppsz_argv, ppsz_env );
#elif defined( WIN32 )
_fmode = _O_BINARY; /* sets the default file-translation mode on Win32 */
#endif #endif
/* /*
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* video_text.c : text manipulation functions * video_text.c : text manipulation functions
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: video_text.c,v 1.29 2001/06/25 11:34:08 sam Exp $ * $Id: video_text.c,v 1.30 2001/08/05 15:32:47 gbazin Exp $
* *
* Authors: Vincent Seguin <seguin@via.ecp.fr> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -263,11 +263,7 @@ vout_font_t *vout_LoadFont( const char *psz_name ) ...@@ -263,11 +263,7 @@ vout_font_t *vout_LoadFont( const char *psz_name )
} }
/* Open file */ /* Open file */
#ifndef WIN32
i_file = open( psz_file, O_RDONLY ); i_file = open( psz_file, O_RDONLY );
#else
i_file = open( psz_file, O_RDONLY | O_BINARY );
#endif
free( psz_file ); free( psz_file );
if( i_file != -1 ) if( i_file != -1 )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment