ao_avfoundation: stop requesting media while paused - #18390
aliceisjustplaying wants to merge 1 commit into
Conversation
Why should it do that?
Busylooping any time the player is paused would've resulted in far more noise about it, considering we haven't heard about this issue at all yet, is this a MacOS regression? |
| struct priv *p = ao->priv; | ||
|
|
||
| if (paused) { | ||
| [p->renderer stopRequestingMediaData]; |
There was a problem hiding this comment.
I know we use this property elsewhere in the AO too, but this is deprecated https://developer.apple.com/documentation/avfoundation/avsamplebufferaudiorenderer/stoprequestingmediadata()
It can't be the case that avoiding busylooping necessitates the use of a deprecated property
|
I also find it strange that there is no noise about it, but I tested this both on the macOS 27 beta but also on macOS 26 now and I can reproduce it, Updated the PR description. Looking into the deprecated property. |
|
@llyyr it's deprecated for swift but not objc, and as far as i can tell apple's website is just simply wrong about this Xcode 27 SDK, #if defined(__swift__)
API_DEPRECATED("Cancel the receiver's Task instead", macos(10.13, 27.0), ...)
#else
API_AVAILABLE(macos(10.13), ...)
#endif
|
The AVSampleBufferAudioRenderer callback remained registered when the synchronizer rate was set to zero. If its queue was empty when playback was paused, AVFoundation immediately invoked the callback again after ao_read_data returned no samples, consuming a full CPU core. Stop requesting media data before pausing and register the callback again when playback resumes. This balances the request/stop lifecycle and prevents the empty renderer from busy-looping.
4df03a9 to
4e616c3
Compare
|
I can reproduce this on macOS 27.0 arm64 with libmpv 0.41.0, and this PR fixes it. I hit it through Supersonic, a Subsonic client that bundles libmpv. It sat at 91-100% CPU while paused, and a My reproducer uses libmpv with
Pausing with audio still queued doesn't trigger it on either build. Neither does starting paused, seeking while paused, adding and removing an aggregate device while paused, or The harness is about 60 lines of C plus a small Python server. Happy to share it. Disclosure: I used an AI coding assistant for the diagnosis and the test harness. I ran the tests and checked the results myself. |
Summary
Stop
AVSampleBufferAudioRendererfrom requesting media data while mpv is paused, then register the request callback again when playback resumes.Root cause
set_pauseset the render synchronizer rate to zero but left the media-data request active. If the renderer had no queued audio,ao_read_datareturned no samples while paused. AVFoundation still considered the renderer ready for more data and immediately invoked the callback again, creating a busy loop on theavfoundation eventqueue.The callback request now stops before the rate changes to zero. Resuming sets the rate back to one and registers a new callback, keeping the request and stop lifecycle balanced.
Observed failure
A paused mpv 0.41.0 process consistently consumed one full CPU core while its playback, decoder, demuxer, video-output, and Lua threads slept. A process sample showed the active thread in this stack:
The process-level signal stayed consistent across repeated measurements:
Verification
meson compile -C buildgit diff --check origin/master...HEADao=avfoundation, completed five pause/resume cycles, and left the player pausedAdditional macOS 26 runtime verification:
e7191f2a65) and PR commit (4df03a9b22) on macOS 26.6.2 (25G83), arm64paused_cpu=77.4; a three-second sample recorded 2,266 samples onDispatchQueue: avfoundation event, including 1,610 in-[AVMediaDataRequester _requestMediaDataIfReady]paused_cpu=0.1;requestMediaDataIfReadywas absent from the sample; resume and re-pause measured0.0%CPUThis build configuration defines no automated tests. The behavior depends on the macOS AVFoundation runtime, so the verification exercises the real audio output.
AI/LLM disclosure
OpenAI Codex with GPT-5.6 Sol (high) assisted with diagnosis, implementation, testing, and drafting this pull request. I understand the change and take full responsibility for it, including its licensing under the file's existing LGPLv2.1+ terms. I will participate in review with human-written responses.