Prefer avfoundation AO on macOS 27 to avoid mpv hotplug listener crash

On macOS 27 beta, mpv's coreaudio AO fails to initialize (channel layout
set rejected with paramErr -50). The existing ao=coreaudio,avfoundation
fallback restored audio, but exposed an mpv bug: init() registers a HAL
hotplug listener (AudioObjectAddPropertyListener on the system object,
with the raw ao pointer as user data) before the step that fails, and
the coreaudio_error path never unregisters it. mpv then frees the ao
and falls back to avfoundation, leaving a dangling listener per
playback start. The next audio device change (AirPods connect,
sleep/wake device republish) invokes the listener with the freed
pointer and crashes with a use-after-free SIGSEGV on the
HALC_ProxyNotification Call Listener Queue (observed in build 262;
faulting address was reused "texture_" shader string memory).

Gate the AO order by OS version: on macOS 27+ use
avfoundation,coreaudio so the failing coreaudio init never runs; older
macOS keeps the native coreaudio first with avfoundation as fallback.
Update the read-only defaults mirror in MPV options settings to match.
This commit is contained in:
Arkadiusz Fal
2026-07-07 23:51:34 +02:00
parent 9e2b0fa095
commit afa73e6bcb
2 changed files with 17 additions and 6 deletions

View File

@@ -463,11 +463,18 @@ final class MPVClient: @unchecked Sendable {
#elseif os(macOS)
// coreaudio is the native macOS AO, but on macOS 27 beta it fails to
// initialize ("unable to set the input channel layout on the audio
// unit -50"), leaving playback silent. Add avfoundation
// (AVSampleBufferAudioRenderer) as a fallback so mpv self-heals: older
// macOS keeps using coreaudio, and where coreaudio can't open the
// device mpv drops to avfoundation instead of playing no sound.
setOptionSync("ao", "coreaudio,avfoundation")
// unit -50"), leaving playback silent. Worse, mpv's coreaudio AO
// registers a HAL hotplug listener before the step that fails and its
// init-failure path never unregisters it, so every failed init leaves
// a dangling listener that crashes (use-after-free) on the next audio
// device change. On macOS 27+ put avfoundation first so the failing
// coreaudio init never runs; older macOS keeps native coreaudio with
// avfoundation as fallback.
if ProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 27 {
setOptionSync("ao", "avfoundation,coreaudio")
} else {
setOptionSync("ao", "coreaudio,avfoundation")
}
#endif
// Cache settings for network streams

View File

@@ -123,7 +123,11 @@ private struct DefaultOptionsSection: View {
#if os(iOS) || os(tvOS)
options.append(("ao", "audiounit"))
#else
options.append(("ao", "coreaudio,avfoundation"))
if ProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 27 {
options.append(("ao", "avfoundation,coreaudio"))
} else {
options.append(("ao", "coreaudio,avfoundation"))
}
#endif
options.append(("cache", "yes"))