ios - 调用 AVAssetResourceLoadingRequest 的 finishLoadingWithError(err) 时如何强制 AVPlayer 失败
问题描述
我想通过 playerFailedToReachEnd 通知或通过 KVO 观察 player.status 强制 AVPlayer 抛出播放器错误,当在通过 AVAssetResourceLoader 加载资源请求的过程中请求完成加载错误时。
它不应该在 AVPlayer 上进行手动播放停止,以避免处理手动停止和 KVO/通知之间的竞争条件
避免发生错误时在 AVPlayer 上手动停止播放以避免竞争条件。
尝试返回回调“resourceLoader:shouldWaitForLoadingOfRequestedResource:”的部分以返回 NO 它不会使 AVPlayer 将状态更改为失败,也不会发送有关播放器失败的通知
@implementation AssetLoader <AVAssetResourceLoaderDelegate>
- (AVPlayerItem *)setupLoader {
NSURL *playbackUrl = [NSURL URLWithString:@"example-url"];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:playbackUrl options:nil];
[asset.resourceLoader setDelegate:self queue:_sample_queue];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
return playerItem;
}
- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest {
if ([url.scheme isEqual:@"skd"] == NO) {
QPLogError(@"Unexpected url scheme: %@", url.absoluteString);
return NO;
}
LicenseAction *action = [[LicenseAction alloc] initWithLoadingRequest:loadingRequest];
[action execute:^(NSData *ckcData, NSError *error) {
if (error) {
[loadingRequest finishLoadingWithError:error]; //This should prompt AVPlayer to fail
} else {
[loadingRequest.dataRequest respondWithData:ckcData];
[loadingRequest finishLoading];
}
}];
return YES;
}
...
@end
@implementation Player {
AVPlayer *_player;
}
- (void)prepare {
[_player replaceCurrentItemWithPlayerItem:playerItem];
NSKeyValueObservingOptions options = (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld | NSKeyValueObservingOptionInitial);
[_player addObserver:self forKeyPath:@"status" options:options context:&QPClearPlayerAVPlayerKVOContext];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemFailedToEnd:) name:AVPlayerItemFailedToPlayToEndTimeNotification object:_player.currentItem];
}
- (void)stopWithError {
...
[self reportPlayerError];
}
...
- (void)playerItemFailedToEnd:(NSNotification *)notification {
...
[self reportPlayerError];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if(object == _player && keyPath == @"status") {
...
if (_player.status == AVPlayerStatusFailed) {
[self reportPlayerError];
}
}
}
...
@end
在调用 AVAssetResourceLoadingRequest.finishLoadingWithError() 时预期 AVPlayer 将发送失败通知或 KVO 状态更改
实际 AVPlayer 没有状态变化也没有失败通知
解决方案
推荐阅读
- function - Julia 中的局部变量不支持“const”声明
- sql - SQL按月和年选择日期,但按列关系选择另一个月/年行
- amazon-s3 - 带有 CMK 的 AWS 加密 S3 无法进行跨账户访问
- python - 从数据库中获取所有记录(Flask 和 SQLAlchemy)
- ios - 需要为 SKStoreReviewController 自定义弹出警报
- kotlin - 如何使用数组读取存储到 Firestore 的数据?
- c# - 如何在 .net 核心中使用 cert.pem、private.key 创建 pfx 文件
- laravel - Laravel api sanctum CSRF 令牌在 chorme 中不匹配
- c# - 将列表与另一个列表进行比较并获取匹配项
- node.js - npm 错误!无法确定要运行的可执行文件