首页 > 解决方案 > 调用 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 没有状态变化也没有失败通知

标签: iosobjective-cavplayertvosavassetresourceloaderdelegate

解决方案


推荐阅读