AVFoundation旋转屏幕 - 对象C

时间:2016-05-09 05:43:47

标签: ios objective-c avfoundation transform video-processing

我正在努力改变视频的方向。它以纵向录制,但随后以横向格式保存。更改变换只会使视频在横向视频中旋转。在这个使用M_PI_2的示例中,它从屏幕旋转或平坦时消失。但是,如果我将其更改为M_PI_2 / 2或其出现的但是弯曲的东西。我知道AVFoundation默认会这样做。我该如何改变?我从本教程中获得了很多代码:https://www.raywenderlich.com/30200/avfoundation-tutorial-adding-overlays-and-animations-to-videos但是使用AVMutableVideoCompositionLayerInstruction无效。

AVMutableCompositionTrack *videoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
                                                                    preferredTrackID:kCMPersistentTrackID_Invalid];
CMTime insertTime = kCMTimeZero;
for(AVAsset *videoAsset in self.videoArray){
    [videoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] atTime:insertTime error:nil];
    // Updating the insertTime for the next insert
    insertTime = CMTimeAdd(insertTime, videoAsset.duration);
}
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(M_PI_2);
videoTrack.preferredTransform = rotationTransform;

// 3.1 - Create AVMutableVideoCompositionInstruction
AVMutableVideoCompositionInstruction *mainInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
mainInstruction.timeRange = videoTrack.timeRange;

// 3.2 - Create an AVMutableVideoCompositionLayerInstruction for the video track and fix the orientation.
AVMutableVideoCompositionLayerInstruction *videolayerInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack:videoTrack];
AVAssetTrack *videoAssetTrack = [[videoTrack.asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];

UIImageOrientation videoAssetOrientation_  = UIImageOrientationUp;
BOOL isVideoAssetPortrait_  = NO;

CGAffineTransform videoTransform = videoAssetTrack.preferredTransform;
if (videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0) {
    videoAssetOrientation_ = UIImageOrientationRight;
    isVideoAssetPortrait_ = YES;
}
if (videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0) {
    videoAssetOrientation_ =  UIImageOrientationLeft;
    isVideoAssetPortrait_ = YES;
}
if (videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0) {
    videoAssetOrientation_ =  UIImageOrientationUp;
}
if (videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0) {
    videoAssetOrientation_ = UIImageOrientationDown;
}

//CGAffineTransform rotationTransform = videoAssetTrack.preferredTransform;

[videolayerInstruction setTransform:videoAssetTrack.preferredTransform atTime:kCMTimeZero];
[videolayerInstruction setOpacity:0.0 atTime:videoTrack.timeRange.duration];

有没有办法设置锚点或进行自己的转换?

1 个答案:

答案 0 :(得分:4)

检查https://developer.apple.com/library/content/qa/qa1744/_index.html,这是使用AVFoundation设置视频方向的官方说明。简单来说,您需要使用AVMutableVideoCompositionLayerInstruction对象来修改要应用于视频合成中给定轨道的变换。
然后让我们谈谈你应该应用的转换。有这么多人建议使用AVAssetTrack的首选变换。在大多数情况下,它可以工作,您应该使用它来获取assetTrack的视频方向。但有时preferredTransform可能缺乏tx(ty)的值(如果你不知道什么是tx(ty),你应该检查Apple API Reference中的CGAffineTransform)或者tx(ty)有不准确的值导致错误的视频定位。登记/> 所以主要的想法是:使用preferredTransform来确定原始视频方向并进行自己的转换 这是获取轨道方向的代码:

- (UIInterfaceOrientation)orientationForTrack:(AVAsset *)asset {
    UIInterfaceOrientation orientation = UIInterfaceOrientationPortrait;
    NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];

    if([tracks count] > 0) {
        AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
        CGAffineTransform t = videoTrack.preferredTransform;

        // Portrait
        if(t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0) {
            orientation = UIInterfaceOrientationPortrait;
        }
        // PortraitUpsideDown
        if(t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0) {
            orientation = UIInterfaceOrientationPortraitUpsideDown;
        }
        // LandscapeRight
        if(t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0) {
            orientation = UIInterfaceOrientationLandscapeRight;
        }
        // LandscapeLeft
        if(t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0) {
            orientation = UIInterfaceOrientationLandscapeLeft;
        }
    }
    return orientation;
}

用于获取所需变换的代码:

- (CGAffineTransform)transformBasedOnAsset:(AVAsset *)asset {
    UIInterfaceOrientation orientation = [AVUtilities orientationForTrack:asset];
    AVAssetTrack *assetTrack = [asset tracksWithMediaType:AVMediaTypeVideo][0];
    CGSize naturalSize = assetTrack.naturalSize;
    CGAffineTransform finalTranform;
    switch (orientation) {
        case UIInterfaceOrientationLandscapeLeft:
            finalTranform = CGAffineTransformMake(-1, 0, 0, -1, naturalSize.width, naturalSize.height);
            break;
        case UIInterfaceOrientationLandscapeRight:
            finalTranform = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
            break;
        case UIInterfaceOrientationPortrait:
            finalTranform = CGAffineTransformMake(0, 1, -1, 0, naturalSize.height, 0);
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            finalTranform = CGAffineTransformMake(0, -1, 1, 0, 0, naturalSize.width);
            break;
        default:
            break;
    }
    return finalTranform;
}

如果您感到困惑,我建议您首先拍摄不同方向的视频,然后使用NSStringFromCGAffineTransform()或其他内容打印出视频的首选变换以查看详细信息。