AVCaptureVideoPreviewLayer orientation - need landscape

soleil picture soleil · Feb 25, 2013 · Viewed 52.2k times · Source

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.

Answer

Maselko picture Maselko · Apr 12, 2016

BEST ANSWER FOR SWIFT 3.0 AND XCODE 8.0

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: UIDeviceOrientation = currentDevice.orientation
        
        let previewLayerConnection : AVCaptureConnection = connection
        
        if previewLayerConnection.isVideoOrientationSupported {
            
            switch (orientation) {
            case .portrait: updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)
                                
            case .landscapeRight: updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeLeft)
                                
            case .landscapeLeft: updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeRight)
                                
            case .portraitUpsideDown: updatePreviewLayer(layer: previewLayerConnection, orientation: .portraitUpsideDown)
                                
            default: updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)
            
            }
        }
    }
}

BEST ANSWER FOR SWIFT 2.2 AND 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)
            
            }
        }
    }
}