]> git.sesse.net Git - vlc/commitdiff
* Big rewrite of the DirectX audio plugin. The audio output is now (almost)
authorGildas Bazin <gbazin@videolan.org>
Sun, 5 Aug 2001 15:32:47 +0000 (15:32 +0000)
committerGildas Bazin <gbazin@videolan.org>
Sun, 5 Aug 2001 15:32:47 +0000 (15:32 +0000)
    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

plugins/directx/aout_directx.c
plugins/directx/vout_directx.c
plugins/x11/vout_xvideo.c
src/ac3_decoder/ac3_decoder_thread.c
src/ac3_decoder/ac3_decoder_thread.h
src/input/input.c
src/interface/main.c
src/video_output/video_text.c

index 2b2892ff143b4399d129350bb9ad76119231cf4b..9cccf0cd02560514b0c7aad50b1911ebbb52a0de 100644 (file)
@@ -2,7 +2,7 @@
  * aout_directx.c: Windows DirectX audio output method
  *****************************************************************************
  * 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>
  *
 #define MODULE_NAME directx
 #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
@@ -81,12 +75,24 @@ typedef struct aout_sys_s
                                        * takes care of mixing all the
                                        * secondary buffers into the primary) */
 
+    LPDIRECTSOUNDNOTIFY p_dsnotify;         /* the position notify interface */
+
     HINSTANCE           hdsound_dll;      /* handle of the opened dsound dll */
 
     long l_buffer_size;                       /* secondary sound buffer size */
     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;
 
@@ -102,8 +108,10 @@ static void    aout_Play        ( aout_thread_t *p_aout,
 static void    aout_Close       ( aout_thread_t *p_aout );
 
 /* local functions */
-static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout );
-static int DirectxInitDSound( aout_thread_t *p_aout );
+static int  DirectxCreateSecondaryBuffer ( 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
@@ -144,7 +152,6 @@ static int aout_Open( aout_thread_t *p_aout )
 {
     HRESULT dsresult;
     DSBUFFERDESC dsbuffer_desc;
-    WAVEFORMATEX waveformat;
 
     intf_WarnMsg( 3, "aout: DirectX aout_Open ");
 
@@ -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_dsbuffer_primary = 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->i_format   = AOUT_FORMAT_DEFAULT;
@@ -194,42 +207,25 @@ static int aout_Open( aout_thread_t *p_aout )
         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,
-                                            &waveformat);
-    if( dsresult != DS_OK )
-    {
-        intf_WarnMsg( 3, "aout: can't set primary buffer format");
-    }
+    /* Now we need to setup DirectSound play notification */
 
-#if 0
-    /* ensure the primary buffer is playing. We won't actually hear anything
-     * until the secondary buffer is playing */
-    dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer_primary,
-                                        0,
-                                        0,
-                                        DSBPLAY_LOOPING);
-    if( dsresult != DS_OK )
+    /* first we need to create the notification events */
+    p_aout->p_sys->notification_events[0].hEventNotify =
+        CreateEvent( NULL, FALSE, FALSE, NULL );
+    p_aout->p_sys->notification_events[1].hEventNotify =
+        CreateEvent( NULL, FALSE, FALSE, NULL );
+
+    /* then launch the notification thread */
+    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 ");
-        IDirectSound_Release( p_aout->p_sys->p_dsbuffer_primary );
-        IDirectSound_Release( p_aout->p_sys->p_dsobject );
-        p_aout->p_sys->p_dsobject = NULL;
-        p_aout->p_sys->p_dsbuffer_primary = NULL;
-        return( 1 );
+        intf_ErrMsg( "aout error: can't create DirectSoundThread" );
+        intf_ErrMsg("aout error: %s", strerror(ENOMEM));
+        /* Let's go on anyway */
     }
-#endif
 
     return( 0 );
 }
