[vlc-devel] [PATCH v2 4/7] aout: use a seperate drain callback

Thomas Guillem thomas at gllm.fr
Wed Mar 13 09:55:52 CET 2019


This callback is not mandatory. If it is NULL, the core will wait for the delay
returned by time_get(). This was already the case for most aout plugins:
PulseAudio, coreaudio, Android, DirectSound, Wasapi, and Jack.
---
 include/vlc_aout.h                      | 12 ++++++--
 modules/audio_output/adummy.c           |  4 +--
 modules/audio_output/alsa.c             | 23 +++++++++------
 modules/audio_output/amem.c             | 17 +++++++++---
 modules/audio_output/audiotrack.c       | 25 ++++-------------
 modules/audio_output/audiounit_ios.m    | 13 ++-------
 modules/audio_output/coreaudio_common.c | 37 ++++++-------------------
 modules/audio_output/coreaudio_common.h |  2 +-
 modules/audio_output/directsound.c      | 13 ++-------
 modules/audio_output/file.c             |  5 ++--
 modules/audio_output/jack.c             | 12 ++------
 modules/audio_output/kai.c              | 16 +++--------
 modules/audio_output/mmdevice.c         |  4 +--
 modules/audio_output/mmdevice.h         | 14 ++--------
 modules/audio_output/opensles_android.c | 32 +++++++++------------
 modules/audio_output/oss.c              |  8 ++----
 modules/audio_output/pulse.c            | 35 +++++++++++++----------
 modules/audio_output/sndio.c            |  5 ++--
 modules/audio_output/waveout.c          | 34 +++++++++++------------
 modules/audio_output/winstore.c         |  4 +--
 src/audio_output/dec.c                  | 14 ++++++++--
 21 files changed, 138 insertions(+), 191 deletions(-)

diff --git a/include/vlc_aout.h b/include/vlc_aout.h
index a4ae6bc498..a6b8069151 100644
--- a/include/vlc_aout.h
+++ b/include/vlc_aout.h
@@ -212,14 +212,20 @@ struct audio_output
       * \note This callback cannot be called in stopped state.
       */
 
-    void (*flush)( audio_output_t *, bool wait);
-    /**< Flushes or drains the playback buffers (mandatory, cannot be NULL).
+    void (*flush)( audio_output_t *);
+    /**< Flushes the playback buffers (mandatory, cannot be NULL).
       *
       * \param wait true to wait for playback of pending buffers (drain),
       *             false to discard pending buffers (flush)
       *
       * \note This callback cannot be called in stopped state.
       */
+    void (*drain)(audio_output_t *);
+    /**< Drain the playback buffers (can be NULL).
+      *
+      * If NULL, the caller will wait for the delay returned by time_get before
+      * calling stop().
+      */
 
     int (*volume_set)(audio_output_t *, float volume);
     /**< Changes playback volume (optional, may be NULL).
@@ -456,7 +462,7 @@ static inline void aout_PauseDefault(audio_output_t *aout, bool paused,
                                      vlc_tick_t date)
 {
     if (paused && aout->flush != NULL)
-        aout->flush(aout, false);
+        aout->flush(aout);
     (void) date;
 }
 
diff --git a/modules/audio_output/adummy.c b/modules/audio_output/adummy.c
index d0889b8c08..e81a9cb0c8 100644
--- a/modules/audio_output/adummy.c
+++ b/modules/audio_output/adummy.c
@@ -52,9 +52,9 @@ static void Pause(audio_output_t *aout, bool paused, vlc_tick_t date)
     (void) aout; (void) paused; (void) date;
 }
 
-static void Flush(audio_output_t *aout, bool wait)
+static void Flush(audio_output_t *aout)
 {
-    (void) aout; (void) wait;
+    (void) aout;
 }
 
 static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
diff --git a/modules/audio_output/alsa.c b/modules/audio_output/alsa.c
index e507f78241..a99faed3cb 100644
--- a/modules/audio_output/alsa.c
+++ b/modules/audio_output/alsa.c
@@ -294,7 +294,8 @@ static int TimeGet (audio_output_t *aout, vlc_tick_t *);
 static void Play(audio_output_t *, block_t *, vlc_tick_t);
 static void Pause (audio_output_t *, bool, vlc_tick_t);
 static void PauseDummy (audio_output_t *, bool, vlc_tick_t);
-static void Flush (audio_output_t *, bool);
+static void Flush (audio_output_t *);
+static void Drain (audio_output_t *);
 
 /** Initializes an ALSA playback stream */
 static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
