使用AV Foundation时旋转AV视频预览区域和其他元素

时间:2011-07-23 18:00:40

标签: iphone ios avfoundation orientation-changes

我使用UIImagePickerController启动了一个项目来捕获静态图像。我已经放弃使用这种简单的机制,因为叠加和刚刚捕获的图像之间的相互作用很差。问题如下:如果您激活了叠加层并拍摄照片,则当用户出现使用或重新拍摄图像的选项时,刚拍摄的图像会围绕纵向方向进行纵横填充。发生这种情况时,无法关闭叠加层,或旋转叠加层以对应新的静止图像预览方向。不好。

我决定尝试使用AV Foundation的各种机制重新实现UIImagePickerController的静态图像捕获行为。这个设置非常容易,但我仍然有一些挥之不去的问题:

1)我想重新定位机制,使其类似于UI在标准UIImagePickerController中的工作方式。如您所知,在此控制器中,无论手机如何旋转,按钮栏始终固定在纵向方向的底部。在此按钮栏中,按钮中的字形本身会旋转,但其他所有字符都保持固定。闪光灯组,相机切换和选项的叠加控件可以重新定向。如何在旋转这些其他元素时让此标签栏保持固定状态?有没有办法从旋转中排除某些元素?

2)在进行自动重定向时,我希望AVVideoCaptureLayer始终保持实时并占据整个屏幕。当设备执行重定向旋转时,此图层的大小会异常缩小(缩小),视频输入本身会偏离90度。显然这个图层正在旋转,但不是全屏尺寸,视频输入本身的行为不符合预期。我希望视频保持固定并通过完整旋转占据整个屏幕,并且总是向上,并且在旋转期间不会调整预览的大小。但我也希望能够像第1项那样进行,某些元素重新定位。

非常感谢任何说明如何实现这一目标的示例代码。

3 个答案:

答案 0 :(得分:6)

刚刚发现在AVCaptureVideoPreviewLayer上使用orientation属性已被弃用。这是一个更新的解决方案(尽管@Jaret Ward分享的先前解决方案的工作要少得多:):

使用AVCaptureConnection中使用setVideoOrientation更改它的推荐方法。我会在viewDidAppear和你的一个旋转回调中添加对此的调用。

//setup a connection to the preview layer
AVCaptureConnection *connection;
connection = [self.videoPreviewLayer connection];
[connection setVideoOrientation:[self avOrientationForDeviceOrientation:[[UIDevice currentDevice] orientation]]];

//translate the orientation
 - (AVCaptureVideoOrientation)avOrientationForDeviceOrientation:(UIDeviceOrientation)deviceOrientation {

AVCaptureVideoOrientation result = deviceOrientation;
if ( deviceOrientation == UIDeviceOrientationLandscapeLeft )
    result = AVCaptureVideoOrientationLandscapeRight;
else if ( deviceOrientation == UIDeviceOrientationLandscapeRight )
    result = AVCaptureVideoOrientationLandscapeLeft;
else if( deviceOrientation == UIDeviceOrientationPortrait)
    result = AVCaptureVideoOrientationPortrait;
else if( deviceOrientation == UIDeviceOrientationPortraitUpsideDown)
    result = AVCaptureVideoOrientationPortraitUpsideDown;
return result;
}

答案 1 :(得分:3)

通过在视频预览图层的连接上设置方向属性。

这只是@ CocoaEv答案的更简洁版本。除了使方向修复函数而不是方法之外,它还使用较新的点语法。

self.videoPreviewLayer.connection.videoOrientation = AVOrientationFromDeviceOrientation([UIDevice currentDevice].orientation);

AVCaptureVideoOrientation AVOrientationFromDeviceOrientation(UIDeviceOrientation deviceOrientation) {
    if ( deviceOrientation == UIDeviceOrientationLandscapeLeft )
        return AVCaptureVideoOrientationLandscapeRight;
    else if ( deviceOrientation == UIDeviceOrientationLandscapeRight )
        return AVCaptureVideoOrientationLandscapeLeft;
    else if( deviceOrientation == UIDeviceOrientationPortrait)
        return AVCaptureVideoOrientationPortrait;
    else if( deviceOrientation == UIDeviceOrientationPortraitUpsideDown)
        return AVCaptureVideoOrientationPortraitUpsideDown;
    else
        return deviceOrientation;
}

答案 2 :(得分:2)

我在自己的努力中遇到了类似的问题,最后放下了尝试影响视频流的想法。相反,我专注于AVCaptureVideoPreviewLayer本身,并提出了这个解决方案:

- (void)orientationChangedMethod {
    self.previewLayer.orientation = [[UIDevice currentDevice] orientation];
    self.previewLayer.frame = self.view.bounds;
}

其中orientationChangedMethod填充the.ichibod.com的(非常有用的)代码,self.previewLayer是对我的AVCaptureVideoPreviewLayer实例的引用。

自iOS 6以来,该答案已被弃用!