ao_coreaudio: use AudioUnitReset as ao_driver.reset to prevent long restart

[motivation]
Seeking on MacOS appears to be lagged when users connect
to wireless audio output (airpods for example).

This commit attempts to fix mpv-player/mpv#10270

[observation]
1. When using other media player (VLC to be exact) simultaneously,
the lagging on seek disappear. We could guess that the AudioDevice
is on some sort of "warm-up" state.

See mpv-player/mpv#9243 for detailed description.

2. `AudioOutputUnitStart` takes significant longer time after each seek
or pause/play when using wireless output devices compares to wired devices.

[rationale]
After investigate codes in ao_coreaudio.c, it appears that the the `stop`
function was used as `ao_driver.reset` function. Therefore every seek
and pause would call `AudioOutputUnitStop`.

It turns out that `ao_driver.reset` function is used in `ao_reset`.
And `ao_reset` function is used to clean up the state of current `ao`
so I think `AudioUnitReset` is more proper than `AudioOutputUnitStop`
under this semantics.

Since ao_coreaudio use pull base mechanism, audio playback behaviors
upon pause/seek could be handled by callback function
(streaming silence when paused) so there is no need to stop AudioUnit when resetting.
Therefore using `AudioUnitReset` as `ao_driver.reset` looks proper.

Additionally, after using proper reset, the AudioUnit that represents
hardware I/O devices doesn't need to be restart everytime seek/pause actions happen.
Restarting wireless devices simply takes longer in MacOS which is
the root cause of lagging observed by users when they seek or pause/play media.

[method]
Use `AudioUnitReset` for ao_driver.reset.
This commit is contained in:
Li Chang 2022-12-02 19:00:57 +08:00 committed by sfan5
parent ad65c8855b
commit 39f7f83351
1 changed files with 4 additions and 4 deletions

View File

@ -314,11 +314,11 @@ coreaudio_error:
return false; return false;
} }
static void stop(struct ao *ao) static void reset(struct ao *ao)
{ {
struct priv *p = ao->priv; struct priv *p = ao->priv;
OSStatus err = AudioOutputUnitStop(p->audio_unit); OSStatus err = AudioUnitReset(p->audio_unit, kAudioUnitScope_Global, 0);
CHECK_CA_WARN("can't stop audio unit"); CHECK_CA_WARN("can't reset audio unit");
} }
static void start(struct ao *ao) static void start(struct ao *ao)
@ -415,7 +415,7 @@ const struct ao_driver audio_out_coreaudio = {
.uninit = uninit, .uninit = uninit,
.init = init, .init = init,
.control = control, .control = control,
.reset = stop, .reset = reset,
.start = start, .start = start,
.hotplug_init = hotplug_init, .hotplug_init = hotplug_init,
.hotplug_uninit = hotplug_uninit, .hotplug_uninit = hotplug_uninit,