@@ -714,20 +715,25 @@ static void PauseDummy (audio_output_t *aout, bool pause, vlc_tick_t date)
 }
 
 /**
- * Flushes/drains the audio playback buffer.
+ * Flushes the audio playback buffer.
  */
-static void Flush (audio_output_t *aout, bool wait)
+static void Flush (audio_output_t *aout)
 {
     aout_sys_t *p_sys = aout->sys;
     snd_pcm_t *pcm = p_sys->pcm;
-
-    if (wait)
-        snd_pcm_drain (pcm);
-    else
-        snd_pcm_drop (pcm);
+    snd_pcm_drop (pcm);
     snd_pcm_prepare (pcm);
 }
 
+/**
+ * Drains the audio playback buffer.
+ */
+static void Drain (audio_output_t *aout)
+{
+    aout_sys_t *p_sys = aout->sys;
+    snd_pcm_t *pcm = p_sys->pcm;
+    snd_pcm_drain (pcm);
+}
 
 /**
  * Releases the audio output.
@@ -851,6 +857,7 @@ static int Open(vlc_object_t *obj)
     aout->time_get = TimeGet;
     aout->play = Play;
     aout->flush = Flush;
+    aout->drain = Drain;
 
     return VLC_SUCCESS;
 error:
diff --git a/modules/audio_output/amem.c b/modules/audio_output/amem.c
index dcba84c32d..f859a4b10a 100644
--- a/modules/audio_output/amem.c
+++ b/modules/audio_output/amem.c
@@ -104,19 +104,27 @@ static void Pause (audio_output_t *aout, bool paused, vlc_tick_t date)
     }
 }
 
-static void Flush (audio_output_t *aout, bool wait)
+static void Flush (audio_output_t *aout)
 {
     aout_sys_t *sys = aout->sys;
-    void (*cb) (void *) = wait ? sys->drain : sys->flush;
 
-    if (cb != NULL)
+    if (sys->flush != NULL)
     {
         vlc_mutex_lock(&sys->lock);
-        cb (sys->opaque);
+        sys->flush (sys->opaque);
         vlc_mutex_unlock(&sys->lock);
     }
 }
 
+static void Drain (audio_output_t *aout)
+{
+    aout_sys_t *sys = aout->sys;
+
+    vlc_mutex_lock(&sys->lock);
+    sys->drain (sys->opaque);
+    vlc_mutex_unlock(&sys->lock);
+}
+
 static int VolumeSet (audio_output_t *aout, float vol)
 {
     aout_sys_t *sys = aout->sys;
@@ -313,6 +321,7 @@ static int Open (vlc_object_t *obj)
     aout->play = Play;
     aout->pause = Pause;
     aout->flush = Flush;
+    aout->drain = sys->drain ? Drain : NULL;
     if (sys->set_volume != NULL)
     {
         aout->volume_set = VolumeSet;
diff --git a/modules/audio_output/audiotrack.c b/modules/audio_output/audiotrack.c
index 2dcababe47..1d39852343 100644
--- a/modules/audio_output/audiotrack.c
+++ b/modules/audio_output/audiotrack.c
@@ -2040,7 +2040,7 @@ bailout:
 }
 
 static void
-Flush( audio_output_t *p_aout, bool b_wait )
+Flush( audio_output_t *p_aout )
 {
     aout_sys_t *p_sys = p_aout->sys;
     JNIEnv *env;
@@ -2061,25 +2061,10 @@ Flush( audio_output_t *p_aout, bool b_wait )
      * that has not been played back will be discarded.  No-op if not stopped
      * or paused, or if the track's creation mode is not MODE_STREAM.
      */
