iosorientationavfoundationavcapturesessionavcapture

AVCaptureVideoPreviewLayer orientation - need landscape


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.


Solution

  • 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.