简体   繁体   中英

Smooth transition while switching cameras in custom camera swift + xcode

I was creating my custom camera view using swift 3 and xcode.

I have got it to work, but i am facing a small issue. To switch camera device from front/back i stop the session, remove the video preview layer from the view and then create a new session and add a new video preview layer from the front camera. This makes the new camera come on with a jerk. I want smooth transition between the camera devices. How can i do that?

Here my code for loading the camera:

func loadCamera()
{

    session?.stopRunning()
    videoPreviewLayer?.removeFromSuperlayer()

    session = AVCaptureSession()
    session!.sessionPreset = AVCaptureSessionPresetPhoto


    var backCamera = AVCaptureDevice.defaultDevice(withDeviceType: .builtInWideAngleCamera, mediaType: AVMediaTypeVideo, position: .front)

    if cameraPos == "back"
    {
        backCamera = AVCaptureDevice.defaultDevice(withDeviceType: .builtInWideAngleCamera, mediaType: AVMediaTypeVideo, position: .back)
    }

    var error: NSError?
    var input: AVCaptureDeviceInput!
    do {
        input = try AVCaptureDeviceInput(device: backCamera)
    } catch let error1 as NSError {
        error = error1
        input = nil
        print(error!.localizedDescription)
    }

    if error == nil && session!.canAddInput(input) {
        session!.addInput(input)

        stillImageOutput = AVCapturePhotoOutput()


        if session!.canAddOutput(stillImageOutput) {
            session!.addOutput(stillImageOutput)


            videoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)

            videoPreviewLayer?.frame = cameraView.bounds
            videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
            videoPreviewLayer?.connection.videoOrientation = AVCaptureVideoOrientation.portrait


            cameraView.layer.addSublayer(videoPreviewLayer!)
            session!.startRunning()

        }   
    }
}

I call this from viewWillAppear

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

and i call load camera when user clicks on change camera

@IBAction func changeCamera(_ sender: UIButton) {

    if cameraPos == "back"
    {cameraPos = "front"}

    else
    {cameraPos = "back"}


    loadCamera()
}

In loadCamera() you'll need to create an AVCaptureInput from the front capture device. It's good practice to hold both the back input and the front input on some camera singleton. The smooth transition between front and back can be done by removing all inputs then assigning another input.

func show(back: Bool) {
  session.beginConfiguration()
  if let inputs = session.inputs as? [AVCaptureDeviceInput] {
    for input in inputs {
      session.removeInput(input)
    }
  }
  if back {
    if session.canAddInput(backInput) {
      session.addInput(backInput)
    }
  } else {
    if session.canAddInput(frontInput) {
      session.addInput(frontInput)
    }
  }
  session.commitConfiguration()
}

Call the loadCamera() function inside viewDidAppear instead of viewWillAppear

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(true)
    loadCamera()
}

Background thread:

DispatchQueue.global(qos: .background).async {

    // perform ui updation and web related code
    // background thread

    DispatchQueue.main.async {
        // main thread
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM