Closed defagos closed 2 years ago
This is likely a tvOS 15 regression, probably in the way tvOS deals with interstitial updates or when an AVPlayer(Item)
instance gets deallocated. We must probably create a sample project and report the issue to Apple, as we do nothing special with interstitials (except updating them).
I guess we should create a small AVPlayerViewController
example:
AVPlayer
with interstitials (or empty array).AVPlayer
with interstitials (or empty array). I can simply reproduce the issue in SRG Media Player demo by switching the media after some while in the SRG Media Player View Controller demo:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(7. * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[playerViewController.controller playURL:media.URL];
});
No matter whether the player item interstitial property is set or not, the crash occurs. So a good sample project could be:
AVPlayerViewController
with an associated AVPlayer
instance and KVObserve its player property and investigate what kind of code executed upon KVObservation (via MAKVONotificationCenter blocks in our case, which could add their own share of issues) could be responsible of the crash.By experimenting a bit with the code executed upon KVObservation of player changes we might be able to figure out what causes the crash.
The following AVPlayerViewController
sample does not crash, so we might find something in our code which explains the crash by swapping the NSLog
with code involving more player changes like those we do in our current SRGMediaPlayerViewController
implementation:
NSURL *URL = ...;
AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init];
playerViewController.delegate = self;
AVPlayer *player = [AVPlayer playerWithURL:URL];
playerViewController.player = player;
[self presentViewController:playerViewController animated:YES completion:^{
[player play];
}];
@weakify(playerViewController)
[playerViewController addObserver:self keyPath:@keypath(playerViewController.player) options:0 block:^(MAKVONotification *notification) {
@strongify(playerViewController)
NSLog(@"--> %@", playerViewController);
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(7. * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
playerViewController.player = [AVPlayer playerWithURL:URL];
[playerViewController.player play];
});
Crash is likely due to -bindToPlayerViewController:
being called when player changes are detected with KVO. Seems to be related to the fact that we ultimately assign playerViewController.player = self.player
from within the KVO block.
Code to reproduce the crash with AVPlayerViewController
only. A bit contrived since we are observing changes to the player property to apply them again via KVO, but this leads to the exact same crash and could be helpful in finding a solution:
NSURL *URL = ...;
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"System player", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init];
playerViewController.delegate = self;
AVPlayer *player = [AVPlayer playerWithURL:URL];
playerViewController.player = player;
[self presentViewController:playerViewController animated:YES completion:^{
[player play];
}];
@weakify(playerViewController)
[playerViewController addObserver:self keyPath:@keypath(playerViewController.player) options:0 block:^(MAKVONotification *notification) {
@strongify(playerViewController)
playerViewController.player = player;
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5. * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
playerViewController.player = [AVPlayer playerWithURL:];
[playerViewController.player play];
});
}]];
It might be related to the deallocation of the previous player instance, rather than to the assignment to the player view controller. This should be further investigated.
The crash randomly occurs when setting the AVPlayerViewController
player
property to nil
. This is done in our current implementation when switching between medias since the player is reset first to nil
.
This can be reproduced in a sample project which I will submit to Apple. I also suspect we can find a workaround in the meantime.
If we try to set the property to an AVPlayer
instance (e.g. one instantiated with -new
) the crash still occurs. It is likely that the issue is not related to the value itself, but to the fact we are setting several times the player view controller player property in a row. Maybe a viable workaround would perform additional checks to avoid performing several changes in a row if not necessary.
It is also very likely that this issue would be less of a problem if we were using a single AVQueuePlayer
instance per controller, see #252.
@defagos Nice bug understanding.
Enabling auto play in Letterbox demo and displaying the continuous playback screen, no more crashes on tvOS.
The app crashes when a new media is being played after continuous playback display.
Issue type
Crash
Description of the problem
Stack trace:
This is an issue with interstitials and KVO, probably a regression of tvOS 15.
Environment information
Reproducibility
Always reproducible
Steps to reproduce