[vlc-commits] coreaudio: disable resampling when latency is too high

Thomas Guillem git at videolan.org
Mon Mar 12 17:58:34 CET 2018


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Mon Mar 12 16:06:48 2018 +0100| [f18fef325af25113875b09c8f727017febc6198a] | committer: Thomas Guillem

coreaudio: disable resampling when latency is too high

On iOS, the render callback is called by default with 1024 frames, and 4096
when the screen is OFF. 4096 frames @ 44.1Hhz is around 88ms, which is higher
than AOUT_MAX_PTS_DELAY (60ms). This caused the resampler to be started/stopped
very often when the screen was OFF due to the imprecision of 88ms from the
TimeGet callback.

To fix this issue, this commit disable the TimeGet callback when the latency is
too high.

This will also save some CPU time by disabling any synchronisation when the
screen is OFF. From my tests, high latency is only triggered by switching OFF
the display.

Fixes #18939

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

 modules/audio_output/auhal.c            |  2 +-
 modules/audio_output/coreaudio_common.c | 23 ++++++++++++++++++++---
 modules/audio_output/coreaudio_common.h |  4 +++-
 3 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/modules/audio_output/auhal.c b/modules/audio_output/auhal.c
index 3359798d1a..d221e08ce3 100644
--- a/modules/audio_output/auhal.c
+++ b/modules/audio_output/auhal.c
@@ -983,7 +983,7 @@ RenderCallbackSPDIF(AudioDeviceID inDevice, const AudioTimeStamp * inNow,
     uint8_t *p_output = outOutputData->mBuffers[p_sys->i_stream_index].mData;
     size_t i_size = outOutputData->mBuffers[p_sys->i_stream_index].mDataByteSize;
 
-    ca_Render(p_aout, p_output, i_size);
+    ca_Render(p_aout, 0, p_output, i_size);
 
     return noErr;
 }
diff --git a/modules/audio_output/coreaudio_common.c b/modules/audio_output/coreaudio_common.c
index 0413dea570..292146f28c 100644
--- a/modules/audio_output/coreaudio_common.c
+++ b/modules/audio_output/coreaudio_common.c
@@ -50,6 +50,7 @@ ca_Open(audio_output_t *p_aout)
     atomic_init(&p_sys->i_underrun_size, 0);
     atomic_init(&p_sys->b_paused, false);
     atomic_init(&p_sys->b_do_flush, false);
+    atomic_init(&p_sys->b_highlatency, true);
     vlc_sem_init(&p_sys->flush_sem, 0);
     vlc_mutex_init(&p_sys->lock);
 
@@ -70,10 +71,17 @@ ca_Close(audio_output_t *p_aout)
 
 /* Called from render callbacks. No lock, wait, and IO here */
 void
-ca_Render(audio_output_t *p_aout, uint8_t *p_output, size_t i_requested)
+ca_Render(audio_output_t *p_aout, uint32_t i_nb_samples, uint8_t *p_output,
+          size_t i_requested)
 {
     struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys;
 
+    const bool b_highlatency = CLOCK_FREQ * (uint64_t)i_nb_samples / p_sys->i_rate
+                             > AOUT_MAX_PTS_DELAY;
+
+    if (b_highlatency)
+        atomic_store(&p_sys->b_highlatency, true);
+
     bool expected = true;
     if (atomic_compare_exchange_weak(&p_sys->b_do_flush, &expected, false))
     {
@@ -109,6 +117,11 @@ ca_Render(audio_output_t *p_aout, uint8_t *p_output, size_t i_requested)
         atomic_fetch_add(&p_sys->i_underrun_size, i_requested - i_tocopy);
         memset(&p_output[i_tocopy], 0, i_requested - i_tocopy);
     }
+
+    /* Set high delay to false (re-enabling ca_Timeget) after consuming the
+     * circular buffer */
+    if (!b_highlatency)
+        atomic_store(&p_sys->b_highlatency, false);
 }
 
 int
@@ -116,6 +129,10 @@ ca_TimeGet(audio_output_t *p_aout, mtime_t *delay)
 {
     struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys;
 
+    /* Too high delay: TimeGet will be too imprecise */
+    if (atomic_load(&p_sys->b_highlatency))
+        return -1;
+
     int32_t i_bytes;
     TPCircularBufferTail(&p_sys->circular_buffer, &i_bytes);
 
@@ -240,6 +257,7 @@ ca_Initialize(audio_output_t *p_aout, const audio_sample_format_t *fmt,
 
     atomic_store(&p_sys->i_underrun_size, 0);
     atomic_store(&p_sys->b_paused, false);
+    atomic_store(&p_sys->b_highlatency, true);
     p_sys->i_rate = fmt->i_rate;
     p_sys->i_bytes_per_frame = fmt->i_bytes_per_frame;
     p_sys->i_frame_length = fmt->i_frame_length;
@@ -347,9 +365,8 @@ RenderCallback(void *p_data, AudioUnitRenderActionFlags *ioActionFlags,
     VLC_UNUSED(ioActionFlags);
     VLC_UNUSED(inTimeStamp);
     VLC_UNUSED(inBusNumber);
-    VLC_UNUSED(inNumberFrames);
 
-    ca_Render(p_data, ioData->mBuffers[0].mData,
+    ca_Render(p_data, inNumberFrames, ioData->mBuffers[0].mData,
               ioData->mBuffers[0].mDataByteSize);
 
     return noErr;
diff --git a/modules/audio_output/coreaudio_common.h b/modules/audio_output/coreaudio_common.h
index 4fb4e5fb64..21cdcb6518 100644
--- a/modules/audio_output/coreaudio_common.h
+++ b/modules/audio_output/coreaudio_common.h
@@ -55,6 +55,7 @@ struct aout_sys_common
     atomic_uint         i_underrun_size;
     atomic_bool         b_paused;
     atomic_bool         b_do_flush;
+    atomic_bool         b_highlatency;
     vlc_sem_t           flush_sem;
     vlc_mutex_t         lock;
     int                 i_rate;
@@ -70,7 +71,8 @@ void ca_Open(audio_output_t *p_aout);
 
 void ca_Close(audio_output_t *p_aout);
 
-void ca_Render(audio_output_t *p_aout, uint8_t *p_output, size_t i_requested);
+void ca_Render(audio_output_t *p_aout, uint32_t i_nb_samples, uint8_t *p_output,
+               size_t i_requested);
 
 int  ca_TimeGet(audio_output_t *p_aout, mtime_t *delay);
 



More information about the vlc-commits mailing list