* modules/gui/wxwindows/interface.cpp: resume after pause was broken recently.
authorGildas Bazin <gbazin@videolan.org>
Wed, 9 Jul 2003 21:42:28 +0000 (21:42 +0000)
committerGildas Bazin <gbazin@videolan.org>
Wed, 9 Jul 2003 21:42:28 +0000 (21:42 +0000)
* src/audio_output/output.c: reverted a recent change that was screwing up the proper scheduling of audio samples after a starvation. That should improve the heavy resampling we currently have after a pause.
* modules/audio_output/alsa.c: improvements and fixes to the alsa audio output.

modules/audio_output/alsa.c
modules/gui/wxwindows/interface.cpp
src/audio_output/output.c

index bead5db..081009e 100644 (file)
@@ -2,7 +2,7 @@
  * alsa.c : alsa plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000-2001 VideoLAN
- * $Id: alsa.c,v 1.28 2003/05/26 19:06:47 gbazin Exp $
+ * $Id: alsa.c,v 1.29 2003/07/09 21:42:28 gbazin Exp $
  *
  * Authors: Henri Fallon <henri@videolan.org> - Original Author
  *          Jeffrey Baker <jwbaker@acm.org> - Port to ALSA 1.0 API
@@ -57,6 +57,12 @@ struct aout_sys_t
 #ifdef DEBUG
     snd_output_t      * p_snd_stderr;
 #endif
+
+    int b_playing;                                         /* playing status */
+    mtime_t start_date;
+
+    vlc_mutex_t lock;
+    vlc_cond_t  wait ;
 };
 
 #define A52_FRAME_NB 1536
@@ -65,7 +71,7 @@ struct aout_sys_t
    To convert them to a number of bytes you have to multiply them by the
    number of channel(s) (eg. 2 for stereo) and the size of a sample (eg.
    2 for s16). */
-#define ALSA_DEFAULT_PERIOD_SIZE        2048
+#define ALSA_DEFAULT_PERIOD_SIZE        1024
 #define ALSA_DEFAULT_BUFFER_SIZE        ( ALSA_DEFAULT_PERIOD_SIZE << 4 )
 #define ALSA_SPDIF_PERIOD_SIZE          A52_FRAME_NB
 #define ALSA_SPDIF_BUFFER_SIZE          ( ALSA_SPDIF_PERIOD_SIZE << 4 )
@@ -262,6 +268,10 @@ static int Open( vlc_object_t *p_this )
         msg_Err( p_aout, "out of memory" );
         return VLC_ENOMEM;
     }
+    p_sys->b_playing = VLC_FALSE;
+    p_sys->start_date = 0;
+    vlc_cond_init( p_aout, &p_sys->wait );
+    vlc_mutex_init( p_aout, &p_sys->lock );
 
     /* Get device name */
     if( (psz_device = config_GetPsz( p_aout, "alsadev" )) == NULL )
@@ -561,6 +571,19 @@ error:
  *****************************************************************************/
 static void Play( aout_instance_t *p_aout )
 {
+    if( !p_aout->output.p_sys->b_playing )
+    {
+        p_aout->output.p_sys->b_playing = 1;
+
+        /* get the playing date of the first aout buffer */
+        p_aout->output.p_sys->start_date =
+            aout_FifoFirstDate( p_aout, &p_aout->output.fifo );
+
+        /* wake up the audio output thread */
+        vlc_mutex_lock( &p_aout->output.p_sys->lock );
+        vlc_cond_signal( &p_aout->output.p_sys->wait );
+        vlc_mutex_unlock( &p_aout->output.p_sys->lock );
+    }
 }
 
 /*****************************************************************************
@@ -572,6 +595,11 @@ static void Close( vlc_object_t *p_this )
     struct aout_sys_t * p_sys = p_aout->output.p_sys;
     int i_snd_rc;
 
+    /* make sure the audio output thread is waken up */
+    vlc_mutex_lock( &p_aout->output.p_sys->lock );
+    vlc_cond_signal( &p_aout->output.p_sys->wait );
+    vlc_mutex_unlock( &p_aout->output.p_sys->lock );
+
     p_aout->b_die = VLC_TRUE;
     vlc_thread_join( p_aout );
     p_aout->b_die = VLC_FALSE;
@@ -596,20 +624,18 @@ static void Close( vlc_object_t *p_this )
  *****************************************************************************/
 static int ALSAThread( aout_instance_t * p_aout )
 {
-    struct aout_sys_t * p_sys = p_aout->output.p_sys;
+    /* Wait for the exact time to start playing (avoids resampling) */
+    vlc_mutex_lock( &p_aout->output.p_sys->lock );
+    if( !p_aout->output.p_sys->start_date )
+        vlc_cond_wait( &p_aout->output.p_sys->wait,
+                       &p_aout->output.p_sys->lock );
+    vlc_mutex_unlock( &p_aout->output.p_sys->lock );
+
+    mwait( p_aout->output.p_sys->start_date - AOUT_PTS_TOLERANCE / 4 );
 
     while ( !p_aout->b_die )
     {
         ALSAFill( p_aout );
-
-        /* Sleep during less than one period to avoid a lot of buffer
-           underruns */
-
-        /* Why do we need to sleep ? --Meuuh */
-        /* Maybe because I don't want to eat all the cpu by looping
-           all the time. --Bozo */
-        /* Shouldn't snd_pcm_wait() make us wait ? --Meuuh */
-        msleep( p_sys->i_period_time >> 1 );
     }
 
     return 0;
@@ -630,18 +656,7 @@ static void ALSAFill( aout_instance_t * p_aout )
 
     snd_pcm_status_alloca( &p_status );
 
-    /* Wait for the device's readiness (ie. there is enough space in the
-       buffer to write at least one complete chunk) */
-    i_snd_rc = snd_pcm_wait( p_sys->p_snd_pcm, THREAD_SLEEP );
-    if( i_snd_rc < 0 )
-    {
-        msg_Err( p_aout, "ALSA device not ready !!! (%s)",
-                         snd_strerror( i_snd_rc ) );
-        return;
-    }
-
     /* Fill in the buffer until space or audio output buffer shortage */
-    for ( ; ; )
     {
         /* Get the status */
         i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );
@@ -649,6 +664,8 @@ static void ALSAFill( aout_instance_t * p_aout )
         {
             msg_Err( p_aout, "unable to get the device's status (%s)",
                              snd_strerror( i_snd_rc ) );
+
+            msleep( p_sys->i_period_time >> 1 );
             return;
         }
 
@@ -666,15 +683,18 @@ static void ALSAFill( aout_instance_t * p_aout )
                 i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );
                 if( i_snd_rc < 0 )
                 {
-                    msg_Err( p_aout,
-                        "unable to get the device's status after recovery (%s)",
-                        snd_strerror( i_snd_rc ) );
+                    msg_Err( p_aout, "unable to get the device's status after "
+                             "recovery (%s)", snd_strerror( i_snd_rc ) );
+
+                    msleep( p_sys->i_period_time >> 1 );
                     return;
                 }
             }
             else
             {
                 msg_Err( p_aout, "unable to recover from buffer underrun" );
+
+                msleep( p_sys->i_period_time >> 1 );
                 return;
             }
         }
@@ -691,10 +711,12 @@ static void ALSAFill( aout_instance_t * p_aout )
                         (p_aout->output.output.i_format ==
                          VLC_FOURCC('s','p','d','i')) );
 
-        /* Audio output buffer shortage -> stop the fill process and
-           wait in ALSAThread */
+        /* Audio output buffer shortage -> stop the fill process and wait */
         if( p_buffer == NULL )
+        {
+            msleep( p_sys->i_period_time >> 1 );
             return;
+        }
 
         i_snd_rc = snd_pcm_writei( p_sys->p_snd_pcm, p_buffer->p_buffer,
                                    p_buffer->i_nb_samples );
@@ -706,8 +728,5 @@ static void ALSAFill( aout_instance_t * p_aout )
         }
 
         aout_BufferFree( p_buffer );
-
-        msleep( p_sys->i_period_time >> 2 );
     }
 }
-
index 3badf8d..c1204a0 100644 (file)
@@ -2,7 +2,7 @@
  * interface.cpp : wxWindows plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000-2001 VideoLAN
- * $Id: interface.cpp,v 1.43 2003/07/01 13:12:19 sam Exp $
+ * $Id: interface.cpp,v 1.44 2003/07/09 21:42:28 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  *
@@ -706,7 +706,7 @@ void Interface::OnPlayStream( wxCommandEvent& WXUNUSED(event) )
         }
 
         /* Stream is paused, resume it */
-        playlist_Play( p_playlist );
+        input_SetStatus( p_input, INPUT_STATUS_PLAY );
         TogglePlayButton( PLAYING_S );
         vlc_object_release( p_input );
         vlc_object_release( p_playlist );
index 3fcf776..5705dd0 100644 (file)
@@ -2,7 +2,7 @@
  * output.c : internal management of output streams for the audio output
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: output.c,v 1.40 2003/05/11 01:00:26 massiot Exp $
+ * $Id: output.c,v 1.41 2003/07/09 21:42:28 gbazin Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -304,8 +304,13 @@ aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout,
     /* Here we suppose that all buffers have the same duration - this is
      * generally true, and anyway if it's wrong it won't be a disaster. */
     if ( p_buffer->start_date > start_date
-                         + (p_buffer->end_date - p_buffer->start_date)
-                         + AOUT_PTS_TOLERANCE )
+                         + (p_buffer->end_date - p_buffer->start_date) )
+    /*
+     *                   + AOUT_PTS_TOLERANCE )
+     * There is no reason to want that, it just worsen the scheduling of
+     * an audio sample after an output starvation (ie. on start or on resume)
+     * --Gibalou
+     */
     {
         vlc_mutex_unlock( &p_aout->output_fifo_lock );
         if ( !p_aout->output.b_starving )