[vlc-devel] [RFC PATCH 1/2] aout: make the play() API non blocking

Thomas Guillem thomas at gllm.fr
Tue Mar 12 18:18:42 CET 2019


TODO: implement it on all modules.
---
 include/vlc_aout.h                      | 33 +++++++++++++++++++++++--
 modules/audio_output/adummy.c           |  3 ++-
 modules/audio_output/alsa.c             |  6 ++---
 modules/audio_output/amem.c             |  3 ++-
 modules/audio_output/audiotrack.c       |  6 ++---
 modules/audio_output/audiounit_ios.m    |  7 ++++--
 modules/audio_output/coreaudio_common.c |  7 +++---
 modules/audio_output/coreaudio_common.h |  2 +-
 modules/audio_output/directsound.c      | 21 ++++++++++------
 modules/audio_output/file.c             |  5 ++--
 modules/audio_output/jack.c             |  5 ++--
 modules/audio_output/kai.c              |  5 ++--
 modules/audio_output/mmdevice.c         |  5 ++--
 modules/audio_output/mmdevice.h         |  5 ++--
 modules/audio_output/opensles_android.c |  3 ++-
 modules/audio_output/oss.c              |  5 ++--
 modules/audio_output/pulse.c            |  3 ++-
 modules/audio_output/sndio.c            |  5 ++--
 modules/audio_output/wasapi.c           |  5 ++--
 modules/audio_output/waveout.c          |  7 +++---
 modules/audio_output/winstore.c         |  6 +++--
 src/audio_output/aout_internal.h        |  1 +
 src/audio_output/dec.c                  | 27 +++++++++++++++++++-
 src/audio_output/output.c               |  1 +
 24 files changed, 128 insertions(+), 48 deletions(-)

diff --git a/include/vlc_aout.h b/include/vlc_aout.h
index 4441a42a82..770c2b7025 100644
--- a/include/vlc_aout.h
+++ b/include/vlc_aout.h
@@ -112,6 +112,7 @@
 #include <vlc_block.h>
 
 struct vlc_audio_output_events {
+    void (*more_data_report)(audio_output_t *);
     void (*drained_report)(audio_output_t *);
     void (*timing_report)(audio_output_t *, vlc_tick_t system_now, vlc_tick_t pts);
     void (*volume_report)(audio_output_t *, float);
@@ -123,6 +124,7 @@ struct vlc_audio_output_events {
     int (*gain_request)(audio_output_t *, float);
 };
 
+
 /** Audio output object
  *
  * The audio output object is the abstraction for rendering decoded
@@ -187,11 +189,27 @@ struct audio_output
       * \note This callback cannot be called in stopped state.
       */
 
-    void (*play)(audio_output_t *, block_t *block, vlc_tick_t date);
+#define AOUT_PLAY_WAIT_REPORT (-1)
+#define AOUT_PLAY_DONE (0)
+    vlc_tick_t (*play)(audio_output_t *, block_t *block, vlc_tick_t date);
     /**< Queues a block of samples for playback (mandatory, cannot be NULL).
       *
-      * \param block block of audio samples
+      * As the play implementation must be non-blocking, the implementation is
+      * allowed to return prematurely if is internal buffer is full. In that
+      * case, the implementation must modify the block offset since the same
+      * block will be given in a successive call and return one of the 3
+      * possibles values:
+      * AOUT_PLAY_DONE: the block is fully written
+      * AOUT_PLAY_WAIT_REPORT: aout_MoreDataReport() must be called
+      * asynchronously from the implementation to notify the core that new data
+      * can be written.
+      * > 0: The core will wait for that positive delay before calling play()
+      * again.
+      *
+      * \param block block of audio samples, must be released when returning
+      * AOUT_PLAY_DONE
       * \param date intended system time to render the first sample
+      * \return AOUT_PLAY_WAIT_REPORT, AOUT_PLAY_DONE or a positive delay
       *
       * \note This callback cannot be called in stopped state.
       */
@@ -460,6 +478,17 @@ static inline void aout_DrainedReport(audio_output_t *aout)
     aout->events->drained_report(aout);
 }
 