@@ -243,25 +239,65 @@ static int aout_Open( 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 ");
 
-    /* first release the current secondary buffer */
-    if( p_aout->p_sys->p_dsbuffer != NULL )
+    /* Set the format of Direct Sound primary buffer */
+
+    /* 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_aout->p_sys->p_dsbuffer = NULL;
+        p_waveformat = malloc( i_size_struct );
+        dsresult = IDirectSoundBuffer_GetFormat(
+                                             p_aout->p_sys->p_dsbuffer_primary,
+                                             p_waveformat, i_size_struct,
+                                             NULL );
     }
 
-    /* then create a new secondary buffer */
-    dsresult = DirectxCreateSecondaryBuffer( p_aout );    
+    if( dsresult == DS_OK )
+    {
+        /* 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 )
+        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");
+        vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
         return( 1 );
     }
 
+    vlc_mutex_unlock( &p_aout->p_sys->buffer_lock );
+
     p_aout->i_latency = 0;
   
     return( 0 );
@@ -270,48 +306,35 @@ static int aout_SetFormat( aout_thread_t *p_aout )
 /*****************************************************************************
  * aout_GetBufInfo: buffer status query
  *****************************************************************************
- * returns the number of bytes in the audio buffer compared to the size of
- * l_buffer_limit...
+ * returns the number of bytes in the audio buffer that have not yet been
+ * sent to the sound device.
  *****************************************************************************/
 static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit )
 {
     long l_play_position, l_notused, l_result;
     HRESULT dsresult;
 
-    dsresult = IDirectSoundBuffer_GetCurrentPosition(p_aout->p_sys->p_dsbuffer,
-                                                 &l_play_position, &l_notused);
-    if( dsresult == DSERR_BUFFERLOST )
+    if( p_aout->p_sys->b_buffer_underflown )
     {
-        IDirectSoundBuffer_Restore( p_aout->p_sys->p_dsbuffer );
-        dsresult = IDirectSoundBuffer_GetCurrentPosition(
-                                                 p_aout->p_sys->p_dsbuffer,
-                                                 &l_play_position, &l_notused
-                                                        );
+        intf_WarnMsg( 3, "aout: DirectX aout_GetBufInfo underflow");
+        return( l_buffer_limit );
     }
+
+    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");
         return( l_buffer_limit );
     }
 
-#if 0
-    /* temporary hack. When you start playing a new file, the play position
-     * doesn't start changing immediatly, even though sound is already
-     * playing from the sound card */
-    if( l_play_position == 0 )
-    { 
-       intf_WarnMsg( 5, "aout: DirectX aout_GetBufInfo: %li", l_buffer_limit);
-       return( l_buffer_limit );
-    }
-#endif
-
     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_write_position) /2 ;
+                  + p_aout->p_sys->l_write_position);
 
 #if 0
-    intf_WarnMsg( 5, "aout: DirectX aout_GetBufInfo: %li", l_result);
+    intf_WarnMsg( 3, "aout: DirectX aout_GetBufInfo: %li", l_result);
 #endif
     return l_result;
 }
@@ -320,58 +343,40 @@ static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit )
  * aout_Play: play a sound buffer
  *****************************************************************************
  * 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 )
 {
     VOID            *p_write_position, *p_start_buffer;
-    long            l_bytes1, l_bytes2;
-    long            l_play_position, l_notused, l_buffer_free_length;
+    long            l_bytes1, l_bytes2, l_play_position;
     HRESULT         dsresult;
 
-    /* We want to copy data to the circular sound buffer, so we first need to
-     * find out were in the buffer we can write our data */
-    dsresult = IDirectSoundBuffer_GetCurrentPosition(p_aout->p_sys->p_dsbuffer,
-                                                     &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_Play can'get buffer position");
-    }
-
-#if 1
-    /* check that we are not overflowing the circular buffer (everything should
-     * be alright but just in case) */
-    l_buffer_free_length =  l_play_position - p_aout->p_sys->l_write_position;
-    if( l_buffer_free_length <= 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;*/
+    /* protect buffer access (because of DirectSoundThread) */
+    vlc_mutex_lock( &p_aout->p_sys->buffer_lock );
 
-        /* Update the write pointer */
-        p_aout->p_sys->l_write_position = l_notused;
-
-    }
-    else
+    if( p_aout->p_sys->b_buffer_underflown )
     {
-#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
+        /* 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(
+                                            p_aout->p_sys->p_dsbuffer,
+                                            &l_play_position,
+                                            &p_aout->p_sys->l_write_position );
+        if( dsresult != DS_OK )
+        {
+            intf_WarnMsg( 3, "aout: aout_Play can'get buffer position");
+            p_aout->p_sys->l_write_position = 0; 
+        }
+
+        /* reinitialise the underflow detection counters */
+        p_aout->p_sys->l_data_written_from_beginning = 0;
+        p_aout->p_sys->l_data_played_from_beginning =
+         -(p_aout->p_sys->l_write_position % (p_aout->p_sys->l_buffer_size/2));
+        p_aout->p_sys->b_buffer_underflown = 0;
     }
-#endif
 
     /* Before copying anything, we have to lock the buffer */
     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 )
     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 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 );
     if( p_start_buffer != NULL )
     {
@@ -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*/
     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_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 */
     dsresult = IDirectSoundBuffer_Play( p_aout->p_sys->p_dsbuffer,
@@ -445,18 +454,14 @@ static void aout_Close( aout_thread_t *p_aout )
 
     intf_WarnMsg( 3, "aout: DirectX aout_Close ");
 
-    /* make sure the buffer isn't playing */
-    if( p_aout->p_sys->p_dsbuffer != NULL )
-    {
-        IDirectSoundBuffer_Stop( p_aout->p_sys->p_dsbuffer );
-    }
+    /* kill the position notification thread */
+    p_aout->p_sys->b_notification_thread_die = 1;
+    SetEvent( p_aout->p_sys->notification_events[0].hEventNotify );
+    vlc_thread_join( p_aout->p_sys->notification_thread_id );
+    vlc_mutex_destroy( &p_aout->p_sys->buffer_lock );
 
-    /* first release the secondary buffer */
-    if( p_aout->p_sys->p_dsbuffer != NULL )
-    {
-        IDirectSoundBuffer_Release( p_aout->p_sys->p_dsbuffer );
-        p_aout->p_sys->p_dsbuffer = NULL;
-    }  
+    /* release the secondary buffer */
+    DirectxDestroySecondaryBuffer( p_aout );
 
     /* then release the primary buffer */
     if( p_aout->p_sys->p_dsbuffer_primary != NULL )
@@ -557,17 +562,17 @@ static int DirectxInitDSound( aout_thread_t *p_aout )
  *****************************************************************************/
 static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout )
 {
-    WAVEFORMATEX waveformat;
-    DSBUFFERDESC dsbdesc;
-    DSBCAPS      dsbcaps;
+    WAVEFORMATEX         waveformat;
+    DSBUFFERDESC         dsbdesc;
+    DSBCAPS              dsbcaps;
 
     /* First set the buffer format */
     memset(&waveformat, 0, sizeof(WAVEFORMATEX)); 
-    waveformat.wFormatTag = WAVE_FORMAT_PCM; 
-    waveformat.nChannels = p_aout->i_channels; 
-    waveformat.nSamplesPerSec = p_aout->l_rate; 
-    waveformat.wBitsPerSample = 16; 
-    waveformat.nBlockAlign = waveformat.wBitsPerSample / 8 *
+    waveformat.wFormatTag      = WAVE_FORMAT_PCM; 
+    waveformat.nChannels       = p_aout->i_channels; 
+    waveformat.nSamplesPerSec  = p_aout->l_rate; 
+    waveformat.wBitsPerSample  = 16; 
+    waveformat.nBlockAlign     = waveformat.wBitsPerSample / 8 *
                                  waveformat.nChannels;
     waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec *
                                      waveformat.nBlockAlign;
@@ -576,6 +581,7 @@ static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout )
     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 = waveformat.nAvgBytesPerSec * 2;  /* 2 sec buffer */
     dsbdesc.lpwfxFormat = &waveformat; 
@@ -596,8 +602,179 @@ static int DirectxCreateSecondaryBuffer( aout_thread_t *p_aout )
     IDirectSoundBuffer_GetCaps( p_aout->p_sys->p_dsbuffer, &dsbcaps  );
     p_aout->p_sys->l_buffer_size = dsbcaps.dwBufferBytes;
     p_aout->p_sys->l_write_position = 0;
+
     intf_WarnMsg( 3, "aout: DirectX DirectxCreateSecondaryBuffer: %li",
                   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 );
+    }
+        
+    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" );
+
+}
+
+
index 757a4f556d54807f7d5c6b3104074efe9233abec..a10d3e5d4df26ec371fc5c19bdcad6da8e39bd2d 100644 (file)
@@ -2,7 +2,7 @@
  * vout_directx.c: Windows DirectX video output display method
  *****************************************************************************
  * 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>
  *
