2013-06-12 47 views
4

我正在使用AVCaptureSession来记录视频,使用AVAssetWriterInput我正在将视频写入文件。
我的问题是与视频方向,使用苹果RosyWriter的例子,我可以转换AVAssetWriterInput所以视频将在正确的方向。AVCaptureSession前置摄像头方向

- (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发生变化,并且我获得了前凸轮和后凸轮的不同方向。

所以也许我需要调整后面和前面凸轮的初始方向之间的差异。
我真的不想每次用户切换摄像头时都改变连接的方向,因为苹果说它会伤害到性能(而且当我这样做的时候看起来很糟糕),所以 因此苹果公司建议使用AVAssetWriterInputtransform属性来改变输出方向,但我不知道我可以使用transform,因为我想让用户在录制时切换相机,但在我开始写入(它崩溃)后我不能更改transform ...

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

回答

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; 
} 
+0

这不是一个镜像问题,所有的框架是颠倒.. – Eyal

+0

检查出编辑..你甚至尝试了顺便说一句吗? –

+0

再次思考我不确定我可以使用AVAssetWriterInput转换,我想让用户在录制时切换相机,但是我无法在开始写入(崩溃)时更改AVAssetWriterInput转换,所以我认为我没有选择,但是改变AVCaptureConnection方向(我知道它会伤害性能),你不觉得吗? – Eyal

0

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

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

请注意,AVAssetWriterInputtransform属性仅适用于iPhone。比方说,如果您使用AVFoundation录制视频并将其上传到浏览器中并观看,它将会有错误的方向。所以,如果你经历了一个彻底的解决方案,那么你自己的转变就是要走的路。

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

相关问题