-    if( b_wait )
-    {
-        /* Wait for the thread to process the circular buffer */
-        while( !p_sys->b_error
-            && p_sys->circular.i_read != p_sys->circular.i_write )
-            vlc_cond_wait( &p_sys->aout_cond, &p_sys->lock );
-        if( p_sys->b_error )
-            goto bailout;
-
-        JNI_AT_CALL_VOID( stop );
-        if( CHECK_AT_EXCEPTION( "stop" ) )
-            goto bailout;
-    } else
-    {
-        JNI_AT_CALL_VOID( pause );
-        if( CHECK_AT_EXCEPTION( "pause" ) )
-            goto bailout;
-        JNI_AT_CALL_VOID( flush );
-    }
+    JNI_AT_CALL_VOID( pause );
+    if( CHECK_AT_EXCEPTION( "pause" ) )
+        goto bailout;
+    JNI_AT_CALL_VOID( flush );
     p_sys->circular.i_read = p_sys->circular.i_write = 0;
 
     /* HACK: Before Android 4.4, the head position is not reset to zero and is
diff --git a/modules/audio_output/audiounit_ios.m b/modules/audio_output/audiounit_ios.m
index e449f6e2eb..ea555c0c14 100644
--- a/modules/audio_output/audiounit_ios.m
+++ b/modules/audio_output/audiounit_ios.m
@@ -409,15 +409,7 @@ Pause (audio_output_t *p_aout, bool pause, vlc_tick_t date)
      * that we loose 1-2 sec of audio when resuming. The order is important
      * here, ca_Flush need to be called when paused. */
     if (pause)
-        ca_Flush(p_aout, false);
-}
-
-static void
-Flush(audio_output_t *p_aout, bool wait)
-{
-    aout_sys_t * p_sys = p_aout->sys;
-
-    ca_Flush(p_aout, wait);
+        ca_Flush(p_aout);
 }
 
 static int
@@ -430,7 +422,7 @@ MuteSet(audio_output_t *p_aout, bool mute)
     {
         Pause(p_aout, mute, 0);
         if (mute)
-            ca_Flush(p_aout, false);
+            ca_Flush(p_aout);
     }
 
     return VLC_SUCCESS;
@@ -562,7 +554,6 @@ Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
     fmt->channel_type = AUDIO_CHANNEL_TYPE_BITMAP;
     p_aout->mute_set  = MuteSet;
     p_aout->pause = Pause;
-    p_aout->flush = Flush;
 
     aout_SoftVolumeStart( p_aout );
 
diff --git a/modules/audio_output/coreaudio_common.c b/modules/audio_output/coreaudio_common.c
index d790daf1cb..4a714f5411 100644
--- a/modules/audio_output/coreaudio_common.c
+++ b/modules/audio_output/coreaudio_common.c
@@ -230,42 +230,21 @@ ca_TimeGet(audio_output_t *p_aout, vlc_tick_t *delay)
 }
 
 void
