iOS AVPlayer从未做好准备

时间:2013-05-28 10:48:43

标签: ios avplayer

我正在使用此代码开始播放参考形成播放列表的本地视频块。

完全相同的代码适用于一个项目,但不适用于另一个项目。 在我正在进行的项目中,我可以看到第一个块是如何加载的,第一个框架也会显示出来。但AVPlayer永远不会开始播放,因为它永远不会收到AVPlayerStatusReadyToPlay通知:

- (void)loadAssetAsync
{
    NSLog(@"loadAssetAsync for URL: %@", videoURL);

    /**
     * Create an asset for inspection of a resource referenced by a given URL.
     * Load the values for the asset keys "tracks", "playable".
     */
    AVURLAsset *asset = [AVURLAsset URLAssetWithURL:videoURL options:nil];

    NSArray *requestedKeys = [NSArray arrayWithObjects:kTracksKey, kPlayableKey, nil];

    // Tells the asset to load the values of any of the specified keys that are not already loaded.
    [asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:
     ^{
         dispatch_async( dispatch_get_main_queue(),
                        ^{
                            // IMPORTANT: Must dispatch to main queue in order to operate on the AVPlayer and AVPlayerItem.
                            [self prepareToPlayAsset:asset withKeys:requestedKeys];

                        });
     }];
}
/**
 * Invoked at the completion of the loading of the values for all keys on the asset that required.
 */
- (void)prepareToPlayAsset:(AVURLAsset *)asset withKeys:(NSArray *)requestedKeys
{
    //assert([NSThread isMainThread]);

    // Make sure that the value of each key has loaded successfully.
    for (NSString *thisKey in requestedKeys)
    {
        NSError *error = nil;
        AVKeyValueStatus keyStatus = [asset statusOfValueForKey:thisKey error:&error];
        if (keyStatus == AVKeyValueStatusFailed)
        {
            BVLogWarn(@"%@: %@", THIS_FILE, error.localizedDescription);

            [self handleErrorForProxy:error];

            [self assetFailedToPrepareForPlayback];
            return;
        }
    }

    if (!asset.playable)
    {
        BVLogWarn(@"%@: Item cannot be played", THIS_FILE);

        [self handleErrorForProxy:nil];

        [self assetFailedToPrepareForPlayback];
        return;
    }

    // Create a new instance of AVPlayerItem from the now successfully loaded AVAsset.
    playerItem = [[AVPlayerItem alloc] initWithAsset:asset];

    // Observe the player item "status" key to determine when it is ready to play.
    [playerItem addObserver:self
                 forKeyPath:kStatusKey
                    options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                    context:BVPlayerItemStatusObserverContext];

    [playerItem addObserver:self
                 forKeyPath:kBufferEmpty
                    options:NSKeyValueObservingOptionNew
                    context:BVPLayerBufferEmptyObserverContext];

    [playerItem addObserver:self
                 forKeyPath:kLikelyToKeepUp
                    options:NSKeyValueObservingOptionNew
                    context:BVPlayerLikelyToKeepUpObserverContext];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd:)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:playerItem];


    // Get a new AVPlayer initialized to play the specified player item.
    player = [[AVPlayer alloc] initWithPlayerItem:playerItem];

    // Do nothing if the item has finished playing
    [player setActionAtItemEnd:AVPlayerActionAtItemEndNone];

    /* Observe the AVPlayer "currentItem" property to find out when any
     AVPlayer replaceCurrentItemWithPlayerItem: replacement will/did
     occur.*/
    [player addObserver:self
             forKeyPath:kCurrentItemKey
                options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                context:BVCurrentItemObserverContext];

    // Observe the AVPlayer "rate" property to update the scrubber control.
    [player addObserver:self
             forKeyPath:kRateKey
                options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                context:BVRateObserverContext];

    [player replaceCurrentItemWithPlayerItem:playerItem];
}

