2012-05-19 7 views
6

再生中にビデオコンポジションのレイアウト(コンポーネントフレームのトランスフォーム)を変更しようとしています。時にはこれが機能し、ビデオコンポジションが新しいトランスフォームセットにシームレスに変更されるようですが、それ以外の時はフリーズして現在のトランスフォームにとどまります。 AVPlayerインスタンスにステータスコードの変更はなく、プレーヤーまたはプレーヤーアイテムにエラーはありません。再生中にAVPlayerItemのvideoCompositionプロパティ(AVMutableVideoComposition)を変更する

誰もこれまでに経験したことがありますか?なぜこれが起こっているのか、それを回避する方法についての提案は感謝します。

いくつかのコードを以下に示します。重要なビットは 'playerItem.videoComposition = videoComposition'で、ここでビデオをタップすると(テスト目的で)トリガーされます。

この問題のもう1つの解決策は、ビデオを別々のレイヤーに表示することですが、ビデオが同期していることが不可欠であるため、これを達成する唯一の方法と思われます。

@implementation VideoView 
{ 
    CGSize _videoSize; 
    CMTimeRange _videoFullRange; 

    AVMutableCompositionTrack * _compositionTrackVideoA; 
    AVMutableCompositionTrack * _compositionTrackVideoB; 
} 

+ (Class)layerClass 
{ 
    return [AVPlayerLayer class]; 
} 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) 
    { 
     NSString * videoAPath = [[NSBundle mainBundle] pathForResource:@"cam09v2" ofType:@"mp4"]; 
     NSString * videoBPath = [[NSBundle mainBundle] pathForResource:@"cam10v2_b" ofType:@"mp4"]; 
     AVURLAsset * videoAAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:videoAPath] options:nil]; 
     AVURLAsset * videoBAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:videoBPath] options:nil]; 

     AVAssetTrack * videoATrack = [[videoAAsset tracksWithMediaType:AVMediaTypeVideo] lastObject]; 
     AVAssetTrack * videoBTrack = [[videoBAsset tracksWithMediaType:AVMediaTypeVideo] lastObject]; 
     AVAssetTrack * audioTrack = [[videoAAsset tracksWithMediaType:AVMediaTypeAudio] lastObject]; 

     _videoSize = [videoATrack naturalSize]; 
     CMTime videoDuration = videoAAsset.duration; 
     _videoFullRange = CMTimeRangeMake(kCMTimeZero, videoDuration); 

     AVMutableComposition *composition = [AVMutableComposition composition]; 
     AVMutableCompositionTrack * compositionTrackVideoA = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
     AVMutableCompositionTrack * compositionTrackVideoB = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; 
     AVMutableCompositionTrack * compositionTrackAudio = [composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; 

     compositionTrackVideoA.preferredTransform = videoATrack.preferredTransform; 

     NSError * error = nil; 
     if (! [compositionTrackVideoA insertTimeRange:_videoFullRange ofTrack:videoATrack atTime:kCMTimeZero error:&error]) 
      NSLog(@"%@", error); 

     if (! [compositionTrackVideoB insertTimeRange:_videoFullRange ofTrack:videoBTrack atTime:kCMTimeZero error:&error]) 
      NSLog(@"%@", error); 

     if (! [compositionTrackAudio insertTimeRange:_videoFullRange ofTrack:audioTrack atTime:kCMTimeZero error:&error]) 
      NSLog(@"%@", error); 

     _compositionTrackVideoA = [compositionTrackVideoA copy]; 
     _compositionTrackVideoB = [compositionTrackVideoB copy]; 

     AVPlayerItem * playerItem = [AVPlayerItem playerItemWithAsset:composition]; 

     AVPlayer * player = [AVPlayer playerWithPlayerItem:playerItem]; 

     [(AVPlayerLayer *)self.layer setPlayer:player]; 

     [player play]; 

     [player addObserver:self forKeyPath:@"status" options:0 context:0]; 

     [self updateCompositionForPlayerItem:playerItem]; 

     UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTap:)]; 
     [self addGestureRecognizer:tapGesture]; 
    } 
    return self; 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if ([keyPath isEqualToString:@"status"]) 
     NSLog(@"STATUS %d", ((AVPlayer *)object).status); 
} 

- (void)updateCompositionForPlayerItem:(AVPlayerItem *)playerItem 
{ 

    AVMutableVideoComposition * videoComposition = [AVMutableVideoComposition videoComposition]; 

    AVMutableVideoCompositionInstruction *videoInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; 
    videoInstruction.enablePostProcessing = NO; 
    videoInstruction.timeRange = _videoFullRange; 

    AVMutableVideoCompositionLayerInstruction * layerInstructionA = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:_compositionTrackVideoA]; 
    CGAffineTransform transformA = CGAffineTransformMakeScale(0.5, 0.5); 
    [layerInstructionA setTransform:transformA atTime:kCMTimeZero]; 
    AVMutableVideoCompositionLayerInstruction * layerInstructionB = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:_compositionTrackVideoB]; 
    CGAffineTransform transformB = CGAffineTransformMakeScale(0.5, 0.5); 
    static int i = 0; 
    transformB = CGAffineTransformTranslate(transformB, (i++ % 2 == 0) ? _videoSize.width : 0, _videoSize.height); 
    [layerInstructionB setTransform:transformB atTime:kCMTimeZero]; 

    videoInstruction.layerInstructions = [NSArray arrayWithObjects:layerInstructionA, layerInstructionB, nil]; 

    videoComposition.instructions = [NSArray arrayWithObject:videoInstruction]; 

    videoComposition.frameDuration = CMTimeMake(1, 30); // 30 fps 
    videoComposition.renderSize = _videoSize; 

    playerItem.videoComposition = videoComposition; 

} 

- (void)didTap:(UITapGestureRecognizer *)tapGesture 
{ 
    [self updateCompositionForPlayerItem:((AVPlayerLayer *)self.layer).player.currentItem]; 
} 

@end 

答えて

1

あなたはそれを変更し、新たな映像合成でプレーヤーのアイテムを交換し、あなたが遊んで立ち止まった時から新しいプレーヤーアイテムに再びプレイヤーを開始したい時間を節約することができます。

関連する問題