Search code examples
iosswiftautolayoutavfoundationavcapturesession

AVCaptureVideoPreviewLayer looks to be iPhone 4 size


I'm using this code to display a camera in my iOS 9, Swift app:

Properties:

@IBOutlet weak var previewView: UIView!

var session: AVCaptureSession!
var input: AVCaptureDeviceInput!
var output: AVCaptureStillImageOutput!
var previewLayer: AVCaptureVideoPreviewLayer?

Delegate methods:

override func viewDidLoad() {
    super.viewDidLoad()
}

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    setupSession()
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    // Experimental / debugging
    view.layoutSubviews()
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // Experimental / debugging
    previewLayer!.frame = previewView.bounds
}

Camera methods:

func setupSession() {
    session = AVCaptureSession()
    session.sessionPreset = AVCaptureSessionPresetPhoto

    let camera = frontCamera()

    do { input = try AVCaptureDeviceInput(device: camera) } catch { return }

    output = AVCaptureStillImageOutput()
    output.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]

    guard session.canAddInput(input) && session.canAddOutput(output) else { return }

    session.addInput(input)
    session.addOutput(output)

    previewLayer = AVCaptureVideoPreviewLayer(session: session)
    previewLayer!.videoGravity = AVLayerVideoGravityResizeAspect
    previewLayer!.frame = previewView.bounds
    previewLayer!.connection?.videoOrientation = .Portrait

    previewView.layer.addSublayer(previewLayer!)

    session.startRunning()
}

func frontCamera() -> AVCaptureDevice! {
    let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
    for device in devices {
        if (device.position == AVCaptureDevicePosition.Front) {
            return device as! AVCaptureDevice
        }
    }
    return nil
}

However, the camera is displayed like this:

enter image description here

And it appears to be equivalent to the display size of an iPhone 4.

How can I solve this? I've tried setting the frame in viewDidLayoutSubviews, but I can't get it sized properly.


Solution

  • You don't have to override the layoutSubivews or viewDidLayoutSUbviews method.

    1. Make sure the previewView is constrainted to superview (If you are using autolayout)
    2. Make sure the bounds of previewLayer is same as previewView bounds. Don't get confused while giving the frame value to bounds or bound value to frame.
    3. set the video gravity of the preview layer to AVLayerVideoGravityResizeAspectFill.

    4.You can position the previewLayer and make it center to the previewView . Use position property of previewLayer and set it to the center of previewView.

    1. call the setupSession() either in viewDidAppear/viewWillAppear