[vlc-commits] coreaudio: finer audio delay

Thomas Guillem git at videolan.org
Wed Mar 14 14:50:50 CET 2018


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Wed Mar 14 14:49:30 2018 +0100| [feaa3e792b259099771987635f5cdc8f56d776af] | committer: Thomas Guillem

coreaudio: finer audio delay

This is a partial revert of f18fef325af25113875b09c8f727017febc6198a

This commit fixes the delay imprecision that was depending on the number of
frames asked by the render callback. This also fixes audio glitches (due to
flush/resampling) when this number of frames was changed (when the screen is
OFF for example).

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

 modules/audio_output/auhal.c            |  5 ++++-
 modules/audio_output/coreaudio_common.c | 37 ++++++++++++++++++++++++---------
 modules/audio_output/coreaudio_common.h |  7 ++++---
 3 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/modules/audio_output/auhal.c b/modules/audio_output/auhal.c
index d221e08ce3..1306542cfd 100644
--- a/modules/audio_output/auhal.c
+++ b/modules/audio_output/auhal.c
@@ -983,7 +983,10 @@ 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, 0, p_output, i_size);
+    uint64_t i_host_time = (inNow->mFlags & kAudioTimeStampHostTimeValid)
+                         ? inNow->mHostTime : 0;
+
+    ca_Render(p_aout, 0, i_host_time, p_output, i_size);
 
     return noErr;
 }
diff --git a/modules/audio_output/coreaudio_common.c b/modules/audio_output/coreaudio_common.c
index 1dd80812c8..da1ba1a8c9 100644
--- a/modules/audio_output/coreaudio_common.c
+++ b/modules/audio_output/coreaudio_common.c
@@ -26,6 +26,7 @@
 #import <CoreAudio/CoreAudioTypes.h>
 
 #import <dlfcn.h>
+#import <mach/mach_time.h>
 
 static struct
 {
@@ -33,6 +34,8 @@ static struct
     void (*unlock)(os_unfair_lock *lock);
 } unfair_lock;
 
+static mach_timebase_info_data_t tinfo;
+
 static inline uint64_t
 BytesToFrames(struct aout_sys_common *p_sys, size_t i_bytes)
 {
@@ -66,6 +69,9 @@ ca_init_once(void)
     unfair_lock.unlock = dlsym(RTLD_DEFAULT, "os_unfair_lock_unlock");
     if (!unfair_lock.unlock)
         unfair_lock.lock = NULL;
+
+    if (mach_timebase_info(&tinfo) != KERN_SUCCESS)
+        tinfo.numer = tinfo.denom = 0;
 }
 
 static void
@@ -131,15 +137,15 @@ 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, uint32_t i_nb_samples, uint8_t *p_output,
-          size_t i_requested)
+ca_Render(audio_output_t *p_aout, uint32_t i_frames, uint64_t i_host_time,
+          uint8_t *p_output, size_t i_requested)
 {
     struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys;
 
     lock_lock(p_sys);
 
-    p_sys->b_highlatency = CLOCK_FREQ * (uint64_t)i_nb_samples / p_sys->i_rate
-                         > AOUT_MAX_PTS_DELAY;
+    p_sys->i_render_host_time = i_host_time;
+    p_sys->i_render_frames = i_frames;
 
     if (p_sys->b_do_flush)
     {
@@ -201,14 +207,19 @@ ca_TimeGet(audio_output_t *p_aout, mtime_t *delay)
     struct aout_sys_common *p_sys = (struct aout_sys_common *) p_aout->sys;
 
     lock_lock(p_sys);
-    if (p_sys->b_highlatency)
+
+    if (tinfo.denom == 0 || p_sys->i_render_host_time == 0)
     {
         lock_unlock(p_sys);
         return -1;
     }
 
-    int64_t i_frames = BytesToFrames(p_sys, p_sys->i_out_size);
-    *delay = FramesToUs(p_sys, i_frames) + p_sys->i_dev_latency_us;
+    const uint64_t i_render_time_us = p_sys->i_render_host_time
+                                    * tinfo.numer / tinfo.denom / 1000;
+
+    const int64_t i_out_frames = BytesToFrames(p_sys, p_sys->i_out_size);
+    *delay = FramesToUs(p_sys, i_out_frames + p_sys->i_render_frames)
+           + p_sys->i_dev_latency_us + i_render_time_us - mdate();
 
     lock_unlock(p_sys);
     return 0;
@@ -249,10 +260,12 @@ ca_Flush(audio_output_t *p_aout, bool wait)
             p_sys->b_do_flush = true;
             lock_unlock(p_sys);
             vlc_sem_wait(&p_sys->flush_sem);
-            return;
+            lock_lock(p_sys);
         }
     }
 
+    p_sys->i_render_host_time = 0;
+    p_sys->i_render_frames = 0;
     lock_unlock(p_sys);
 }
 
@@ -347,7 +360,8 @@ ca_Initialize(audio_output_t *p_aout, const audio_sample_format_t *fmt,
 
     p_sys->i_underrun_size = 0;
     p_sys->b_paused = false;
-    p_sys->b_highlatency = true;
+    p_sys->i_render_host_time = 0;
+    p_sys->i_render_frames = 0;
 
     p_sys->i_rate = fmt->i_rate;
     p_sys->i_bytes_per_frame = fmt->i_bytes_per_frame;
@@ -460,7 +474,10 @@ RenderCallback(void *p_data, AudioUnitRenderActionFlags *ioActionFlags,
     VLC_UNUSED(inTimeStamp);
     VLC_UNUSED(inBusNumber);
 
-    ca_Render(p_data, inNumberFrames, ioData->mBuffers[0].mData,
+    uint64_t i_host_time = (inTimeStamp->mFlags & kAudioTimeStampHostTimeValid)
+                         ? inTimeStamp->mHostTime : 0;
+
+    ca_Render(p_data, inNumberFrames, i_host_time, 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 d78b1f43ae..eaf21e7621 100644
--- a/modules/audio_output/coreaudio_common.h
+++ b/modules/audio_output/coreaudio_common.h
@@ -52,12 +52,13 @@ struct aout_sys_common
     size_t              i_underrun_size;
     bool                b_paused;
     bool                b_do_flush;
-    bool                b_highlatency;
 
     size_t              i_out_max_size;
     size_t              i_out_size;
     block_t             *p_out_chain;
     block_t             **pp_out_last;
+    uint64_t            i_render_host_time;
+    uint32_t            i_render_frames;
 
     vlc_sem_t           flush_sem;
 
@@ -83,8 +84,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, uint32_t i_nb_samples, uint8_t *p_output,
-               size_t i_requested);
+void ca_Render(audio_output_t *p_aout, uint32_t i_nb_samples, uint64_t i_host_time,
+               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