+/**
+ * Report that more data can be played
+ *
+ * This function can only be called after aout->play() returned
+ * AOUT_PLAY_WAIT_REPORT.
+ */
+static inline void aout_MoreDataReport(audio_output_t *aout)
+{
+    aout->events->more_data_report(aout);
+}
+
 /**
  * Default implementation for audio_output_t.time_get
  */
diff --git a/modules/audio_output/adummy.c b/modules/audio_output/adummy.c
index e81a9cb0c8..c410a295f4 100644
--- a/modules/audio_output/adummy.c
+++ b/modules/audio_output/adummy.c
@@ -41,10 +41,11 @@ vlc_module_end ()
 
 #define A52_FRAME_NB 1536
 
-static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
+static vlc_tick_t Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
 {
     block_Release( block );
     (void) aout; (void) date;
+    return AOUT_PLAY_DONE;
 }
 
 static void Pause(audio_output_t *aout, bool paused, vlc_tick_t date)
diff --git a/modules/audio_output/alsa.c b/modules/audio_output/alsa.c
index cdbfd44d41..5d30d05af9 100644
--- a/modules/audio_output/alsa.c
+++ b/modules/audio_output/alsa.c
@@ -291,7 +291,7 @@ out:
 #endif
 
 static int TimeGet (audio_output_t *aout, vlc_tick_t *);
-static void Play(audio_output_t *, block_t *, vlc_tick_t);
+static vlc_tick_t 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 *);
@@ -647,7 +647,7 @@ static int TimeGet (audio_output_t *aout, vlc_tick_t *restrict delay)
 /**
  * Queues one audio buffer to the hardware.
  */
-static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
+static vlc_tick_t Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
 {
     aout_sys_t *sys = aout->sys;
 
@@ -687,7 +687,7 @@ static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
         }
     }
     block_Release (block);
-    (void) date;
+    return AOUT_PLAY_DONE;
 }
 
 /**
diff --git a/modules/audio_output/amem.c b/modules/audio_output/amem.c
index f859a4b10a..036818769d 100644
--- a/modules/audio_output/amem.c
+++ b/modules/audio_output/amem.c
@@ -81,7 +81,7 @@ typedef struct
     vlc_mutex_t lock;
 } aout_sys_t;
 
-static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
+static vlc_tick_t Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
 {
     aout_sys_t *sys = aout->sys;
 
@@ -89,6 +89,7 @@ static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
     sys->play(sys->opaque, block->p_buffer, block->i_nb_samples, date);
     vlc_mutex_unlock(&sys->lock);
     block_Release (block);
+    return AOUT_PLAY_DONE;
 }
 
 static void Pause (audio_output_t *aout, bool paused, vlc_tick_t date)
diff --git a/modules/audio_output/audiotrack.c b/modules/audio_output/audiotrack.c
index 1d39852343..0bb5e3e9fd 100644
--- a/modules/audio_output/audiotrack.c
+++ b/modules/audio_output/audiotrack.c
@@ -1923,7 +1923,7 @@ ConvertFromIEC61937( audio_output_t *p_aout, block_t *p_buffer )
     return 0;
 }
 
-static void
+static vlc_tick_t
 Play( audio_output_t *p_aout, block_t *p_buffer, vlc_tick_t i_date )
 {
     JNIEnv *env = NULL;
@@ -1934,7 +1934,7 @@ Play( audio_output_t *p_aout, block_t *p_buffer, vlc_tick_t i_date )
      && ConvertFromIEC61937( p_aout, p_buffer ) != 0 )
     {
         block_Release(p_buffer);
-        return;
+        return AOUT_PLAY_DONE;
     }
 
     vlc_mutex_lock( &p_sys->lock );
@@ -2007,7 +2007,7 @@ Play( audio_output_t *p_aout, block_t *p_buffer, vlc_tick_t i_date )
 bailout:
     vlc_mutex_unlock( &p_sys->lock );
     block_Release( p_buffer );
-    (void) i_date;
+    return AOUT_PLAY_DONE;
 }
 
 static void
diff --git a/modules/audio_output/audiounit_ios.m b/modules/audio_output/audiounit_ios.m
index ea555c0c14..d8590a456e 100644
--- a/modules/audio_output/audiounit_ios.m
+++ b/modules/audio_output/audiounit_ios.m
@@ -428,15 +428,18 @@ MuteSet(audio_output_t *p_aout, bool mute)
     return VLC_SUCCESS;
 }
 
-static void
+static vlc_tick_t
 Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date)
 {
     aout_sys_t * p_sys = p_aout->sys;
 
     if (p_sys->b_muted)
+    {
         block_Release(p_block);
+        return AOUT_PLAY_DONE;
+    }
     else
-        ca_Play(p_aout, p_block, date);
+        return ca_Play(p_aout, p_block, date);
 }
 
 #pragma mark initialization
diff --git a/modules/audio_output/coreaudio_common.c b/modules/audio_output/coreaudio_common.c
index 4a714f5411..7bcccd6c2c 100644
--- a/modules/audio_output/coreaudio_common.c
+++ b/modules/audio_output/coreaudio_common.c
@@ -263,7 +263,7 @@ ca_Pause(audio_output_t * p_aout, bool pause, vlc_tick_t date)
     lock_unlock(p_sys);
 }
 
-void
+vlc_tick_t
 ca_Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date)
 {
     struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys;
@@ -290,7 +290,7 @@ ca_Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date)
             if (!p_new)
             {
                 block_Release(p_block);
-                return;
+                return AOUT_PLAY_DONE;
             }
 
             memcpy(p_new->p_buffer, p_block->p_buffer, i_avalaible_bytes);
@@ -307,7 +307,7 @@ ca_Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date)
             {
                 lock_unlock(p_sys);
                 block_Release(p_block);
-                return;
+                return AOUT_PLAY_DONE;
             }
 
             const vlc_tick_t i_frame_us =
@@ -334,6 +334,7 @@ ca_Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date)
     if (i_underrun_size > 0)
         msg_Warn(p_aout, "underrun of %zu bytes", i_underrun_size);
 
+    return AOUT_PLAY_DONE;
     (void) date;
 }
 
diff --git a/modules/audio_output/coreaudio_common.h b/modules/audio_output/coreaudio_common.h
index a860a9aa51..248c1dee91 100644
--- a/modules/audio_output/coreaudio_common.h
+++ b/modules/audio_output/coreaudio_common.h
@@ -93,7 +93,7 @@ void ca_Flush(audio_output_t *p_aout);
 
 void ca_Pause(audio_output_t * p_aout, bool pause, vlc_tick_t date);
 
-void ca_Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date);
+vlc_tick_t ca_Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date);
 
 int  ca_Initialize(audio_output_t *p_aout, const audio_sample_format_t *fmt,
                    vlc_tick_t i_dev_latency_us);
diff --git a/modules/audio_output/directsound.c b/modules/audio_output/directsound.c
index f93237a93a..3f0dbc8c16 100644
--- a/modules/audio_output/directsound.c
+++ b/modules/audio_output/directsound.c
@@ -267,13 +267,16 @@ static HRESULT FillBuffer( vlc_object_t *obj, aout_stream_sys_t *p_sys,
     return DS_OK;
 }
 
-static HRESULT Play( vlc_object_t *obj, aout_stream_sys_t *sys,
-                     block_t *p_buffer )
+static vlc_tick_t Play( vlc_object_t *obj, aout_stream_sys_t *sys,
+                        block_t *p_buffer, HRESULT *hr )
 {
     HRESULT dsresult;
     dsresult = FillBuffer( obj, sys, p_buffer );
     if( dsresult != DS_OK )
-        return dsresult;
+    {
+        *hr = dsresult;
+        return AOUT_PLAY_DONE;
+    }
 
     /* start playing the buffer */
     dsresult = IDirectSoundBuffer_Play( sys->p_dsbuffer, 0, 0,
@@ -294,18 +297,20 @@ static HRESULT Play( vlc_object_t *obj, aout_stream_sys_t *sys,
         vlc_mutex_unlock( &sys->lock );
 
     }
-    return dsresult;
+    *hr = dsresult;
+    return AOUT_PLAY_DONE;
 }
 
-static HRESULT StreamPlay( aout_stream_t *s, block_t *block )
+static vlc_tick_t StreamPlay( aout_stream_t *s, block_t *block, HRESULT *hr )
 {
-    return Play( VLC_OBJECT(s), s->sys, block );
+    return Play( VLC_OBJECT(s), s->sys, block, hr );
 }
 
-static void OutputPlay( audio_output_t *aout, block_t *block, vlc_tick_t date )
+static vlc_tick_t OutputPlay( audio_output_t *aout, block_t *block, vlc_tick_t date )
 {
     aout_sys_t *sys = aout->sys;
-    Play( VLC_OBJECT(aout), &sys->s, block );
+    HRESULT ignored;
+    return Play( VLC_OBJECT(aout), &sys->s, block, &ignored );
     (void) date;
 }
 
diff --git a/modules/audio_output/file.c b/modules/audio_output/file.c
index 906b228548..28c1866895 100644
--- a/modules/audio_output/file.c
+++ b/modules/audio_output/file.c
@@ -73,7 +73,7 @@ static const int pi_channels_maps[CHANNELS_MAX+1] =
  * Local prototypes.
  *****************************************************************************/
 static int     Open        ( vlc_object_t * );
-static void    Play        ( audio_output_t *, block_t *, vlc_tick_t );
+static vlc_tick_t 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 * );
 
@@ -315,7 +315,7 @@ static void Stop( audio_output_t *p_aout )
 /*****************************************************************************
  * Play: pretend to play a sound
  *****************************************************************************/
-static void Play( audio_output_t * p_aout, block_t *p_buffer, vlc_tick_t date )
+static vlc_tick_t Play( audio_output_t * p_aout, block_t *p_buffer, vlc_tick_t date )
 {
     aout_sys_t *p_sys = p_aout->sys;
     if( fwrite( p_buffer->p_buffer, p_buffer->i_buffer, 1,
@@ -331,6 +331,7 @@ static void Play( audio_output_t * p_aout, block_t *p_buffer, vlc_tick_t date )
     }
 
     block_Release( p_buffer );
+    return AOUT_PLAY_DONE;
     (void) date;
 }
 
diff --git a/modules/audio_output/jack.c b/modules/audio_output/jack.c
index d21150f2a4..c5daab6fe5 100644
--- a/modules/audio_output/jack.c
+++ b/modules/audio_output/jack.c
@@ -69,7 +69,7 @@ typedef struct
  *****************************************************************************/
 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 vlc_tick_t 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 );
 static int  TimeGet      ( audio_output_t *, vlc_tick_t * );
@@ -282,7 +282,7 @@ error_out:
     return status;
 }
 
-static void Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date)
+static vlc_tick_t Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date)
 {
     aout_sys_t *p_sys = p_aout->sys;
     jack_ringbuffer_t *rb = p_sys->p_jack_ringbuffer;
@@ -309,6 +309,7 @@ static void Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date)
     }
 
     block_Release(p_block);
+    return AOUT_PLAY_DONE;
     (void) date;
 }
 
diff --git a/modules/audio_output/kai.c b/modules/audio_output/kai.c
index dd75e367d8..aecc95e42d 100644
--- a/modules/audio_output/kai.c
+++ b/modules/audio_output/kai.c
@@ -72,7 +72,7 @@ typedef struct
  *****************************************************************************/
 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 vlc_tick_t 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 * );
 static int  TimeGet ( audio_output_t *, vlc_tick_t *restrict );
@@ -233,7 +233,7 @@ exit_kai_done :
 /*****************************************************************************
  * Play: play a sound samples buffer
  *****************************************************************************/
-static void Play(audio_output_t *p_aout, block_t *block, vlc_tick_t date)
+static vlc_tick_t Play(audio_output_t *p_aout, block_t *block, vlc_tick_t date)
 {
     aout_sys_t *p_sys = p_aout->sys;
 
@@ -242,6 +242,7 @@ static void Play(audio_output_t *p_aout, block_t *block, vlc_tick_t date)
     WriteBuffer( p_aout, block->p_buffer, block->i_buffer );
 
     block_Release( block );
+    return AOUT_PLAY_DONE;
     (void) date;
 }
 
diff --git a/modules/audio_output/mmdevice.c b/modules/audio_output/mmdevice.c
index 4c79cabf1d..abffe3ddb5 100644
--- a/modules/audio_output/mmdevice.c
+++ b/modules/audio_output/mmdevice.c
@@ -136,16 +136,17 @@ static int TimeGet(audio_output_t *aout, vlc_tick_t *restrict delay)
     return SUCCEEDED(hr) ? 0 : -1;
 }
 
-static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
+static vlc_tick_t Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
 {
     aout_sys_t *sys = aout->sys;
     HRESULT hr;
 
     EnterMTA();
-    hr = aout_stream_Play(sys->stream, block);
+    vlc_tick_t wait = aout_stream_Play(sys->stream, block, &hr);
     LeaveMTA();
 
     vlc_FromHR(aout, hr);
+    return wait;
     (void) date;
 }
 
diff --git a/modules/audio_output/mmdevice.h b/modules/audio_output/mmdevice.h
index 2e131ab01f..5b2e610ea3 100644
--- a/modules/audio_output/mmdevice.h
+++ b/modules/audio_output/mmdevice.h
@@ -67,9 +67,10 @@ static inline HRESULT aout_stream_TimeGet(aout_stream_t *s, vlc_tick_t *delay)
     return (s->time_get)(s, delay);
 }
 
-static inline HRESULT aout_stream_Play(aout_stream_t *s, block_t *block)
+static inline vlc_tick_t aout_stream_Play(aout_stream_t *s, block_t *block,
+                                          HRESULT *hr)
 {
-    return (s->play)(s, block);
+    return (s->play)(s, block, hr);
 }
 
 static inline HRESULT aout_stream_Pause(aout_stream_t *s, bool paused)
diff --git a/modules/audio_output/opensles_android.c b/modules/audio_output/opensles_android.c
index b1c2a0d985..64747c13e1 100644
--- a/modules/audio_output/opensles_android.c
+++ b/modules/audio_output/opensles_android.c
@@ -317,7 +317,7 @@ static int WriteBuffer(audio_output_t *aout)
 /*****************************************************************************
  * Play: play a sound
  *****************************************************************************/
-static void Play(audio_output_t *aout, block_t *p_buffer, vlc_tick_t date)
+static vlc_tick_t Play(audio_output_t *aout, block_t *p_buffer, vlc_tick_t date)
 {
     aout_sys_t *sys = aout->sys;
 
@@ -334,6 +334,7 @@ static void Play(audio_output_t *aout, block_t *p_buffer, vlc_tick_t date)
         ;
 
     vlc_mutex_unlock(&sys->lock);
+    return AOUT_PLAY_DONE;
     (void) date;
 }
 
diff --git a/modules/audio_output/oss.c b/modules/audio_output/oss.c
index 5bada6857d..c5399c7747 100644
--- a/modules/audio_output/oss.c
+++ b/modules/audio_output/oss.c
@@ -88,7 +88,7 @@ vlc_module_begin ()
 vlc_module_end ()
 
 static int TimeGet (audio_output_t *, vlc_tick_t *);
-static void Play(audio_output_t *, block_t *, vlc_tick_t);
+static vlc_tick_t 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 *);
 
@@ -269,7 +269,7 @@ static int TimeGet (audio_output_t *aout, vlc_tick_t *restrict pts)
 /**
  * Queues one audio buffer to the hardware.
  */
-static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
+static vlc_tick_t Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
 {
     aout_sys_t *sys = aout->sys;
     int fd = sys->fd;
@@ -286,6 +286,7 @@ static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
             msg_Err (aout, "cannot write samples: %s", vlc_strerror_c(errno));
     }
     block_Release (block);
