2014-07-15 40 views
0

我想在我的游戏开始时播放电影。我正在使用AVPlayer来做到这一点。我的问题是,当我注册一个KVO来检查我的AVPlayer的状态时,我的游戏照常进行,无需等待视频加载并完成。因此,我只能听到我的.mov文件中的音频,并且看不到任何视频(因为我的游戏已经开始)。 我希望视频在继续游戏之前加载并完成。 下面的代码:AVPlayer不显示视频

@interface RMVideoView : NSView 
{ 
    NSURL* _videoURL; 
    AVPlayer* _player; 
    AVPlayerLayer* _playerLayer; 
} 

@property (nonatomic, readonly, strong) AVPlayer* player; 
@property (nonatomic, readonly, strong) AVPlayerLayer* playerLayer; 
@property (nonatomic, retain) NSURL* videoURL; 
- (void) play; 
@end 

static void *RMVideoViewPlayerLayerReadyForDisplay = &RMVideoViewPlayerLayerReadyForDisplay; 
static void *RMVideoViewPlayerItemStatusContext = &RMVideoViewPlayerItemStatusContext; 

@interface RMVideoView() 

- (void)onError:(NSError*)error; 
- (void)onReadyToPlay; 
- (void)setUpPlaybackOfAsset:(AVAsset *)asset withKeys:(NSArray *)keys; 

@end 

@implementation RMVideoView 

@synthesize player = _player; 
@synthesize playerLayer = _playerLayer; 
@synthesize videoURL = _videoURL; 

- (id)initWithFrame:(NSRect)frame { 
    self = [super initWithFrame:frame]; 
    if (self) { 
     self.wantsLayer = YES; 
     _player = [[AVPlayer alloc] init]; 
     [self addObserver:self forKeyPath:@"player.currentItem.status" options:NSKeyValueObservingOptionNew context:RMVideoViewPlayerItemStatusContext]; 
    } 

    return self; 
} 

- (void) setVideoURL:(NSURL *)videoURL { 
    _videoURL = videoURL; 

    [self.player pause]; 
    [self.playerLayer removeFromSuperlayer]; 

    AVURLAsset *asset = [AVAsset assetWithURL:self.videoURL]; 

    [asset retain]; 


    NSArray *assetKeysToLoadAndTest = [NSArray arrayWithObjects:@"playable", @"hasProtectedContent", @"tracks", @"duration", nil]; 
    [asset loadValuesAsynchronouslyForKeys:assetKeysToLoadAndTest completionHandler:^{ 
     dispatch_async(dispatch_get_main_queue(),^{ 
      [self setUpPlaybackOfAsset:asset withKeys:assetKeysToLoadAndTest]; 
     }); 
    }]; 
} 

#pragma mark - KVO 
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 
    if (context == RMVideoViewPlayerItemStatusContext) 
    { 
     AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue]; 
     switch (status) 
     { 
      case AVPlayerItemStatusUnknown: 
       break; 
      case AVPlayerItemStatusReadyToPlay: 
       [self onReadyToPlay]; 
       break; 
      case AVPlayerItemStatusFailed: 
       [self onError:nil]; 
       break; 
     } 
    } 
    else if (context == RMVideoViewPlayerLayerReadyForDisplay) 
    { 
     if ([[change objectForKey:NSKeyValueChangeNewKey] boolValue]) 
     { 
      self.playerLayer.hidden = NO; 
     } 
    } 
    else 
    { 
     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
    } 
} 

#pragma mark - Private 

- (void)onError:(NSError*)error { 
    // Notify delegate 
} 

- (void)onReadyToPlay { 
    // Notify delegate 
    [self.player play]; 
} 

- (void)setUpPlaybackOfAsset:(AVAsset *)asset withKeys:(NSArray *)keys { 
    for (NSString *key in keys) { 
     NSError *error = nil; 
     if ([asset statusOfValueForKey:key error:&error] == AVKeyValueStatusFailed) { 
      [self onError:error]; 
      return; 
     } 
    } 

    if (!asset.isPlayable || asset.hasProtectedContent) { 
     [self onError:nil]; 
     return; 
    } 

    if ([[asset tracksWithMediaType:AVMediaTypeVideo] count] != 0) 
    { // Asset has video tracks 
     _playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; 
     self.playerLayer.frame = self.layer.bounds; 
     self.playerLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable; 
     self.playerLayer.hidden = NO; 
     [self.layer addSublayer:self.playerLayer]; 
     [self addObserver:self forKeyPath:@"playerLayer.readyForDisplay" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:RMVideoViewPlayerLayerReadyForDisplay]; 

    } 

    // Create a new AVPlayerItem and make it our player's current item. 
    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset]; 
    [self.player replaceCurrentItemWithPlayerItem:playerItem]; 
} 
#pragma mark - Public 

- (void) play { 
    [self.player play]; 
} 

@end 

我打电话从我的入口函数的上面的代码 - (空)drawView函数是这样的:

-(void)drawView 
{ 
    if(playVideo) 
    { 
     RMVideoView *rmVid = [[RMVideoView alloc]init]; 

     NSURL* MovieURL; 
     NSBundle *bundle = [NSBundle mainBundle]; 
     if(bundle != nil) 
     { 
      NSString *moviePath = [bundle pathForResource:@"MyVideoResource" ofType:@"mov"]; 
      if (moviePath) 
      { 
       MovieURL = [NSURL fileURLWithPath:moviePath]; 
       [MovieURL retain]; 
       [rmVid setVideoURL:MovieURL]; 
      } 
     } 
     playVideo = kFalse; 
    } 
} 

为[rmVid setVideoURL:MovieURL]所做的调用返回时KVO设置并且游戏向前运行。 请帮忙!

回答

0

您可以侦听通知,当视频播放达到这样的结尾:

  AVPlayerItem *avPlayerItem =[[AVPlayerItem alloc]initWithAsset:avAsset]; 
     [[NSNotificationCenter defaultCenter] addObserver:self 
                selector:@selector(playerItemDidReachedEnd:) 
                 name:AVPlayerItemDidPlayToEndTimeNotification 
                object:avPlayerItem];