Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/122.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone AVCaptureSession前摄像头方向_Iphone_Ios_Objective C_Avfoundation_Avassetwriter - Fatal编程技术网

Iphone AVCaptureSession前摄像头方向

Iphone AVCaptureSession前摄像头方向,iphone,ios,objective-c,avfoundation,avassetwriter,Iphone,Ios,Objective C,Avfoundation,Avassetwriter,我正在使用AVCaptureSession录制视频,使用AVAssetWriterInput我正在将视频写入文件。 我的问题是视频方向,使用appleRosyWriter示例,我可以变换AVAssetWriterInput,使视频方向正确 - (CGFloat)angleOffsetFromPortraitOrientationToOrientation:(AVCaptureVideoOrientation)orientation { CGFloat angle = 0.0;

我正在使用
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
会发生变化,并且前凸轮和后凸轮的方向不同

因此,我可能需要调整前后凸轮的初始方向之间的差异。
我真的不想每次用户切换摄像头时都改变连接的方向,因为正如苹果公司所说的那样,这会影响性能(事实上,当我这样做时,它看起来很糟糕), 因此,苹果建议使用
AVAssetWriterInput
transform
属性来更改输出方向,但我不确定是否可以使用
transform
,因为我想让用户在录制时切换相机,但我无法在开始编写后更改
transform
(它崩溃了)


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

因为前摄像头的图像是镜像的,所以你也需要镜像变换。实现这一点的函数只是用-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;
}

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

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

另一方面,
AVAssetWriterInput
transform
属性仅适用于iPhone。比如说,如果你用AVFoundation录制了一段视频,并将其上传到某个地方,然后在浏览器中观看,那么视频的方向将是错误的。因此,如果您正在寻求一个彻底的解决方案,那么您自己的转型就是一条出路


如果你经常做视频/图像处理(例如,翻转/旋转),考虑OpenCV库。学习需要一些时间,但它是值得的。

再次思考,我不确定我是否可以使用AvassetWriteInput转换,我想让用户在录制时切换相机,但我无法在开始写入后更改AvassetWriteInput转换(它崩溃),因此我想我别无选择,只能更改AVCaptureConnection方向(我知道这会影响性能),你不这么认为吗?如果它能工作,应该不会太糟糕。这里更好的问题是,当样本的分辨率不同时会发生什么。无论如何,如果你更换相机,你可以开始一个新的视频,然后在用户停止录制时将它们全部添加到一起。。