+    return AOUT_PLAY_DONE;
     (void) date;
 }
 
diff --git a/modules/audio_output/pulse.c b/modules/audio_output/pulse.c
index 4ec20cfdd5..f51d521952 100644
--- a/modules/audio_output/pulse.c
+++ b/modules/audio_output/pulse.c
@@ -461,7 +461,7 @@ static int TimeGet(audio_output_t *aout, vlc_tick_t *restrict delay)
 /**
  * Queue one audio frame to the playback stream
  */
-static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
+static vlc_tick_t Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
 {
     aout_sys_t *sys = aout->sys;
     pa_stream *s = sys->stream;
@@ -505,6 +505,7 @@ static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
     block_Release(block);
 
     pa_threaded_mainloop_unlock(sys->mainloop);
+    return AOUT_PLAY_DONE;
 }
 
 /**
diff --git a/modules/audio_output/sndio.c b/modules/audio_output/sndio.c
index 642113a487..26b8c989ec 100644
--- a/modules/audio_output/sndio.c
+++ b/modules/audio_output/sndio.c
@@ -44,7 +44,7 @@ vlc_module_begin ()
 vlc_module_end ()
 
 static int TimeGet (audio_output_t *, vlc_tick_t *);
-static void Play(audio_output_t *, block_t *, vlc_tick_t);
+static vlc_tick_t Play(audio_output_t *, block_t *, vlc_tick_t);
 static void Flush (audio_output_t *);
 static int VolumeSet (audio_output_t *, float);
 static int MuteSet (audio_output_t *, bool);
@@ -230,13 +230,14 @@ static int TimeGet (audio_output_t *aout, vlc_tick_t *restrict delay)
     return 0;
 }
 
-static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
+static vlc_tick_t Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
 {
     aout_sys_t *sys = aout->sys;
 
     sio_write (sys->hdl, block->p_buffer, block->i_buffer);
     sys->delay += block->i_nb_samples;
     block_Release (block);
+    return AOUT_PLAY_DONE;
     (void) date;
 }
 
diff --git a/modules/audio_output/wasapi.c b/modules/audio_output/wasapi.c
index 74d5239bd7..470868b9ec 100644
--- a/modules/audio_output/wasapi.c
+++ b/modules/audio_output/wasapi.c
@@ -140,7 +140,7 @@ static HRESULT TimeGet(aout_stream_t *s, vlc_tick_t *restrict delay)
     return hr;
 }
 
-static HRESULT Play(aout_stream_t *s, block_t *block)
+static vlc_tick_t Play(aout_stream_t *s, block_t *block, HRESULT *phr)
 {
     aout_stream_sys_t *sys = s->sys;
     void *pv;
@@ -206,7 +206,8 @@ static HRESULT Play(aout_stream_t *s, block_t *block)
 out:
     block_Release(block);
 
-    return hr;
+    *phr = hr;
+    return AOUT_PLAY_DONE;
 }
 
 static HRESULT Pause(aout_stream_t *s, bool paused)
diff --git a/modules/audio_output/waveout.c b/modules/audio_output/waveout.c
index 495fe519bc..8331f31231 100644
--- a/modules/audio_output/waveout.c
+++ b/modules/audio_output/waveout.c
@@ -48,7 +48,7 @@
  *****************************************************************************/
 static int  Open         ( vlc_object_t * );
 static void Close        ( vlc_object_t * );
-static void Play         ( audio_output_t *, block_t *, vlc_tick_t );
+static vlc_tick_t Play         ( audio_output_t *, block_t *, vlc_tick_t );
 
 /*****************************************************************************
  * notification_thread_t: waveOut event thread
@@ -347,7 +347,7 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
  * This doesn't actually play the buffer. This just stores the buffer so it
  * can be played by the callback thread.
  *****************************************************************************/
