Commit f18fef32 authored by Thomas Guillem's avatar 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
parent bcf9c70d
......@@ -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;
......@@ -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);
......@@ -70,10 +71,17 @@ ca_Close(audio_output_t *p_aout)
/* Called from render callbacks. No lock, wait, and IO here */
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
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);
......@@ -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,
ca_Render(p_data, ioData->mBuffers[0].mData,
ca_Render(p_data, inNumberFrames, ioData->mBuffers[0].mData,
return noErr;
......@@ -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);
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