在 AVCaptureVideoPreviewLayer 中使用 AVFoundation 旋转 90º 进行实时捕获
Realtime capture using AVFoundation rotated 90º in AVCaptureVideoPreviewLayer
我正在开发一款允许用户实时录制视频的应用,同时一些 HUD 信息会显示在预览层中。
我已经解决了很多问题,但我遇到的一个问题是当 iPad 处于横向模式时,视频本身会向右旋转 90 度。当主页按钮在左侧时,视频会逆时针旋转 90 度,而当主页按钮在右侧时,视频会顺时针旋转 90 度。无论我使用哪种横向模式,视频都应该是直立的。此 [SO 消息] 似乎与我正在处理的内容非常吻合,但该解决方案包含弃用内容。 1
在我的主控制器中:
[self setCaptureManager:[[[CaptureSessionManager alloc] init] autorelease]];
[[self captureManager] addVideoInput];
[[self captureManager] addVideoPreviewLayer];
CGRect layerRect = [[[self view] layer] bounds];
[[[self captureManager] previewLayer] setBounds:layerRect];
[[[self captureManager] previewLayer] setPosition:CGPointMake(CGRectGetMidX(layerRect),
CGRectGetMidY(layerRect))];
[[[self view] layer] addSublayer:[[self captureManager] previewLayer]];
CaptureSessionManager.h
#import <CoreMedia/CoreMedia.h>
#import <AVFoundation/AVFoundation.h>
@interface CaptureSessionManager : NSObject {
}
@property(retain) AVCaptureVideoPreviewLayer *previewLayer;
@property(retain) AVCaptureSession *captureSession;
- (void)addVideoPreviewLayer;
- (void)addVideoInput;
@end
CaptureSessionManager.m
#import "CaptureSessionManager.h"
@implementation CaptureSessionManager
@synthesize captureSession;
@synthesize previewLayer;
#pragma mark Capture Session Configuration
- (id)init {
if ((self = [super init])) {
[self setCaptureSession:[[AVCaptureSession alloc] init]];
if ([captureSession canSetSessionPreset:AVCaptureSessionPresetHigh]) {
captureSession.sessionPreset = AVCaptureSessionPresetHigh;
}
}
return self;
}
- (void)addVideoPreviewLayer {
[self setPreviewLayer:[[[AVCaptureVideoPreviewLayer alloc] initWithSession:[self captureSession]] autorelease]];
[[self previewLayer] setVideoGravity:AVLayerVideoGravityResizeAspectFill];
}
- (void)addVideoInput {
AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if (videoDevice) {
NSError *error;
AVCaptureDeviceInput *videoIn = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
if (!error) {
if ([[self captureSession] canAddInput:videoIn])
[[self captureSession] addInput:videoIn];
else
NSLog(@"Couldn't add video input");
}
else
NSLog(@"Couldn't create video input");
}
else
NSLog(@"Couldn't create video capture device");
}
- (void)dealloc {
[[self captureSession] stopRunning];
[previewLayer release], previewLayer = nil;
[captureSession release], captureSession = nil;
[super dealloc];
}
@end
如果您提到的那个问题的答案不起作用,那么您可以通过其他方式实现。使用 CATransform3DMakeRotation
根据设备的方向旋转预览图层。
例如,对于 UIDeviceOrientationLandscapeLeft
,您可以像这样旋转预览图层:
preview.transform = CATransform3DMakeRotation(-M_PI/2, 0, 0, 1);
发现需要设置预览层连接的videoOrientation属性
这是对我的 addVideoPreviewLayer 方法的更改...
- (void)addVideoPreviewLayer {
[self setPreviewLayer:[[[AVCaptureVideoPreviewLayer alloc] initWithSession:[self captureSession]] autorelease]];
[[self previewLayer] setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[[previewLayer connection] setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
}
我正在开发一款允许用户实时录制视频的应用,同时一些 HUD 信息会显示在预览层中。
我已经解决了很多问题,但我遇到的一个问题是当 iPad 处于横向模式时,视频本身会向右旋转 90 度。当主页按钮在左侧时,视频会逆时针旋转 90 度,而当主页按钮在右侧时,视频会顺时针旋转 90 度。无论我使用哪种横向模式,视频都应该是直立的。此 [SO 消息] 似乎与我正在处理的内容非常吻合,但该解决方案包含弃用内容。 1
在我的主控制器中:
[self setCaptureManager:[[[CaptureSessionManager alloc] init] autorelease]];
[[self captureManager] addVideoInput];
[[self captureManager] addVideoPreviewLayer];
CGRect layerRect = [[[self view] layer] bounds];
[[[self captureManager] previewLayer] setBounds:layerRect];
[[[self captureManager] previewLayer] setPosition:CGPointMake(CGRectGetMidX(layerRect),
CGRectGetMidY(layerRect))];
[[[self view] layer] addSublayer:[[self captureManager] previewLayer]];
CaptureSessionManager.h
#import <CoreMedia/CoreMedia.h>
#import <AVFoundation/AVFoundation.h>
@interface CaptureSessionManager : NSObject {
}
@property(retain) AVCaptureVideoPreviewLayer *previewLayer;
@property(retain) AVCaptureSession *captureSession;
- (void)addVideoPreviewLayer;
- (void)addVideoInput;
@end
CaptureSessionManager.m
#import "CaptureSessionManager.h"
@implementation CaptureSessionManager
@synthesize captureSession;
@synthesize previewLayer;
#pragma mark Capture Session Configuration
- (id)init {
if ((self = [super init])) {
[self setCaptureSession:[[AVCaptureSession alloc] init]];
if ([captureSession canSetSessionPreset:AVCaptureSessionPresetHigh]) {
captureSession.sessionPreset = AVCaptureSessionPresetHigh;
}
}
return self;
}
- (void)addVideoPreviewLayer {
[self setPreviewLayer:[[[AVCaptureVideoPreviewLayer alloc] initWithSession:[self captureSession]] autorelease]];
[[self previewLayer] setVideoGravity:AVLayerVideoGravityResizeAspectFill];
}
- (void)addVideoInput {
AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if (videoDevice) {
NSError *error;
AVCaptureDeviceInput *videoIn = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
if (!error) {
if ([[self captureSession] canAddInput:videoIn])
[[self captureSession] addInput:videoIn];
else
NSLog(@"Couldn't add video input");
}
else
NSLog(@"Couldn't create video input");
}
else
NSLog(@"Couldn't create video capture device");
}
- (void)dealloc {
[[self captureSession] stopRunning];
[previewLayer release], previewLayer = nil;
[captureSession release], captureSession = nil;
[super dealloc];
}
@end
如果您提到的那个问题的答案不起作用,那么您可以通过其他方式实现。使用 CATransform3DMakeRotation
根据设备的方向旋转预览图层。
例如,对于 UIDeviceOrientationLandscapeLeft
,您可以像这样旋转预览图层:
preview.transform = CATransform3DMakeRotation(-M_PI/2, 0, 0, 1);
发现需要设置预览层连接的videoOrientation属性
这是对我的 addVideoPreviewLayer 方法的更改...
- (void)addVideoPreviewLayer {
[self setPreviewLayer:[[[AVCaptureVideoPreviewLayer alloc] initWithSession:[self captureSession]] autorelease]];
[[self previewLayer] setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[[previewLayer connection] setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
}