2014-07-15 3 views
0

게임 시작시에 영화를 재생하려고합니다. 나는 이것을하기 위해 AVPlayer를 사용하고있다. 내 문제는 AVPlayer의 상태를 확인하기 위해 KVO를 등록 할 때 비디오가로드되고 끝날 때까지 기다리지 않고 내 게임이 정상적으로 진행된다는 것입니다. 결과적으로 내 .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];