AVCaptureSession前置摄像头方向

时间:2013-06-12 09:56:18

标签: iphone ios objective-c avfoundation avassetwriter

我正在使用AVCaptureSession来录制视频,使用AVAssetWriterInput我正在将视频写入文件。
我的问题在于视频方向,使用Apple RosyWriter示例,我可以转换AVAssetWriterInput,以便视频的方向正确。

- (CGFloat)angleOffsetFromPortraitOrientationToOrientation:(AVCaptureVideoOrientation)orientation
{
    CGFloat angle = 0.0;

    switch (orientation) {
        case AVCaptureVideoOrientationPortrait:
            angle = 0.0;
            break;
        case AVCaptureVideoOrientationPortraitUpsideDown:
            angle = M_PI;
            break;
        case AVCaptureVideoOrientationLandscapeRight:
            angle = -M_PI_2;
            break;
        case AVCaptureVideoOrientationLandscapeLeft:
            angle = M_PI_2;
            break;
        default:
            break;
    }

    return angle;
}

- (CGAffineTransform)transformFromCurrentVideoOrientationToOrientation:(AVCaptureVideoOrientation)orientation
{
    CGAffineTransform transform = CGAffineTransformIdentity;

    // Calculate offsets from an arbitrary reference orientation (portrait)
    CGFloat orientationAngleOffset = [self angleOffsetFromPortraitOrientationToOrientation:orientation];
    CGFloat videoOrientationAngleOffset = [self angleOffsetFromPortraitOrientationToOrientation:self.videoOrientation];

    // Find the difference in angle between the passed in orientation and the current video orientation
    CGFloat angleOffset = orientationAngleOffset - videoOrientationAngleOffset;
    transform = CGAffineTransformMakeRotation(angleOffset);

    return transform;
}  

问题在于前置摄像头方向,使用此代码后用户更换前置摄像头后无法使用。

似乎导致问题的原因是当我将凸轮改为前方时,AVCaptureConnection发生变化,前凸轮和后凸轮的方向不同。

所以我可能需要调整背部和前部凸轮的初始方向之间的差异 我不想在每次用户切换凸轮时都改变连接的方向,因为苹果公司说这会伤害性能(当我这样做时它看起来确实很糟糕), 因此,Apple建议使用AVAssetWriterInput transform属性来更改输出方向,但我不确定我是否可以使用transform,因为我想让用户切换相机录制时但我开始写作后它无法更改transform(崩溃)......

任何想法如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

由于来自前置摄像头的图像是镜像的,因此您还需要镜像转换。执行此操作的功能只是使用-1缩放其中一个维度。尝试玩这个:

transform = CGAffineTransformConcat(CGAffineTransformMakeRotation(angle), CGAffineTransformMakeScale(1.0, -1.0));

注意可能的排列是(旁边角度)X比例因子是-1和/或交换concat的顺序

编辑:解释

AVCaptureSession将返回您设备不旋转的图像数据,我自然相信这将是横向左侧或右侧。如果您需要视频的正确方向取决于您握住设备的方式,则需要对其应用一些变换,在大多数情况下,只需应用一些旋转就足够了。但是,前置摄像头是一种特殊情况,因为它在您仍在接收非镜像帧时模拟镜像。结果你的视频似乎是上下左右或所有其他组合取决于你正在应用的旋转,因此你说“我尝试了很多角度,但我不能得到对的...”。同样,要模拟镜面效果,您应该将轴中的一个缩放-1。

编辑:交换方向(来自评论)

这只是一个想法,我认为这是一个好主意。不要使用资产转换,做自己的。创建一个您想要视频大小的视图,然后使用您需要的所有变换,剪辑和内容模式为其创建图像视图子视图。从示例中,您可以创建图像,将它们设置为图像视图,并从视图中获取图层快照。然后将快照发送给资产编写者。

我知道你在想什么是“开销”。好吧,我不这么认为。由于视图和图像视图在CPU上的转换与资产编写者相同,因此您所做的就是取消其内部转换并使用您自己的系统。如果你试试这个,我非常想听听你的结果。

获取图层图像:

- (UIImage *)imageFromLayer:(CALayer *)layer {
    UIGraphicsBeginImageContext([layer frame].size);
    [layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return outputImage;
}

答案 1 :(得分:0)

不是最简单的方法,但我认为如果你截取框架并执行自己的转换,它肯定会有效。你不需要任何UIView - AVFoundation允许直接访问和操作它的框架(如果需要,你可以在写入文件时替换自己的缓冲区)。我看到的唯一缺点是性能。即使在旧设备和高分辨率下翻转图像也可能非常慢。

如果这确实损害了性能,您可以按原样保存视频,并为每个帧维护单独的方向阵列。保存视频后,重新打开视频,对每个帧执行转换,并将其保存到新文件中。我做了类似的事情,确实有效。

在旁注中,AVAssetWriterInput的{​​{1}}属性仅适用于iPhone。例如,如果您使用AVFoundation录制视频并将其上传到某个地方并在浏览器中观看,则会出现错误的方向。因此,如果您正在彻底解决问题,那么您自己的转型是可行的方法。

如果您经常进行视频/图像处理(例如在这种情况下,翻转/旋转),请考虑OpenCV库。这需要一些时间来学习,但这是值得的。