[vlc-commits] coreaudio: fix undefined behavior when flushing

Thomas Guillem git at videolan.org
Wed Sep 6 14:45:18 CEST 2017


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Wed Sep  6 11:23:47 2017 +0200| [9ad50ca913fc4e951960ec993d0b8dbd0efed6a4] | committer: Thomas Guillem

coreaudio: fix undefined behavior when flushing

Don't consume (calling TPCircularBufferClear()) from the producer thread
(ca_Flush()).

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=9ad50ca913fc4e951960ec993d0b8dbd0efed6a4
---

 modules/audio_output/coreaudio_common.c | 17 +++++++++++++++--
 modules/audio_output/coreaudio_common.h |  3 +++
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/modules/audio_output/coreaudio_common.c b/modules/audio_output/coreaudio_common.c
index 3039d452cd..75e12df3bc 100644
--- a/modules/audio_output/coreaudio_common.c
+++ b/modules/audio_output/coreaudio_common.c
@@ -48,6 +48,14 @@ ca_Render(audio_output_t *p_aout, uint8_t *p_output, size_t i_requested)
 {
     struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys;
 
+    bool expected = true;
+    if (atomic_compare_exchange_weak(&p_sys->b_do_flush, &expected, false))
+    {
+        TPCircularBufferClear(&p_sys->circular_buffer);
+        /* Signal that the renderer is flushed */
+        vlc_sem_post(&p_sys->flush_sem);
+    }
+
     if (atomic_load_explicit(&p_sys->b_paused, memory_order_relaxed))
     {
         memset(p_output, 0, i_requested);
@@ -112,8 +120,10 @@ ca_Flush(audio_output_t *p_aout, bool wait)
     }
     else
     {
-        /* flush circular buffer if data is left */
-        TPCircularBufferClear(&p_sys->circular_buffer);
+        /* Request the renderer to flush, and wait for an ACK */
+        assert(!atomic_load(&p_sys->b_do_flush));
+        atomic_store_explicit(&p_sys->b_do_flush, true, memory_order_release);
+        vlc_sem_wait(&p_sys->flush_sem);
     }
 }
 
@@ -183,6 +193,8 @@ ca_Initialize(audio_output_t *p_aout, const audio_sample_format_t *fmt,
 
     atomic_init(&p_sys->i_underrun_size, 0);
     atomic_init(&p_sys->b_paused, false);
+    atomic_init(&p_sys->b_do_flush, false);
+    vlc_sem_init(&p_sys->flush_sem, 0);
 
     p_sys->i_rate = fmt->i_rate;
     p_sys->i_bytes_per_frame = fmt->i_bytes_per_frame;
@@ -232,6 +244,7 @@ ca_Uninitialize(audio_output_t *p_aout)
 
     /* clean-up circular buffer */
     TPCircularBufferCleanup(&p_sys->circular_buffer);
+    vlc_sem_destroy(&p_sys->flush_sem);
 }
 
 AudioUnit
diff --git a/modules/audio_output/coreaudio_common.h b/modules/audio_output/coreaudio_common.h
index c6d73ee113..8d0ec10374 100644
--- a/modules/audio_output/coreaudio_common.h
+++ b/modules/audio_output/coreaudio_common.h
@@ -29,6 +29,7 @@
 #import <vlc_common.h>
 #import <vlc_atomic.h>
 #import <vlc_aout.h>
+#import <vlc_threads.h>
 
 #import <AudioUnit/AudioUnit.h>
 #import <AudioToolbox/AudioToolbox.h>
@@ -53,6 +54,8 @@ struct aout_sys_common
     TPCircularBuffer    circular_buffer;
     atomic_uint         i_underrun_size;
     atomic_bool         b_paused;
+    atomic_bool         b_do_flush;
+    vlc_sem_t           flush_sem;
     int                 i_rate;
     unsigned int        i_bytes_per_frame;
     unsigned int        i_frame_length;



More information about the vlc-commits mailing list