-ca_Flush(audio_output_t *p_aout, bool wait)
+ca_Flush(audio_output_t *p_aout)
 {
     struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys;
 
     lock_lock(p_sys);
-    if (wait)
-    {
-        while (p_sys->i_out_size > 0)
-        {
-            if (p_sys->b_paused)
-            {
-                ca_ClearOutBuffers(p_aout);
-                break;
-            }
 
-            /* Calculate the duration of the circular buffer, in order to wait
-             * for the render thread to play it all */
-            const vlc_tick_t i_frame_us =
-                FramesToUs(p_sys, BytesToFrames(p_sys, p_sys->i_out_size)) + VLC_TICK_FROM_MS(10);
-            lock_unlock(p_sys);
-            vlc_tick_sleep(i_frame_us);
-            lock_lock(p_sys);
-        }
-    }
+    assert(!p_sys->b_do_flush);
+    if (p_sys->b_paused)
+        ca_ClearOutBuffers(p_aout);
     else
     {
-        assert(!p_sys->b_do_flush);
-        if (p_sys->b_paused)
-            ca_ClearOutBuffers(p_aout);
-        else
-        {
-            p_sys->b_do_flush = true;
-            lock_unlock(p_sys);
-            vlc_sem_wait(&p_sys->flush_sem);
-            lock_lock(p_sys);
-        }
+        p_sys->b_do_flush = true;
+        lock_unlock(p_sys);
+        vlc_sem_wait(&p_sys->flush_sem);
+        lock_lock(p_sys);
     }
 
     p_sys->i_render_host_time = 0;
diff --git a/modules/audio_output/coreaudio_common.h b/modules/audio_output/coreaudio_common.h
index ead0c34e9e..a860a9aa51 100644
--- a/modules/audio_output/coreaudio_common.h
+++ b/modules/audio_output/coreaudio_common.h
@@ -89,7 +89,7 @@ void ca_Render(audio_output_t *p_aout, uint32_t i_nb_samples, uint64_t i_host_ti
 
 int  ca_TimeGet(audio_output_t *p_aout, vlc_tick_t *delay);
 
-void ca_Flush(audio_output_t *p_aout, bool wait);
+void ca_Flush(audio_output_t *p_aout);
 
 void ca_Pause(audio_output_t * p_aout, bool pause, vlc_tick_t date);
 
diff --git a/modules/audio_output/directsound.c b/modules/audio_output/directsound.c
index fb4fe75e32..f93237a93a 100644
--- a/modules/audio_output/directsound.c
+++ b/modules/audio_output/directsound.c
@@ -360,19 +360,10 @@ static HRESULT StreamFlush( aout_stream_t *s )
     return Flush( s->sys );
 }
 
-static void OutputFlush( audio_output_t *aout, bool drain )
+static void OutputFlush( audio_output_t *aout )
 {
     aout_sys_t *sys = aout->sys;
-    if (drain)
-    {   /* Loosy drain emulation */
-        vlc_tick_t delay;
-
-        if( OutputTimeGet( aout, &delay ) == 0 &&
-            delay <= VLC_TICK_FROM_SEC( 5 ) )
-            Sleep( MS_FROM_VLC_TICK( delay ) + 1 );
-    }
-    else
-        Flush( &sys->s );
+    Flush( &sys->s );
 }
 
 /**
diff --git a/modules/audio_output/file.c b/modules/audio_output/file.c
index fbdf35fcb1..906b228548 100644
--- a/modules/audio_output/file.c
+++ b/modules/audio_output/file.c
@@ -75,7 +75,7 @@ static const int pi_channels_maps[CHANNELS_MAX+1] =
 static int     Open        ( vlc_object_t * );
 static void    Play        ( audio_output_t *, block_t *, vlc_tick_t );
 static void    Pause       ( audio_output_t *, bool, vlc_tick_t );
-static void    Flush       ( audio_output_t *, bool );
+static void    Flush       ( audio_output_t * );
 
 /*****************************************************************************
  * Module descriptor
@@ -339,12 +339,11 @@ static void Pause( audio_output_t *aout, bool paused, vlc_tick_t date )
     (void) aout; (void) paused; (void) date;
 }
 
-static void Flush( audio_output_t *aout, bool wait )
+static void Flush( audio_output_t *aout )
 {
     aout_sys_t *p_sys = aout->sys;
     if( fflush( p_sys->p_file ) )
         msg_Err( aout, "flush error: %s", vlc_strerror_c(errno) );
-    (void) wait;
 }
 
 static int Open(vlc_object_t *obj)
diff --git a/modules/audio_output/jack.c b/modules/audio_output/jack.c
index 59ad013b2f..d21150f2a4 100644
--- a/modules/audio_output/jack.c
+++ b/modules/audio_output/jack.c
@@ -71,7 +71,7 @@ static int  Open         ( vlc_object_t * );
 static void Close        ( vlc_object_t * );
 static void Play         ( audio_output_t * p_aout, block_t *, vlc_tick_t );
 static void Pause        ( audio_output_t *aout, bool paused, vlc_tick_t date );
-static void Flush        ( audio_output_t *p_aout, bool wait );
+static void Flush        ( audio_output_t *p_aout );
 static int  TimeGet      ( audio_output_t *, vlc_tick_t * );
 static int  Process      ( jack_nframes_t i_frames, void *p_arg );
 static int  GraphChange  ( void *p_arg );
@@ -328,19 +328,11 @@ static void Pause(audio_output_t *aout, bool paused, vlc_tick_t date)
     }
 }
 
-static void Flush(audio_output_t *p_aout, bool wait)
+static void Flush(audio_output_t *p_aout)
 {
     aout_sys_t * p_sys = p_aout->sys;
     jack_ringbuffer_t *rb = p_sys->p_jack_ringbuffer;
 
-    /* Sleep if wait was requested */
-    if( wait )
-    {
-        vlc_tick_t delay;
-        if (!TimeGet(p_aout, &delay))
-            vlc_tick_sleep(delay);
-    }
-
     /* reset ringbuffer read and write pointers */
     jack_ringbuffer_reset(rb);
 }