-static void Play( audio_output_t *p_aout, block_t *block, vlc_tick_t date )
+static vlc_tick_t Play( audio_output_t *p_aout, block_t *block, vlc_tick_t date )
 {
     aout_sys_t *sys = p_aout->sys;
 
@@ -358,7 +358,7 @@ static void Play( audio_output_t *p_aout, block_t *block, vlc_tick_t date )
         msg_Err(p_aout, "Couldn't alloc WAVEHDR");
         if( block )
             block_Release( block );
-        return;
+        return AOUT_PLAY_DONE;
     }
 
     p_waveheader->p_next = NULL;
@@ -384,6 +384,7 @@ static void Play( audio_output_t *p_aout, block_t *block, vlc_tick_t date )
     sys->i_frames++;
     sys->i_played_length += block->i_length;
     vlc_mutex_unlock( &sys->lock );
+    return AOUT_PLAY_DONE;
     (void) date;
 }
 
diff --git a/modules/audio_output/winstore.c b/modules/audio_output/winstore.c
index 8ad1fa431f..edabb52400 100644
--- a/modules/audio_output/winstore.c
+++ b/modules/audio_output/winstore.c
@@ -150,17 +150,19 @@ static int TimeGet(audio_output_t *aout, vlc_tick_t *restrict delay)
     return SUCCEEDED(hr) ? 0 : -1;
 }
 
-static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
+static vlc_tick_t Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
 {
     aout_sys_t *sys = aout->sys;
     if( unlikely( sys->client == NULL ) )
         return;
 
     EnterMTA();
-    HRESULT hr = aout_stream_Play(sys->stream, block);
+    HRESULT hr;
+    vlc_tick_t wait = aout_stream_Play(sys->stream, block, &hr);
     LeaveMTA();
 
     vlc_FromHR(aout, hr);
+    return wait;
     (void) date;
 }
 
diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h
index 5e37e70f72..2905b46faf 100644
--- a/src/audio_output/aout_internal.h
+++ b/src/audio_output/aout_internal.h
@@ -152,6 +152,7 @@ void aout_RequestRestart (audio_output_t *, unsigned);
 void aout_RequestRetiming(audio_output_t *aout, vlc_tick_t system_ts,
                           vlc_tick_t audio_ts);
 void aout_Drained(audio_output_t *);
+void aout_MoreData(audio_output_t *);
 
 static inline void aout_InputRequestRestart(audio_output_t *aout)
 {
diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c
index 4c24ea307e..88559873ea 100644
--- a/src/audio_output/dec.c
+++ b/src/audio_output/dec.c
@@ -209,9 +209,34 @@ static void aout_StopResampling (audio_output_t *aout)
     aout_FiltersAdjustResampling (owner->filters, 0);
 }
 
+void aout_MoreData(audio_output_t *aout)
+{
+    aout_owner_t *owner = aout_owner (aout);
+
+    assert(atomic_fetch_add(&owner->report_count, 1) == 0);
+    vlc_sem_post(&owner->report_sem);
+}
+
 static void aout_Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
 {
-    aout->play(aout, block, date);
+    aout_owner_t *owner = aout_owner (aout);
+    for (;;)
+    {
+        vlc_tick_t status = aout->play(aout, block, date);
+        switch (status)
+        {
+            case AOUT_PLAY_WAIT_REPORT:
+                vlc_sem_wait(&owner->report_sem);
+                assert(atomic_fetch_sub(&owner->report_count, 1) == 1);
+                break;
+            case AOUT_PLAY_DONE:
+                return;
+            default:
+                assert(status > 0);
+                vlc_tick_sleep(status);
+                break;
+        }
+    }
 }
 
 static void aout_DecSynchronize(audio_output_t *aout, vlc_tick_t system_now,
diff --git a/src/audio_output/output.c b/src/audio_output/output.c
index 6bb54a2012..717bf6b8e5 100644
--- a/src/audio_output/output.c
+++ b/src/audio_output/output.c
@@ -165,6 +165,7 @@ static int aout_GainNotify (audio_output_t *aout, float gain)
 }
 
 static const struct vlc_audio_output_events aout_events = {
+    aout_MoreData,
     aout_Drained,
     aout_TimingNotify,
     aout_VolumeNotify,
-- 
2.20.1



More information about the vlc-devel mailing list