Commit feaa3e79 authored by Thomas Guillem's avatar Thomas Guillem

coreaudio: finer audio delay

This is a partial revert of f18fef32

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).
parent 9bb14eda
......@@ -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;
}
......
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment