-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ao_coreaudio: stop audio unit after timeout to allow sleep #11667
Conversation
This commit attempts to fix the problem that mpv prevents sleep on Mac while paused (mpv-player#11617). It also affects libmpv clients. This problem was introduced by commit 39f7f83, where AudioOutputUnitStop was changed to AudioUnitReset to prevent Bluetooth audio lag during seeking. However, coreaudiod keeps putting an assertion to prevent sleep when the audio unit is active. The proposed solution in this commit is to call AudioOutputUnitStop after a timeout. If the audio unit is reset and not restarted during the timeout, it indicates that the user paused the playback (rather than seeking), and sleep should be allowed. A serial dispatch queue is created to reset/start the audio unit and update related data structures to avoid racing conditions.
I have built mpv with the proposed changes and tested the fix. Using this command to monitor while true; do pmset -g assertions | grep 'coreaudiod\|mpv' | grep -v grep; sleep 1; done Shows
Monitoring Adapting the command to monitor the behavior of @LiJChang, @sfan5 Thoughts on issue #11617 and this proposed fix? |
With the implementation, could there be an issue in the following sequence of events?
Using 1 static dispatch queue instead of creating a new dispatch queue per AO-init would help avoid this, since then the start_count state is maintained across track boundary. Alternatively need to check not only whether the ao key is set, but also that it hasn't changed since block enqueue. Or maybe another way is using a dispatch timer source, which can be cancelled when uniniting. |
@krackers Glad you are thinking about such scenarios and asking questions. We will have to see that the mpv developers who really know this code think. Here is what I believe will happen in the described scenario… The The next track will get a fresh The data must be kept separate as when Kept thinking about how to break this code and asking questions! |
Yes you are right, thank you for the explanation! I misunderstood how |
I'm happy to explain things. Questioning the code like this is exactly what should happen during review. I really appreciate you taking the time to read and think about the proposed changes. Any other questions, speak up! |
I believe debouncing using dispatch work item would be cleaner: orion1vi@6240364, if it must be serialized: orion1vi@4fa23cf. |
I agree, canceling a dispatch block is cleaner. Serialization is still required to properly coordinate with the queue'd block. |
Note This will impact e.g. macports version of mpv: https://ports.macports.org/port/mpv/details/ which enables CoreAudio for anything >= 10.6. |
@krackers Thanks for pointing that out. Always important to remember that as a result of the high cost of Apple hardware there are users who are forced to use old versions of macOS due to their ancient hardware. A list of vintage and obsolete Macs can be found here. I've been confused about mpv's system requirements for macOS ever since I read a response to an issue that indicated mpv was following Apple's convention of only supporting the 3 latest versions of macOS. I've heard that is Apple's policy, but I've been unable to find an actual statement from Apple on that. Most Apple web site pages only list macOS Ventura. The Apple page Find out which macOS your Mac is using still has a link for macOS Catalina (10.15). The Apple page Apple security updates shows the last security update for Catalina was on 20 Jul 2022. After that date macOS Big Sur is the oldest macOS release listed. Officially mpv's System requirements says this:
Is that out of date? The current release of IINA has a minimum requirement of OS X El Capitan (10.11). |
It probably might be, although it's not strictly wrong. I recall diff --git a/osdep/macosx_menubar.m b/osdep/macosx_menubar.m
index c424df255c6..b51b3738e78 100644
--- a/osdep/macosx_menubar.m
+++ b/osdep/macosx_menubar.m
@@ -715,7 +715,7 @@ - (void)openPlaylist
if ([panel runModal] == NSModalResponseOK){
NSString *pl = [NSString stringWithFormat:@"loadlist \"%@\"",
- [panel URLs][0].path];
+ [[panel URLs][0] path]];
[(Application *)NSApp queueCommand:(char *)[pl UTF8String]];
}
} was the only change needed to get 0.31 to compile on 10.8 (since I think generics were not supported in that version of objective-c, so compiler cannot infer type of array element). And if using X11 instead of Cocoa for windowing, then even that change is not necessary. But since mpv developers do not officially support the legacy vo=opengl backend on OSX anymore, and vo=libmpv requires swift, maybe it is ok to bump the minimum to 10.10? Macports could patch on their end to support lower versions (like they already do for |
we or rather i don't go out of my way to support anything other than the latest 3 macOS versions. that doesn't mean i proactively remove support for older versions. i only remove old things if they are in the way. with that being said, this should not be confused with mpv's system requirements. this only really has implications for bug reports. if the bug occurs on older macOS versions only but not on the latest three versions, we/i won't invest any time in fixing or circumventing it. hence only problems/bugs are relevant that are reproducible on the latest 3 versions. i think mpv's lowest tested macOS target (by me) was 10.10 and that should still work. on a side note, the menubar is an optional feature (can be deactivated) that is not needed for mpv's main purpose, and if this is really the only place that needs adjustments for 10.8 than 10.8 is still supported and the readme correct. |
In that case, dispatch source timer could be used: orion1vi@19a63b1, if timer is reused: orion1vi@85735b2. |
Dispatch timer approach LGTM, and seems just as clean as the block_cancel approach. |
sorry it took me so long. we should finally get a fix for this merged. we recently raised the minimum macOS version to 10.15. so we don't need the dispatch source time approach from here #11667 (comment) anymore? i would say, the cleanest way to deal with this is the second debouncing serialised approach from here #11667 (comment) @orion1vi could you open a PR for this please? would also be nice to have some explanation of the problem, the source of the problem and the fix in the commit body, similar to the commit here. |
I'm glad to hear this issue will be getting some attention. I too was expecting that with the minimum supported macOS version having been raised to macOS Catalina the commit should be updated. IINA considered blocking sleep to be a critical problem and applied the changes in this PR when building As this is touching audio on the Mac, note that IINA is currently unable to function properly with |
lets wait some time (~1week) for them to react/reply. |
Yes, waiting sounds good. Just letting you know I'm willing to help if needed. |
@low-batt i will take you up on the offer. would be nice if you could prepare the PR and preserve the authorship. |
I should have time to prepare a PR tomorrow. I will preserve the authorship. |
I'm in the middle of preparing the new pull request and I have a question about the code. I've pulled this commit from @orion1vi and there is a change compared to the commit in this PR. The new commit uses static void reset(struct ao *ao)
{
struct priv *p = ao->priv;
dispatch_async_f(p->queue, ao, &_reset);
} Whereas the commit in this PR uses static void reset(struct ao *ao)
{
struct priv *p = ao->priv;
dispatch_sync_f(p->queue, p->queue, reset_p);
} The I'm worried the calling code expects the operation to be completed when the Is it ok for these methods to asynchronously perform the operations? |
I've created PR #13663. I did not want to make any code changes without others approving, so I did not change the code other than to add a couple of comments. If these operations need to be synchronous let me know and I will update that PR. |
closing in favour of #13663. |
This commit attempts to fix the problem that mpv prevents sleep on Mac while paused (#11617). The problem also affects libmpv clients.
This problem was introduced by commit 39f7f83, where
AudioOutputUnitStop
was changed to AudioUnitReset to prevent Bluetooth audio lag during seeking. However, coreaudiod keeps putting an assertion to prevent sleep when the audio unit is active.The proposed solution is to call
AudioOutputUnitStop
after a timeout. If the audio unit is reset and not restarted during the timeout, it indicates that the user paused the playback (rather than seeking), and sleep should be allowed.A serial dispatch queue is created to reset, start and stop the audio unit to avoid race conditions.
start
,reset
, anduninit
will run synchronously on this queue.check_stop
will run asynchronously on this queue, after the timeout. Theao
is put into the queue's metadata and removed onunit
, so the scheduledcheck_stop
tasks will know ifao
still exists.Thanks @low-batt for testing this patch.