changsanjiang / SJBaseVideoPlayer

video player. rotation, volume, brightness, rate, play, pause, stop, seekToTime, present.
MIT License
128 stars 52 forks source link

进入AVPlayerStatusFailed的playerItem重新播放会导致崩溃. #18

Closed hootigger closed 3 years ago

hootigger commented 3 years ago
  1. 通过 player.urlAsset = SJVideoPlayerURLAsset(avPlayerItem: item)这种方式初始化asset的,如果是弱网环境导致avPlayerItem.status == AVPlayerStatusFailed,再次进行play的时候,会进入重新创建avPlayer的逻辑.
AVPlayer *avPlayer = target.avPlayer;
    if ( avPlayer == nil ) {
        AVPlayerItem *avPlayerItem = target.avPlayerItem;
        if ( avPlayerItem == nil ) {
            AVAsset *avAsset = target.avAsset;
            if ( avAsset == nil ) {
                avAsset = [AVURLAsset URLAssetWithURL:target.mediaURL options:nil];
            }
            avPlayerItem = [AVPlayerItem playerItemWithAsset:avAsset];
        }
       // 这里导致崩溃  An AVPlayerItem cannot be associated with more than one instance of AVPlayer'
        avPlayer = [AVPlayer playerWithPlayerItem:avPlayerItem];
    }

原因是一旦Item与AVPlayer绑定,就无法再与其他player绑定. 其次进入 AVPlayerStatusFailed 状态的Item好像也无法再被正确缓冲播放(即使网络已经恢复)

if ( avPlayer == nil ) {
        AVPlayerItem *avPlayerItem = target.avPlayerItem;
        // 处理上述所说的情况
        if (avPlayerItem != nil && avPlayerItem.status == AVPlayerStatusFailed) {
            NSURL *url = [avPlayerItem valueForKey:@"_URL"];
            avPlayerItem = [AVPlayerItem playerItemWithURL: url];
        }
        if ( avPlayerItem == nil ) {
       ...

但是这样处理有一个问题,SJVideoPlayerURLAsset中的avPlayerItem和实际的不一致. 所以暂时 使用KVC进行同步数据.

if ( avPlayer == nil ) {
        AVPlayerItem *avPlayerItem = target.avPlayerItem;
        // 处理上述所说的情况
        if (avPlayerItem != nil && avPlayerItem.status == AVPlayerStatusFailed) {
            NSURL *url = [avPlayerItem valueForKey:@"_URL"];
            avPlayerItem = [AVPlayerItem playerItemWithURL: url];
           [target setValue:avPlayerItem forKey:@"avPlayerItem"];
        }
        if ( avPlayerItem == nil ) {
       ...

已经提交pr.