mirror of
https://github.com/yattee/yattee.git
synced 2026-11-02 01:47:18 +00:00
Reload the avfoundation audio output when it restarts while paused
The heat in the iOS 27.2 TestFlight report (~36% CPU for 85 minutes with playback paused) started right after an audio route change while paused: mpv's ao_avfoundation logged "restarting due to system notification" and an unnamed thread went to ~36% immediately, still in the foreground. Its restart handler calls stop() then start() regardless of pause state; start() sets the synchronizer rate to 1 and requests media data, but paused mpv supplies no samples, so the empty renderer re-requests in a tight loop and the running renderer keeps iOS from suspending the app. When that log line arrives and mpv is paused, issue ao-reload so the AO is rebuilt paused. (The display link guard in the previous commit did not reproduce the spin when tested on a device.)
This commit is contained in:
@@ -252,6 +252,10 @@ final class MPVClient: @unchecked Sendable {
|
||||
|
||||
let line = MPVLogLine(prefix: prefix, level: level, text: text)
|
||||
|
||||
if prefix == "ao/avfoundation", text.hasPrefix("restarting due to system notification") {
|
||||
reloadAudioOutputIfPaused()
|
||||
}
|
||||
|
||||
logBufferLock.lock()
|
||||
recentLogBuffer.append(line)
|
||||
if recentLogBuffer.count > recentLogBufferCapacity {
|
||||
@@ -277,6 +281,22 @@ final class MPVClient: @unchecked Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
/// mpv's avfoundation AO restarts its renderer on route changes and automatic
|
||||
/// flushes, and the restart always starts it (synchronizer rate 1, requesting
|
||||
/// data) even while paused. Paused mpv supplies no samples, so the empty
|
||||
/// renderer re-requests in a tight loop on its dispatch queue (~35% CPU), and
|
||||
/// the running renderer keeps iOS from suspending the app in the background.
|
||||
/// Reloading the AO rebuilds it in the paused state.
|
||||
private func reloadAudioOutputIfPaused() {
|
||||
mpvQueue.async { [weak self] in
|
||||
guard let self, let mpv = self.mpv, !self.isDestroyed else { return }
|
||||
var paused: Int32 = 0
|
||||
guard mpv_get_property(mpv, "pause", MPV_FORMAT_FLAG, &paused) >= 0, paused != 0 else { return }
|
||||
self.logWarning("avfoundation AO restarted while paused - reloading audio output")
|
||||
_ = self.commandUnsafe(["ao-reload"])
|
||||
}
|
||||
}
|
||||
|
||||
/// Snapshot the recent log buffer (most-recent-last). Thread-safe.
|
||||
func recentLogLines(minimumSeverity: Int = 0) -> [MPVLogLine] {
|
||||
logBufferLock.lock()
|
||||
|
||||
Reference in New Issue
Block a user