@@ -202,7 +202,7 @@ static int vout_Create( vout_thread_t *p_vout )
      * DirectXEventThread will take care of the creation of the video
      * window (because PeekMessage has to be called from the same thread which
      * 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,
                            "DirectX Events Thread",
                            (void *) DirectXEventThread, (void *) p_vout) )
@@ -475,6 +475,7 @@ static void vout_Display( vout_thread_t *p_vout )
 {
     DDSURFACEDESC ddsd;
     HRESULT       dxresult;
+
     int           i;
     int           i_image_width;
     int           i_image_height;
@@ -503,8 +504,9 @@ static void vout_Display( vout_thread_t *p_vout )
 
     if( p_vout->b_need_render )
     {
-        RECT  rect_window;
-        POINT point_window;
+        RECT     rect_window;
+        POINT    point_window;
+        DDBLTFX  ddbltfx;
   
         /* Nothing yet */
         if( p_vout->p_sys->p_surface == NULL )
@@ -539,17 +541,24 @@ static void vout_Display( vout_thread_t *p_vout )
         rect_window.bottom = point_window.y;
 
         /* 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 );
         }
+#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 */
         dxresult = IDirectDrawSurface3_Blt(p_vout->p_sys->p_display,
                                            &rect_window,
                                            p_vout->p_sys->p_surface,
                                            NULL,
-                                           0, NULL );
+                                           0, &ddbltfx );
         if( dxresult != DD_OK )
         {
             intf_WarnMsg( 3, "vout: could not Blit the surface" );
index 72f4cdcd424f0e4171d7fdb760d998da565a4a14..9bb31680cde5388437b4f13ae1e4aababc07de48 100644 (file)
@@ -2,7 +2,7 @@
  * vout_xvideo.c: Xvideo video output display method
  *****************************************************************************
  * 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>
  *          Vincent Seguin <seguin@via.ecp.fr>
@@ -287,35 +287,16 @@ static int vout_Create( vout_thread_t *p_vout )
         return( 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 );
-    }
-
-    if( (p_vout->p_sys->xv_port = XVideoGetPort( p_vout->p_sys->p_display ))<0 )
+    /* Check we have access to a video port */
+    if( (p_vout->p_sys->xv_port = XVideoGetPort(p_vout->p_sys->p_display)) <0 )
     {
         intf_ErrMsg( "vout error: cannot get XVideo port" );
-        XVideoDestroyWindow( p_vout );
         XCloseDisplay( p_vout->p_sys->p_display );
         free( p_vout->p_sys );
         return 1;
     }
     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) */
     p_vout->p_sys->b_mouse_pointer_visible = 1;
     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 )
                                       &cursor_color,
                                       &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 */
     XVideoDisableScreenSaver( p_vout );
@@ -550,7 +549,7 @@ static int vout_Manage( vout_thread_t *p_vout )
         else if( xevent.type == MotionNotify )
         {
             p_vout->p_sys->i_time_mouse_last_moved = mdate();
-           if( !p_vout->p_sys->b_mouse_pointer_visible )
+            if( !p_vout->p_sys->b_mouse_pointer_visible )
                 X11ToggleMousePointer( p_vout ); 
         }
         /* Other event */
@@ -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,
                   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 );
 }
 
@@ -1089,13 +1095,13 @@ void X11ToggleMousePointer( vout_thread_t *p_vout )
     {
         XDefineCursor( p_vout->p_sys->p_display,
                        p_vout->p_sys->window,
-                      p_vout->p_sys->blank_cursor );
-       p_vout->p_sys->b_mouse_pointer_visible = 0;
+                       p_vout->p_sys->blank_cursor );
+        p_vout->p_sys->b_mouse_pointer_visible = 0;
     }
     else
     {
         XUndefineCursor( p_vout->p_sys->p_display, p_vout->p_sys->window );
-       p_vout->p_sys->b_mouse_pointer_visible = 1;
+        p_vout->p_sys->b_mouse_pointer_visible = 1;
     }
 }
 
index 936869d3fa9b663ad7c049625db1054777399468..1bbf064656715253bef4d80e698dd1d4be42c4b9 100644 (file)
@@ -2,7 +2,7 @@
  * ac3_decoder_thread.c: ac3 decoder thread
  *****************************************************************************
  * 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>
  *
