AVVideoCompositionCoreAnimationTool и CALayer в портретном режиме?

Я пытаюсь запечь CALayer в портретном режиме (при экспорте) с помощью AVMutableComposition, AVMutableVideoComposition и AVVideoCompositionCoreAnimationTool на iOS 4.3. Все это работает в ландшафтном режиме. Однако при портретном захвате видео инструмент AVVideoCompositionCoreAnimationTool игнорирует трансформацию на видеодорожке. То есть, для видео в портретном режиме, я устанавливаю AVMutableCompositionTrack.preferredTransform в значение preferredTransform из исходного видео трека активов. Пока я не использую AVVideoCompositionCoreAnimationTool, это работает, и видео выходит в портретном режиме. Однако, как только я добавляю AVVideoCompositionCoreAnimationTool и CALayer, файл выходит в альбомном режиме. (CALayer появляется правильно, но видео позади него находится на его стороне, и соотношение сторон файла выключено). Я попробовал применить преобразование к CALayerу и установить преобразование в ACVideoComposition. Ни то, ни другое не меняет ориентацию создаваемого файла (это все равно 480x369, а не 360x480). Есть ли способ рендерить портретное видео с помощью AVVideoCompositionCoreAnimationTool?

Сначала я настраиваю AVMutableComposition и AVMutableVideoComposition

AVMutableComposition *composition = [AVMutableComposition composition];
AVMutableCompositionTrack *compositionVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
AVURLAsset *videoAsset = [AVURLAsset URLAssetWithURL:url options:nil];
CMTimeRange timeRange = CMTimeRangeMake(kCMTimeZero, [videoAsset duration]);
AVAssetTrack *clipVideoTrack = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

CGSize videoSize = CGSizeApplyAffineTransform(clipVideoTrack.naturalSize, clipVideoTrack.preferredTransform);
videoSize.width = fabs(videoSize.width);
videoSize.height = fabs(videoSize.height);

CMTime titleDuration = CMTimeMakeWithSeconds(5, 600);
CMTimeRange titleRange = CMTimeRangeMake(kCMTimeZero, titleDuration);

[compositionVideoTrack insertTimeRange:titleRange ofTrack:nil atTime:kCMTimeZero error:nil];
[compositionVideoTrack insertTimeRange:timeRange ofTrack:clipVideoTrack atTime:titleDuration error:nil];
compositionVideoTrack.preferredTransform = clipVideoTrack.preferredTransform;

AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
AVMutableVideoCompositionInstruction *passThroughInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
passThroughInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, [composition duration]);
AVAssetTrack *videoTrack = [[composition tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
AVMutableVideoCompositionLayerInstruction *passThroughLayer = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];    
passThroughInstruction.layerInstructions = [NSArray arrayWithObject:passThroughLayer];
videoComposition.instructions = [NSArray arrayWithObject:passThroughInstruction];       
videoComposition.frameDuration = CMTimeMake(1, 30); 
videoComposition.renderSize = videoSize;
videoComposition.renderScale = 1.0;

И CALayer с названием

CALayer *animationLayer = [CALayer layer];
animationLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height);

CATextLayer *titleLayer = [CATextLayer layer];
titleLayer.string = [effect valueForKey:@"title"];
titleLayer.font = [effect valueForKey:@"font"];
titleLayer.fontSize = 30;

titleLayer.alignmentMode = kCAAlignmentCenter;
titleLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height / 6);

[animationLayer addSublayer:titleLayer];
titleLayer.anchorPoint =  CGPointMake(0.5, 0.5);
titleLayer.position = CGPointMake(CGRectGetMidX(layer.bounds), CGRectGetMidY(layer.bounds));    

CABasicAnimation *fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeAnimation.fromValue = [NSNumber numberWithFloat:1.0];
fadeAnimation.toValue = [NSNumber numberWithFloat:0.0];
fadeAnimation.additive = NO;
fadeAnimation.removedOnCompletion = NO;
fadeAnimation.beginTime = 3.5;
fadeAnimation.duration = 1.0;
fadeAnimation.fillMode = kCAFillModeBoth;
[titleLayer addAnimation:fadeAnimation forKey:nil];

Наконец, я добавляю CALayer в AVMutableVideoComposition

CALayer *parentLayer = [CALayer layer];
CALayer *videoLayer = [CALayer layer];

parentLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height);
parentLayer.anchorPoint =  CGPointMake(0, 0);
parentLayer.position = CGPointMake(0, 0);

videoLayer.bounds = CGRectMake(0, 0, videoSize.width, videoSize.height);
[parentLayer addSublayer:videoLayer];
videoLayer.anchorPoint =  CGPointMake(0.5, 0.5);
videoLayer.position = CGPointMake(CGRectGetMidX(parentLayer.bounds), CGRectGetMidY(parentLayer.bounds));
[parentLayer addSublayer:layer];    
animationLayer.anchorPoint =  CGPointMake(0.5, 0.5);
animationLayer.position = CGPointMake(CGRectGetMidX(parentLayer.bounds), CGRectGetMidY(parentLayer.bounds));
videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

И экспортирую!

AVAssetExportSession *exportSession = [[[AVAssetExportSession alloc] initWithAsset:composition presetName:AVAssetExportPresetMediumQuality] autorelease];
exportSession.videoComposition = videoComposition; 

NSURL *segmentFileURL = //some local URL
exportSession.outputFileType = @"com.apple.quicktime-movie";
exportSession.outputURL = segmentFileURL;


[exportSession exportAsynchronouslyWithCompletionHandler:^{
    switch ([exportSession status]) {
        case AVAssetExportSessionStatusFailed:
            Log(@"Export failed: %@", [exportSession error]);
            break;
        case AVAssetExportSessionStatusCancelled:
            Log(@"Export canceled");
            break;
        case AVAssetExportSessionStatusCompleted:
            Log(@"Export done");
            break;
    }
}]; 

Этот код работает в ландшафтном режиме, а также в портретном, если я удалю строку videoComposition.animationTool = [AVVideoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

14
задан wombat57 8 August 2011 в 22:59
поделиться