diff --git a/modules/audio_output/kai.c b/modules/audio_output/kai.c
index 98a2182394..dd75e367d8 100644
--- a/modules/audio_output/kai.c
+++ b/modules/audio_output/kai.c
@@ -74,7 +74,7 @@ static int  Open    ( vlc_object_t * );
 static void Close   ( vlc_object_t * );
 static void Play    ( audio_output_t *_p_aout, block_t *block, vlc_tick_t );
 static void Pause   ( audio_output_t *, bool, vlc_tick_t );
-static void Flush   ( audio_output_t *, bool );
+static void Flush   ( audio_output_t * );
 static int  TimeGet ( audio_output_t *, vlc_tick_t *restrict );
 
 static ULONG APIENTRY KaiCallback ( PVOID, PVOID, ULONG );
@@ -310,23 +310,15 @@ static void Pause( audio_output_t *aout, bool pause, vlc_tick_t date )
         kaiResume( sys->hkai );
 }
 
-static void Flush( audio_output_t *aout, bool drain )
+static void Flush( audio_output_t *aout )
 {
     aout_sys_t     *sys = aout->sys;
     audio_buffer_t *buffer = sys->buffer;
 
     vlc_mutex_lock( &buffer->mutex );
 
-    if( drain )
-    {
-        while( buffer->length > 0 )
-            vlc_cond_wait( &buffer->cond, &buffer->mutex );
-    }
-    else
-    {
-        buffer->read_pos = buffer->write_pos;
-        buffer->length   = 0;
-    }
+    buffer->read_pos = buffer->write_pos;
+    buffer->length   = 0;
 
     vlc_mutex_unlock( &buffer->mutex );
 }
diff --git a/modules/audio_output/mmdevice.c b/modules/audio_output/mmdevice.c
index 162c8350b7..4c79cabf1d 100644
--- a/modules/audio_output/mmdevice.c
+++ b/modules/audio_output/mmdevice.c
@@ -162,13 +162,13 @@ static void Pause(audio_output_t *aout, bool paused, vlc_tick_t date)
     (void) date;
 }
 
-static void Flush(audio_output_t *aout, bool wait)
+static void Flush(audio_output_t *aout)
 {
     aout_sys_t *sys = aout->sys;
     HRESULT hr;
 
     EnterMTA();
-    hr = aout_stream_Flush(sys->stream, wait);
+    hr = aout_stream_Flush(sys->stream);
     LeaveMTA();
 
     vlc_FromHR(aout, hr);
diff --git a/modules/audio_output/mmdevice.h b/modules/audio_output/mmdevice.h
index d671f450d3..2e131ab01f 100644
--- a/modules/audio_output/mmdevice.h
+++ b/modules/audio_output/mmdevice.h
@@ -77,19 +77,9 @@ static inline HRESULT aout_stream_Pause(aout_stream_t *s, bool paused)
     return (s->pause)(s, paused);
 }
 
-static inline HRESULT aout_stream_Flush(aout_stream_t *s, bool wait)
+static inline HRESULT aout_stream_Flush(aout_stream_t *s)
 {
-    if (wait)
-    {   /* Loosy drain emulation */
-        vlc_tick_t delay;
-
-        if (SUCCEEDED(aout_stream_TimeGet(s, &delay)) &&
-            delay <= VLC_TICK_FROM_SEC(5))
-            Sleep(MS_FROM_VLC_TICK( delay ) + 1);
-        return S_OK;
-    }
-    else
-        return (s->flush)(s);
+    return (s->flush)(s);
 }
 
 static inline