@@ -78,15 +78,17 @@ static void     BitstreamCallback       ( bit_stream_t *p_bit_stream,
 vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config )
 {
     ac3dec_thread_t *   p_ac3thread;
+    ac3dec_thread_t *   p_ac3thread_temp;
 
     intf_DbgMsg( "ac3dec debug: creating ac3 decoder thread" );
 
     /* 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 */
-    p_ac3thread->ac3thread = (int)p_ac3thread & (-15);
-    p_ac3thread = (ac3dec_thread_t *)p_ac3thread->ac3thread;
+    p_ac3thread = (ac3dec_thread_t *)(((unsigned long)p_ac3thread_temp + 15)
+                                     & ~0xFUL );
+    p_ac3thread->ac3thread = p_ac3thread_temp;
     
     if(p_ac3thread == NULL)
     {
@@ -110,7 +112,7 @@ vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config )
     if( DOWNMIX.p_module == NULL )
     {
         intf_ErrMsg( "ac3dec error: no suitable downmix module" );
-        free( p_ac3thread );
+        free( p_ac3thread->ac3thread );
         return( 0 );
     }
 
@@ -135,7 +137,7 @@ vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config )
     {
         intf_ErrMsg( "ac3dec error: no suitable IMDCT module" );
         module_Unneed( p_ac3thread->ac3_decoder.downmix.p_module );
-        free( p_ac3thread );
+        free( p_ac3thread->ac3thread );
         return( 0 );
     }
 
@@ -163,7 +165,7 @@ vlc_thread_t ac3dec_CreateThread( adec_config_t * p_config )
         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.imdct.p_module );
-        free (p_ac3thread);
+        free (p_ac3thread->ac3thread);
         return 0;
     }
 
@@ -341,8 +343,7 @@ static void EndThread (ac3dec_thread_t * p_ac3thread)
 
     /* Destroy descriptor */
     free( p_ac3thread->p_config );
-    p_ac3thread = (ac3dec_thread_t *)p_ac3thread->ac3thread;
-    free( p_ac3thread );
+    free( p_ac3thread->ac3thread );
 
     intf_DbgMsg ("ac3dec debug: ac3 decoder thread %p destroyed", p_ac3thread);
 }
index a06ad6f9380d8eccc3fb9891791aa9abad7780b7..896ad88038704cfeef5ae5ad949768f84468719a 100644 (file)
@@ -2,7 +2,7 @@
  * ac3_decoder_thread.h : ac3 decoder thread interface
  *****************************************************************************
  * 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>
  *
@@ -50,7 +50,8 @@ typedef struct ac3dec_thread_s
      * Output properties
      */
     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;
 
index 3e532d5c423c2c0c8a8f2622af2da4d24c216025..3bdee5cb1df023de85df02430af1371678dd8bbb 100644 (file)
@@ -4,7 +4,7 @@
  * decoders.
  *****************************************************************************
  * 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>
  *
@@ -605,12 +605,8 @@ static void FileOpen( input_thread_t * p_input )
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 
     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,
                                    /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
-#endif
     {
         intf_ErrMsg( "input error: cannot open file (%s)", strerror(errno) );
         p_input->b_error = 1;
index f4305bad589b930f5900e2659de6d0a95dae0885..7f98734e0c647dd2230a5f9a7552bdd33bdf3f58 100644 (file)
@@ -4,7 +4,7 @@
  * and spawn threads.
  *****************************************************************************
  * 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>
  *          Samuel Hocevar <sam@zoy.org>
@@ -287,6 +287,8 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] )
      */
 #if defined( SYS_BEOS ) || defined( SYS_DARWIN )
     system_Init( &i_argc, ppsz_argv, ppsz_env );
+#elif defined( WIN32 )
+    _fmode = _O_BINARY;   /* sets the default file-translation mode on Win32 */
 #endif
 
     /*
index 9c25944d82bd943e7e6915b336b05b92dbe4e4a8..47e51cc3fad6c2d451b2e1413c079922e54265ae 100644 (file)
@@ -2,7 +2,7 @@
  * video_text.c : text manipulation functions
  *****************************************************************************
  * 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>
  *          Samuel Hocevar <sam@zoy.org>
@@ -263,11 +263,7 @@ vout_font_t *vout_LoadFont( const char *psz_name )
         }
 
         /* Open file */
-#ifndef WIN32
         i_file = open( psz_file, O_RDONLY );
-#else
-        i_file = open( psz_file, O_RDONLY | O_BINARY );
-#endif
         free( psz_file );
 
         if( i_file != -1 )