1
mirror of https://code.videolan.org/videolan/vlc synced 2024-10-03 01:31:53 +02:00

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

(cherry picked from commit f18fef325a)
Signed-off-by: Thomas Guillem <thomas@gllm.fr>
This commit is contained in:
Thomas Guillem 2018-03-12 16:06:48 +01:00
parent b83976bcf5
commit bab4c8269e
3 changed files with 24 additions and 5 deletions

View File

@ -984,7 +984,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;
}

View File

@ -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);
@ -239,6 +256,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;
@ -346,9 +364,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;

View File

@ -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);