diff --git a/modules/audio_output/opensles_android.c b/modules/audio_output/opensles_android.c
index f0d7360397..b1c2a0d985 100644
--- a/modules/audio_output/opensles_android.c
+++ b/modules/audio_output/opensles_android.c
@@ -177,30 +177,24 @@ static int TimeGet(audio_output_t* aout, vlc_tick_t* restrict drift)
     return 0;
 }
 
-static void Flush(audio_output_t *aout, bool drain)
+static void Flush(audio_output_t *aout)
 {
     aout_sys_t *sys = aout->sys;
 
-    if (drain) {
-        vlc_tick_t delay;
-        if (!TimeGet(aout, &delay))
-            vlc_tick_sleep(delay);
-    } else {
-        vlc_mutex_lock(&sys->lock);
-        SetPlayState(sys->playerPlay, SL_PLAYSTATE_STOPPED);
-        Clear(sys->playerBufferQueue);
-        SetPlayState(sys->playerPlay, SL_PLAYSTATE_PLAYING);
-
-        /* release audio data not yet written to opensles */
-        block_ChainRelease(sys->p_buffer_chain);
-        sys->p_buffer_chain = NULL;
-        sys->pp_buffer_last = &sys->p_buffer_chain;
+    vlc_mutex_lock(&sys->lock);
+    SetPlayState(sys->playerPlay, SL_PLAYSTATE_STOPPED);
+    Clear(sys->playerBufferQueue);
+    SetPlayState(sys->playerPlay, SL_PLAYSTATE_PLAYING);
 
-        sys->samples = 0;
-        sys->started = false;
+    /* release audio data not yet written to opensles */
+    block_ChainRelease(sys->p_buffer_chain);
+    sys->p_buffer_chain = NULL;
+    sys->pp_buffer_last = &sys->p_buffer_chain;
 
-        vlc_mutex_unlock(&sys->lock);
-    }
+    sys->samples = 0;
+    sys->started = false;
+
+    vlc_mutex_unlock(&sys->lock);
 }
 
 static int VolumeSet(audio_output_t *aout, float vol)
diff --git a/modules/audio_output/oss.c b/modules/audio_output/oss.c
index 5e16255798..5bada6857d 100644
--- a/modules/audio_output/oss.c
+++ b/modules/audio_output/oss.c
@@ -90,7 +90,7 @@ vlc_module_end ()
 static int TimeGet (audio_output_t *, vlc_tick_t *);
 static void Play(audio_output_t *, block_t *, vlc_tick_t);
 static void Pause (audio_output_t *, bool, vlc_tick_t);
-static void Flush (audio_output_t *, bool);
+static void Flush (audio_output_t *);
 
 static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
 {
@@ -302,15 +302,13 @@ static void Pause (audio_output_t *aout, bool pause, vlc_tick_t date)
 }
 
 /**
- * Flushes/drains the audio playback buffer.
+ * Flushes the audio playback buffer.
  */
-static void Flush (audio_output_t *aout, bool wait)
+static void Flush (audio_output_t *aout)
 {
     aout_sys_t *sys = aout->sys;
     int fd = sys->fd;
 
-    if (wait)
-        return; /* drain is implicit with OSS */
     ioctl (fd, SNDCTL_DSP_HALT, NULL);
 }
 
diff --git a/modules/audio_output/pulse.c b/modules/audio_output/pulse.c
index a76fd6c657..cc4af1e8c0 100644
--- a/modules/audio_output/pulse.c
+++ b/modules/audio_output/pulse.c
@@ -533,26 +533,14 @@ static void Pause(audio_output_t *aout, bool paused, vlc_tick_t date)
 /**
  * Flush or drain the playback stream
  */
-static void Flush(audio_output_t *aout, bool wait)
+static void Flush(audio_output_t *aout)
 {
     aout_sys_t *sys = aout->sys;
     pa_stream *s = sys->stream;
-    pa_operation *op;
 
     pa_threaded_mainloop_lock(sys->mainloop);
 
-    if (wait)
-    {
-        op = pa_stream_drain(s, NULL, NULL);
-
-        /* XXX: Loosy drain emulation.
-         * See #18141: drain callback is never received */
-        vlc_tick_t delay;
-        if (TimeGet(aout, &delay) == 0 && delay <= VLC_TICK_FROM_SEC(5))
-            vlc_tick_sleep(delay);
-    }
-    else
-        op = pa_stream_flush(s, NULL, NULL);
+    pa_operation *op = pa_stream_flush(s, NULL, NULL);
     if (op != NULL)
         pa_operation_unref(op);
     sys->last_date = VLC_TICK_INVALID;
@@ -561,6 +549,24 @@ static void Flush(audio_output_t *aout, bool wait)
     pa_threaded_mainloop_unlock(sys->mainloop);
 }
 