- (void)observeValueForKeyPath:(NSString*) keyPath
                      ofObject:(id)object
                        change:(NSDictionary*)change
                       context:(void*)context
{
    // AVPlayerItem "status" property value observer.
    if (context == BVPlayerItemStatusObserverContext)
    {
        AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
        switch (status)
        {
            case AVPlayerStatusUnknown:
            {
                [self removeTimeObserver];

                [self syncTimeScrubber];

                [timeControl setEnabled:NO];
                [playButton setEnabled:NO];
                [fullscreenButton setEnabled:NO];

                [loadingIndicator startAnimating];
            }
                break;

            case AVPlayerStatusReadyToPlay:
            {

                if (firstPlayback|becomeActive)
                {
                    [timeControl setEnabled:YES];
                    [playButton setEnabled:YES];
                    [fullscreenButton setEnabled:YES];
                    [upperControls setHidden:NO];
                    [lowerControls setHidden:NO];
                    [loadingIndicator stopAnimating];

                    if (firstPlayback) {
                        [playbackView setNeedsDisplay];
                    }

                    if (self.shouldAutoplay)
                        [player play];

                    if (firstPlayback) {
                        timeRemaining.text = [NSString stringWithFormat:@"-%@", timeStringForSeconds(CMTimeGetSeconds(playerItem.duration) )];
                    }

                    firstPlayback = NO;
                    controlsHidden = NO;

                    if (!isSeeking)
                        [self startHideControlsTimer];

                }

                if (becomeActive) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [player seekToTime:CMTimeMakeWithSeconds(lastTimeStop, NSEC_PER_SEC)
                           toleranceBefore:kCMTimeZero
                            toleranceAfter:kCMTimeZero
                         completionHandler:^(BOOL finished) {
                             if (finished && rateToRestoreAfterScrubbing)
                             {
                                 [player setRate:rateToRestoreAfterScrubbing];
                                 rateToRestoreAfterScrubbing = 0.f;
                             }
                             [self addTimeObserver];
                             [playbackView setPlayer:player];
                             becomeActive = NO;
                         }];
                    });

                }else{
                    [self addTimeObserver];
                }
            }
                break;

            case AVPlayerStatusFailed:
            {
                AVPlayerItem *thePlayerItem = (AVPlayerItem *)object;
                BVLogWarn(@"%@: %@", THIS_FILE, thePlayerItem.error.localizedDescription);

                [self handleErrorForProxy:thePlayerItem.error];

                [self assetFailedToPrepareForPlayback];
            }
                break;
        }
    }
    // AVPlayer "rate" property value observer.
    else if (context == BVRateObserverContext)
    {
        [self updatePlayPauseButton];
    }
    // AVPlayer "currentItem" buffer is empty observer
    else if (context == BVPLayerBufferEmptyObserverContext)
    {
        [loadingIndicator startAnimating];
    }
    // AVPlayer "currentItem" is likely to keep up observer
    else if (context == BVPlayerLikelyToKeepUpObserverContext)
    {
        [loadingIndicator stopAnimating];
    }
    // AVPlayer "currentItem" property observer.
    else if (context == BVCurrentItemObserverContext)
    {
        AVPlayerItem *newPlayerItem = [change objectForKey:NSKeyValueChangeNewKey];

        // New player item null?
        if (newPlayerItem == (id)[NSNull null])
        {
            [playButton setEnabled:NO];
            [timeControl setEnabled:NO];

        } else  // Replacement of player currentItem has occurred
        {

            if (!becomeActive) {
                [playbackView setPlayer:player];
            }else{

            }


            [playbackView setVideoFillMode:[self scalingMode]];

            [self updatePlayPauseButton];
        }
    }
    else
    {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }

    return;
}

1 个答案:

答案 0 :(得分:0)

您是否尝试在if之前添加一些日志?也许通知工作正常,但因为你的if?

而被停止了
case AVPlayerStatusReadyToPlay:
{
  NSLog(@"NOTIFICATION TEST PASSED");
  if (firstPlayback|becomeActive) {}
}