From 9ad50ca913fc4e951960ec993d0b8dbd0efed6a4 Mon Sep 17 00:00:00 2001 From: Thomas Guillem Date: Wed, 6 Sep 2017 11:23:47 +0200 Subject: [PATCH] coreaudio: fix undefined behavior when flushing Don't consume (calling TPCircularBufferClear()) from the producer thread (ca_Flush()). --- 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 #import #import +#import #import #import @@ -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;