Reputation: 13083
My app is landscape only. I'm presenting the AVCaptureVideoPreviewLayer like this:
self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[self.previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
[self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
NSLog(@"previewView: %@", self.previewView);
CALayer *rootLayer = [self.previewView layer];
[rootLayer setMasksToBounds:YES];
[self.previewLayer setFrame:[rootLayer bounds]];
NSLog(@"previewlayer: %f, %f, %f, %f", self.previewLayer.frame.origin.x, self.previewLayer.frame.origin.y, self.previewLayer.frame.size.width, self.previewLayer.frame.size.height);
[rootLayer addSublayer:self.previewLayer];
[session startRunning];
self.previewView has a frame of (0,0,568,320), which is correct. self.previewLayer logs a frame of (0,0,568,320), which is theoretically correct. However, the camera display appears as a portrait rectangle in the middle of the landscape screen, and the orientation of the camera preview image is wrong by 90 degrees. What am I doing wrong? I need the camera preview layer to appear in the full screen, in landscape mode, and the image should be orientated correctly.
Upvotes: 71
Views: 61955
Reputation: 1
I encountered the same problem while setting up a camera view controller.
Letting the view rotate with the layout and then fixing the previewOrientation on the way is not the best approach to this for two reasons: Firstly, the frame will actually rotate which feels very unnatural even if we fix the preview orientation on the way. Secondly, since the camera is physically attached to the device and therefore rotates with it, what we really want is to fix the preview's frame transform in portrait mode. Obviously, the contents of the preview will naturally rotate with the physical camera.
Solutions that involve having a separate view controller to block interface rotation for the preview view did not work when I tried it.
I ended up Apple's suggested solution posted in this Technical Q&A and had success:
"Preventing a View From Rotating" https://developer.apple.com/library/archive/qa/qa1890/_index.html
Using this method the frame rotation animation that is applied to the preview is canceled out, and the preview stays exactly where it is while the rest of the interface rotates to realign with the orientation.
Upvotes: 0
Reputation: 4128
Swift 5.5, Xcode 13.2
private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {
layer.videoOrientation = orientation
self.previewLayer?.frame = view.bounds
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let connection = self.previewLayer?.connection {
let currentDevice = UIDevice.current
let orientation: UIDeviceOrientation = currentDevice.orientation
let previewLayerConnection: AVCaptureConnection = connection
if previewLayerConnection.isVideoOrientationSupported {
switch orientation {
case .portrait: self.updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)
case .landscapeRight: self.updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeLeft)
case .landscapeLeft: self.updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeRight)
case .portraitUpsideDown: self.updatePreviewLayer(layer: previewLayerConnection, orientation: .portraitUpsideDown)
default: self.updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)
}
}
}
}
Swift 2.2, Xcode 7.3
private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {
layer.videoOrientation = orientation
previewLayer.frame = self.view.bounds
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let connection = self.previewLayer?.connection {
let currentDevice: UIDevice = UIDevice.currentDevice()
let orientation: UIDeviceOrientation = currentDevice.orientation
let previewLayerConnection : AVCaptureConnection = connection
if (previewLayerConnection.supportsVideoOrientation) {
switch (orientation) {
case .Portrait: updatePreviewLayer(previewLayerConnection, orientation: .Portrait)
case .LandscapeRight: updatePreviewLayer(previewLayerConnection, orientation: .LandscapeLeft)
case .LandscapeLeft: updatePreviewLayer(previewLayerConnection, orientation: .LandscapeRight)
case .PortraitUpsideDown: updatePreviewLayer(previewLayerConnection, orientation: .PortraitUpsideDown)
default: updatePreviewLayer(previewLayerConnection, orientation: .Portrait)
}
}
}
}
Upvotes: 93
Reputation: 2710
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
if let connection = self.previewLayer?.connection {
let currentDevice: UIDevice = UIDevice.current
let orientation: UIDeviceOrientation = currentDevice.orientation
let previewLayerConnection : AVCaptureConnection = connection
if (previewLayerConnection.isVideoOrientationSupported) {
switch (orientation) {
case .portrait:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.portrait
case .landscapeRight:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.landscapeRight
case .landscapeLeft:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.landscapeLeft
case .portraitUpsideDown:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.portraitUpsideDown
default:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.portrait
}
}
}
}
Upvotes: 31
Reputation: 2192
The API seems to have changed somewhat. videoOrientation
is now a property on the preview layer's connection
property. Furthermore, no need to use a switch. Answer for Swift 3.0:
override func viewDidLayoutSubviews() {
self.configureVideoOrientation()
}
private func configureVideoOrientation() {
if let previewLayer = self.previewLayer,
let connection = previewLayer.connection {
let orientation = UIDevice.current.orientation
if connection.isVideoOrientationSupported,
let videoOrientation = AVCaptureVideoOrientation(rawValue: orientation.rawValue) {
previewLayer.frame = self.view.bounds
connection.videoOrientation = videoOrientation
}
}
}
Upvotes: 27
Reputation: 761
Improved version of Maselko's answer
Works just great!
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let connection = previewView.connection {
if connection.isVideoOrientationSupported {
let videoOrientation = AVCaptureVideoOrientation.init(rawValue: UIApplication.shared.statusBarOrientation.rawValue)!
connection.videoOrientation = videoOrientation
previewView.frame = self.view.bounds
}
}
}
Upvotes: 1
Reputation: 151
Swift 5 Version
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
updatePreview()
}
func updatePreview() {
let orientation: AVCaptureVideoOrientation
switch UIDevice.current.orientation {
case .portrait:
orientation = .portrait
case .landscapeRight:
orientation = .landscapeLeft
case .landscapeLeft:
orientation = .landscapeRight
case .portraitUpsideDown:
orientation = .portraitUpsideDown
default:
orientation = .portrait
}
if previewLayer?.connection?.isVideoOrientationSupported == true {
previewLayer?.connection?.videoOrientation = orientation
}
previewLayer.frame = view.bounds
}
Upvotes: 4
Reputation: 305
We can't use
[previewLayerConnection setVideoOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
because UIInterfaceOrientation != AVCaptureVideoOrientation
But we can just test values... and this work,with following code.
-(void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
switch (orientation) {
case UIInterfaceOrientationPortrait:
[_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
break;
case UIInterfaceOrientationPortraitUpsideDown:
[_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
break;
case UIInterfaceOrientationLandscapeLeft:
[_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
break;
case UIInterfaceOrientationLandscapeRight:
[_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
break;
}
}
Upvotes: 19
Reputation: 599
Correct mapping from UIDeviceOrientation
to AVCaptureVideoOrientation
is necessary.
If your app supports device rotation
, resizing preview.frame
is also necessary, and this func
should be called from viewDidLayoutSubviews()
and viewWillTransition()
.
private func configureVideoOrientation() {
if let preview = self.previewLayer,
let connection = preview.connection {
let orientation = UIDevice.current.orientation
if connection.isVideoOrientationSupported {
var videoOrientation: AVCaptureVideoOrientation
switch orientation {
case .portrait:
videoOrientation = .portrait
case .portraitUpsideDown:
videoOrientation = .portraitUpsideDown
case .landscapeLeft:
videoOrientation = .landscapeRight
case .landscapeRight:
videoOrientation = .landscapeLeft
default:
videoOrientation = .portrait
}
preview.frame = self.view.bounds
connection.videoOrientation = videoOrientation
}
}
}
Upvotes: 3
Reputation: 4444
Here is the solution I'm using with Swift 4.
It's short and works beautifully for me.
open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
let videoLayer = self.previewLayer
coordinator.animate(alongsideTransition: { (context: UIViewControllerTransitionCoordinatorContext) in
guard let connection = videoLayer?.connection, connection.isVideoOrientationSupported, let orientation = AVCaptureVideoOrientation(rawValue: UIApplication.shared.statusBarOrientation.rawValue) else {
return
}
connection.videoOrientation = orientation
videoLayer?.frame = self.view.bounds
}) { (context: UIViewControllerTransitionCoordinatorContext) in
// handle any completion logic here...
}
}
Upvotes: 0
Reputation: 1024
Selected answer working for Swift 4.2 - Xcode 10.0 - iOS 12.0:
var videoPreviewLayer: AVCaptureVideoPreviewLayer?
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let previewLayerConnection = self.videoPreviewLayer?.connection, previewLayerConnection.isVideoOrientationSupported {
updatePreviewLayer(layer: previewLayerConnection, orientation: UIApplication.shared.statusBarOrientation.videoOrientation)
}
}
private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {
layer.videoOrientation = orientation
videoPreviewLayer?.frame = self.view.bounds
}
Don't forget the mapping from UIInterfaceOrientation to AVCaptureVideoOrientation
extension UIInterfaceOrientation {
public var videoOrientation: AVCaptureVideoOrientation {
switch self {
case .portrait:
return AVCaptureVideoOrientation.portrait
case .landscapeRight:
return AVCaptureVideoOrientation.landscapeRight
case .landscapeLeft:
return AVCaptureVideoOrientation.landscapeLeft
case .portraitUpsideDown:
return AVCaptureVideoOrientation.portraitUpsideDown
default:
return AVCaptureVideoOrientation.portrait
}
}
}
Upvotes: 3
Reputation: 77
Maselko's answer nearly worked for me, except that if the status-bar-orientation flips then the camera output displays upside down. I've addressed that issue by re-calling Maselko's logic when the status bar flips.
Here's my modified Maselko solution (tested on ios12/swift4):
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
setCameraOrientation()
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
setCameraOrientation()
}
@objc func setCameraOrientation() {
if let connection = self.previewLayer?.connection {
let currentDevice: UIDevice = UIDevice.current
let orientation: UIDeviceOrientation = currentDevice.orientation
let previewLayerConnection : AVCaptureConnection = connection
if previewLayerConnection.isVideoOrientationSupported {
let o: AVCaptureVideoOrientation
switch (orientation) {
case .portrait: o = .portrait
case .landscapeRight: o = .landscapeLeft
case .landscapeLeft: o = .landscapeRight
case .portraitUpsideDown: o = .portraitUpsideDown
default: o = .portrait
}
previewLayerConnection.videoOrientation = o
previewLayer!.frame = self.view.bounds
}
}
}
Upvotes: 1
Reputation: 307
@Maselko 's answer is correct but for one thing: You should be using UIApplication.shared.statusBarOrientation
instead of UIDevice.current.orientation
, because the device orientation is how your device is physically positioned. It breaks when your device is in landscape but your UI does not support that orientation (like when I was making a landscape-only camera app and initiate the view when the device is in portrait position).
private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {
layer.videoOrientation = orientation
previewLayer.frame = self.view.bounds
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let connection = self.previewLayer?.connection {
let currentDevice: UIDevice = UIDevice.current
let orientation = UIApplication.shared.statusBarOrientation
let previewLayerConnection : AVCaptureConnection = connection
if previewLayerConnection.isVideoOrientationSupported {
switch (orientation) {
case .portrait: updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)
break
case .landscapeRight: updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeLeft)
break
case .landscapeLeft: updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeRight)
break
case .portraitUpsideDown: updatePreviewLayer(layer: previewLayerConnection, orientation: .portraitUpsideDown)
break
default: updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)
break
}
}
}
}
Upvotes: 0
Reputation: 28094
Works with Swift 4, Xcode 9:
override func viewWillTransition(to size: CGSize,
with coordinator: UIViewControllerTransitionCoordinator)
{
super.viewWillTransition(to: size, with: coordinator)
guard
let conn = self.previewLayer?.connection,
conn.isVideoOrientationSupported
else { return }
let deviceOrientation = UIDevice.current.orientation
switch deviceOrientation {
case .portrait: conn.videoOrientation = .portrait
case .landscapeRight: conn.videoOrientation = .landscapeLeft
case .landscapeLeft: conn.videoOrientation = .landscapeRight
case .portraitUpsideDown: conn.videoOrientation = .portraitUpsideDown
default: conn.videoOrientation = .portrait
}
}
One subtlety to notice here is that UIDeviceOrientation.landscapeRight
goes with AVCaptureVideoOrientation.landscapeLeft
.
The other landscape case is similarly mismatched. This is deliberate, and accommodates an unfortunate mismatch between UIKit and AVFoundation. If you match the cases up by matching the names, it won't work, and your video will be upside down in landscape configurations.
Upvotes: 4
Reputation: 1215
The only way it worked for me in iOS 8 to 11.1 without any problem is to do this and I should mention that in my case, I loaded my application only in landscape mode but it should work in all orientations.(Btw you can overlay the camera manually via imageview or anything u want this way very easily)
@interface ViewController (){
AVCaptureVideoPreviewLayer * previewLayer;
AVCaptureSession* session;
}
@property (weak, nonatomic) IBOutlet UIView *cameraPreviewView;
-(void)viewDidLoad{
AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] error:nil];
if (captureInput) {
session = [[AVCaptureSession alloc] init];
[session addInput:captureInput];
}
previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
[previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
CALayer *rootLayer = [self.cameraPreviewView layer];
[rootLayer setMasksToBounds:YES];
[previewLayer setFrame:[self.view bounds]];
[rootLayer addSublayer:previewLayer];
[session startRunning];
//Orientation Code is in viewDidLayoutSubviews method
}
-(void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
switch (orientation) {
case UIInterfaceOrientationPortrait:
[previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
break;
case UIInterfaceOrientationPortraitUpsideDown:
[previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
break;
case UIInterfaceOrientationLandscapeLeft:
[previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
break;
case UIInterfaceOrientationLandscapeRight:
[previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
break;
default:break;
}
}
Upvotes: 0
Reputation: 2181
I too was facing the same This was to fix my Camera orientation
override func shouldAutorotate() -> Bool {
return false
}
override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return UIInterfaceOrientation.LandscapeLeft
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.LandscapeLeft
}
To fix the camera
let previewLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.avCaptureSession)
previewLayer.frame = self.view.layer.frame
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
Upvotes: 1
Reputation: 589
First we need to create the AVCaptureVideoPreviewLayer and :
set the frame.
[_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[_videoPreviewLayer setFrame:_viewPreview.layer.bounds];
set the orientation initially
if (_videoPreviewLayer.connection.supportsVideoOrientation) {
_videoPreviewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation:[UIApplication sharedApplication].statusBarOrientation];
}
set the orientation for each case using a simple switch case
-(AVCaptureVideoOrientation)interfaceOrientationToVideoOrientation:
(UIInterfaceOrientation)orientation {
switch (orientation) {
case UIInterfaceOrientationPortrait:
return AVCaptureVideoOrientationPortrait;
case UIInterfaceOrientationPortraitUpsideDown:
return AVCaptureVideoOrientationPortraitUpsideDown;
case UIInterfaceOrientationLandscapeLeft:
return AVCaptureVideoOrientationLandscapeLeft ;
case UIInterfaceOrientationLandscapeRight:
return AVCaptureVideoOrientationLandscapeRight;
default:
break;
}
NSLog(@"Warning - Didn't recognise interface orientation (%d)",orientation);
return AVCaptureVideoOrientationPortrait;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
if (_videoPreviewLayer.connection.supportsVideoOrientation) {
_videoPreviewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation:toInterfaceOrientation];
}
}
Upvotes: 2
Reputation: 49
Hey Guys thanks for all the answers and feedback on this, I came across this as I am working on a swift app. You can achieve the camera to rotate with your device using this code:
override func shouldAutorotate() -> Bool {
if your cameraController.previewLayer.connection != nil {
var currentDevice: UIDevice = UIDevice.currentDevice()
var orientation: UIDeviceOrientation = currentDevice.orientation
var previewLayerConnection : AVCaptureConnection = your cameraController.previewLayer.connection
if (previewLayerConnection.supportsVideoOrientation)
{
switch (orientation)
{
case .Portrait:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
break
case .LandscapeRight:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.LandscapeLeft
break
case .LandscapeLeft:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.LandscapeRight
break
default:
previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
break
}
}
}
return true
}
Hope this helps!
Upvotes: 2
Reputation: 91
For anyone who is struggling on a full functional camera preview. Here is production code. Of course the drawback is a lag when orientation changes. If anyone have better solution to overcome this please share
- (void)viewDidLoad
{
[super viewDidLoad];
[self initCamera];
}
- (void)initCamera
{
AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] error:nil];
if (captureInput) {
mSession = [[AVCaptureSession alloc] init];
[mSession addInput:captureInput];
}
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
if ([mSession isRunning]) {
[mSession stopRunning];
[mCameraLayer removeFromSuperlayer];
[self initCamera];
[self startCamera];
}
}
- (void)startCamera
{
[mSession startRunning];
Settings::getInstance()->setClearColor(Color(0, 0, 0, 0));
mCameraLayer = [AVCaptureVideoPreviewLayer layerWithSession: mSession];
[self updateCameraLayer];
[mCameraView.layer addSublayer:mCameraLayer];
}
- (void)stopCamera
{
[mSession stopRunning];
[mCameraLayer removeFromSuperlayer];
Settings::getInstance()->setDefClearColor();
}
- (void)toggleCamera
{
mSession.isRunning ? [self stopCamera] : [self startCamera];
[mGLKView setNeedsDisplay];
}
- (void)updateCameraLayer
{
mCameraLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
mCameraLayer.frame = mCameraView.bounds;
float x = mCameraView.frame.origin.x;
float y = mCameraView.frame.origin.y;
float w = mCameraView.frame.size.width;
float h = mCameraView.frame.size.height;
CATransform3D transform = CATransform3DIdentity;
if (UIDeviceOrientationLandscapeLeft == [[UIDevice currentDevice] orientation]) {
mCameraLayer.frame = CGRectMake(x, y, h, w);
transform = CATransform3DTranslate(transform, (w - h) / 2, (h - w) / 2, 0);
transform = CATransform3DRotate(transform, -M_PI/2, 0, 0, 1);
} else if (UIDeviceOrientationLandscapeRight == [[UIDevice currentDevice] orientation]) {
mCameraLayer.frame = CGRectMake(x, y, h, w);
transform = CATransform3DTranslate(transform, (w - h) / 2, (h - w) / 2, 0);
transform = CATransform3DRotate(transform, M_PI/2, 0, 0, 1);
} else if (UIDeviceOrientationPortraitUpsideDown == [[UIDevice currentDevice] orientation]) {
mCameraLayer.frame = mCameraView.bounds;
transform = CATransform3DMakeRotation(M_PI, 0, 0, 1);
} else {
mCameraLayer.frame = mCameraView.bounds;
}
mCameraLayer.transform = transform;
}
enter code here
Upvotes: 7
Reputation: 4109
As there is a deprecation and conversion warning using the above solution, and setting videoOrientation didn't seem to be working in iOS7, I put checks for orientation in my getter for the AVCaptureVideoPreviewLayer like so:
- (AVCaptureVideoPreviewLayer *) previewLayer
{
if(!_previewLayer)
{
_previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession: self.captureSession];
[_previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
_previewLayer.frame = self.view.bounds; // Assume you want the preview layer to fill the view.
[_previewLayer setPosition:CGPointMake(0,0)];
if (UIDeviceOrientationLandscapeLeft == [[UIDevice currentDevice] orientation]) {
_previewLayer.transform = CATransform3DMakeRotation(-M_PI/2, 0, 0, 1);
}
else if (UIDeviceOrientationLandscapeRight == [[UIDevice currentDevice] orientation])
{
_previewLayer.transform = CATransform3DMakeRotation(M_PI/2, 0, 0, 1);
}
}
return _previewLayer;
}
Upvotes: 4
Reputation: 8741
The default camera orientation is Landscape Left (home button one the left). You need to do two things here:
1- Change the previewLayer frame to:
self.previewLayer.frame=self.view.bounds;
You need to set the preview layer frame to the bounds of the screen so that the frame of the preview layer changes when the screen rotates (you cannot use frame of the root view because that does not change with rotation but the bounds of the root view do). In your example, you are setting the previewlayer frame to a previewView property which I do not see.
2- You need to rotate the preview layer connection with the rotation of the device. Add this code in viewDidAppear:
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:YES];
//Get Preview Layer connection
AVCaptureConnection *previewLayerConnection=self.previewLayer.connection;
if ([previewLayerConnection isVideoOrientationSupported])
[previewLayerConnection setVideoOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}
Hope this solves it.
Full Disclosure: This is a simplified version since you do not care if Landscape right or Landscape left.
Upvotes: 70