+static void Drain(audio_output_t *aout)
+{
+    aout_sys_t *sys = aout->sys;
+    pa_stream *s = sys->stream;
+
+    pa_threaded_mainloop_lock(sys->mainloop);
+    pa_operation *op = pa_stream_drain(s, NULL, NULL);
+    if (op != NULL)
+        pa_operation_unref(op);
+    pa_threaded_mainloop_unlock(sys->mainloop);
+
+    /* XXX: Loosy drain emulation.
+     * See #18141: drain callback is never received */
+    vlc_tick_t delay;
+    if (TimeGet(aout, &delay) == 0 && delay <= VLC_TICK_FROM_SEC(5))
+        vlc_tick_sleep(delay);
+}
+
 static int VolumeSet(audio_output_t *aout, float vol)
 {
     aout_sys_t *sys = aout->sys;
@@ -1006,6 +1012,7 @@ static int Open(vlc_object_t *obj)
     aout->play = Play;
     aout->pause = Pause;
     aout->flush = Flush;
+    aout->drain = Drain;
     aout->volume_set = VolumeSet;
     aout->mute_set = MuteSet;
     aout->device_select = StreamMove;
diff --git a/modules/audio_output/sndio.c b/modules/audio_output/sndio.c
index 6b28772817..642113a487 100644
--- a/modules/audio_output/sndio.c
+++ b/modules/audio_output/sndio.c
@@ -45,7 +45,7 @@ vlc_module_end ()
 
 static int TimeGet (audio_output_t *, vlc_tick_t *);
 static void Play(audio_output_t *, block_t *, vlc_tick_t);
-static void Flush (audio_output_t *, bool);
+static void Flush (audio_output_t *);
 static int VolumeSet (audio_output_t *, float);
 static int MuteSet (audio_output_t *, bool);
 static void VolumeChanged (void *, unsigned);
@@ -240,7 +240,7 @@ static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
     (void) date;
 }
 
-static void Flush (audio_output_t *aout, bool wait)
+static void Flush (audio_output_t *aout)
 {
     aout_sys_t *sys = aout->sys;
 
@@ -248,7 +248,6 @@ static void Flush (audio_output_t *aout, bool wait)
     sys->started = 0;
     sys->delay = 0;
     sio_start (sys->hdl);
-    (void)wait;
 }
 
 static void VolumeChanged (void *arg, unsigned volume)
diff --git a/modules/audio_output/waveout.c b/modules/audio_output/waveout.c
index b9be127bb6..3c9884ce01 100644
--- a/modules/audio_output/waveout.c
+++ b/modules/audio_output/waveout.c
@@ -79,7 +79,8 @@ static void WaveOutClearBuffer( HWAVEOUT, WAVEHDR *);
 static int ReloadWaveoutDevices( const char *, char ***, char *** );
 static uint32_t findDeviceID(char *);
 static int WaveOutTimeGet(audio_output_t * , vlc_tick_t *);
-static void WaveOutFlush( audio_output_t *, bool);
+static void WaveOutFlush( audio_output_t *);
+static void WaveOutDrain( audio_output_t *);
 static void WaveOutPause( audio_output_t *, bool, vlc_tick_t);
 static int WaveoutVolumeSet(audio_output_t * p_aout, float volume);
 static int WaveoutMuteSet(audio_output_t * p_aout, bool mute);
@@ -177,6 +178,7 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
     p_aout->play = Play;
     p_aout->pause = WaveOutPause;
     p_aout->flush = WaveOutFlush;
+    p_aout->drain = WaveOutDrain;
 
     aout_sys_t *sys = p_aout->sys;
 
