【问题标题】:AVCaptureSession front camera orientationAVCaptureSession 前置摄像头方向
【发布时间】:2013-06-08 09:26:52
【问题描述】:

我正在使用AVCaptureSession 录制视频,使用AVAssetWriterInput 我正在将视频写入文件。
我的问题是视频方向,使用苹果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 所说的那样它会损害性能(而且当我这样做时确实看起来很糟糕), 所以Apple建议使用AVAssetWriterInputtransform属性来改变输出方向,但我不确定我可以使用transform,因为我想让用户在录制时切换相机但我不能改变我开始写作后的transform(它崩溃了)......

有什么办法解决这个问题吗?

【问题讨论】:

    标签: iphone ios objective-c avfoundation avassetwriter


    【解决方案1】:

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

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

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

    编辑:解释

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

    编辑:交换方向(来自 cmets)

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

    我知道您在这里的想法是“开销”。嗯,我不这么认为。由于视图和图像视图在 CPU 上进行转换,资产编写器也是如此,所以您所做的就是取消其内部转换并使用您自己的系统。如果你愿意尝试这个,我非常想听听你的结果。

    获取图层图像:

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

    【讨论】:

    • 再想一想我不确定我是否可以使用 AVAssetWriterInput 转换,我想让用户在录制时切换相机但我无法在开始写入后更改 AVAssetWriterInput 转换(它崩溃),所以我认为我别无选择,只能更改 AVCaptureConnection 方向(我知道这会损害性能),你不觉得吗?
    • 如果它会起作用,它应该不会太糟糕。这里更好的问题是当样本具有不同的分辨率时会发生什么。无论如何,如果您交换相机,您可以开始一个新视频,然后在用户停止录制时将它们全部添加在一起..
    【解决方案2】:

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

    如果这确实会影响性能,您可以按原样保存视频,并为每一帧保留一个单独的方向数组。保存视频后,重新打开它,对每一帧执行转换,然后将其保存到新文件中。我做过类似的事情,它确实有效。

    附带说明,AVAssetWriterInputtransform 属性仅适用于 iPhone。例如,如果您使用 AVFoundation 录制视频并将其上传到某处并在浏览器中观看,那么它将有错误的方向。因此,如果您正在寻求彻底的解决方案,那么您自己的转变就是要走的路。

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

    【讨论】:

      猜你喜欢
      • 2015-10-31
      • 2012-02-19
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      • 1970-01-01
      • 2020-09-17
      • 2021-03-14
      • 1970-01-01
      相关资源
      最近更新 更多