@@ -393,7 +395,7 @@ static void Stop( audio_output_t *p_aout )
     MMRESULT result = waveOutReset( p_sys->h_waveout );
 
     /* wait for the frames to be queued in cleaning list */
-    WaveOutFlush( p_aout, true );
+    WaveOutDrain( p_aout );
     WaveOutClean( p_sys );
 
     /* now we can Close the device */
@@ -848,27 +850,25 @@ static int WaveOutTimeGet(audio_output_t * p_aout, vlc_tick_t *delay)
     return 0;
 }
 
-static void WaveOutFlush( audio_output_t *p_aout, bool wait)
+static void WaveOutFlush( audio_output_t *p_aout)
 {
     MMRESULT res;
     aout_sys_t *sys = p_aout->sys;
 
-    if( !wait )
-    {
-        res  = waveOutReset( sys->h_waveout );
-        sys->i_played_length = 0;
-        if( res != MMSYSERR_NOERROR )
-            msg_Err( p_aout, "waveOutReset failed");
-    }
-    else
+    res  = waveOutReset( sys->h_waveout );
+    sys->i_played_length = 0;
+    if( res != MMSYSERR_NOERROR )
+        msg_Err( p_aout, "waveOutReset failed");
+}
+
+static void WaveOutDrain( audio_output_t *p_aout)
+{
+    vlc_mutex_lock( &sys->lock );
+    while( sys->i_frames )
     {
-        vlc_mutex_lock( &sys->lock );
-        while( sys->i_frames )
-        {
-            vlc_cond_wait( &sys->cond, &sys->lock );
-        }
-        vlc_mutex_unlock( &sys->lock );
+        vlc_cond_wait( &sys->cond, &sys->lock );
     }
+    vlc_mutex_unlock( &sys->lock );
 }
 
 static void WaveOutPause( audio_output_t * p_aout, bool pause, vlc_tick_t date)
diff --git a/modules/audio_output/winstore.c b/modules/audio_output/winstore.c
index 5205c9e5a4..8ad1fa431f 100644
--- a/modules/audio_output/winstore.c
+++ b/modules/audio_output/winstore.c
@@ -178,14 +178,14 @@ static void Pause(audio_output_t *aout, bool paused, vlc_tick_t date)
     vlc_FromHR(aout, hr);
 }
 
-static void Flush(audio_output_t *aout, bool wait)
+static void Flush(audio_output_t *aout)
 {
     aout_sys_t *sys = aout->sys;
     if( unlikely( sys->client == NULL ) )
         return;
 
     EnterMTA();
-    HRESULT hr = aout_stream_Flush(sys->stream, wait);
+    HRESULT hr = aout_stream_Flush(sys->stream);
     LeaveMTA();
 
     vlc_FromHR(aout, hr);
diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c
index 638ff78e48..73c473bc97 100644
--- a/src/audio_output/dec.c
+++ b/src/audio_output/dec.c
@@ -480,7 +480,7 @@ void aout_DecChangePause (audio_output_t *aout, bool paused, vlc_tick_t date)
         if (aout->pause != NULL)
             aout->pause(aout, paused, date);
         else if (paused)
-            aout->flush(aout, false);
+            aout->flush(aout);
     }
 }
 
@@ -506,7 +506,7 @@ void aout_DecFlush(audio_output_t *aout)
     {
         aout_FiltersFlush (owner->filters);
 
-        aout->flush(aout, false);
+        aout->flush(aout);
         vlc_clock_Reset(owner->sync.clock);
         aout_FiltersResetClock(owner->filters);
 
@@ -538,7 +538,15 @@ void aout_DecDrain(audio_output_t *aout)
     block_t *block = aout_FiltersDrain (owner->filters);
     if (block)
         aout->play(aout, block, vlc_tick_now());
-    aout->flush(aout, true);
+
+    if (aout->drain)
+        aout->drain(aout);
+    else
+    {
+        vlc_tick_t delay;
+        if (aout->time_get(aout, &delay) == 0)
+            vlc_tick_sleep(delay);
+    }
 
     vlc_clock_Reset(owner->sync.clock);
     aout_FiltersResetClock(owner->filters);
-- 
2.20.1



More information about the vlc-devel mailing list