Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove AVCaptureSession and PreviewLayer Properly in Swift

Using iOS Swift to capture video feed from App, and looking to stop it properly.

Right now, I have created a button which starts the AVCaptureSession, and would like to allow the same button to stop the AVCapture Session properly when the user prefers. This would allow the user to start and end camera capture easily.

I receive error when I use:

captureSession.stopRunning()  

Here is the code:

import UIKit
import AVFoundation
import Vision

class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {

    // creates a new capture session
    let captureSession = AVCaptureSession()

    override func viewDidLoad() {
        super.viewDidLoad()

        setupLabel()
        createButton()

    }


    func setupCaptureSession() {

        // search for available capture devices
        let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices

        // get capture device, add device input to capture session
        do {
            if let captureDevice = availableDevices.first {
                captureSession.addInput(try AVCaptureDeviceInput(device: captureDevice))
            }
        } catch {
            print(error.localizedDescription)
        }

        // setup output for Model 1, add output to capture session
        let captureOutput = AVCaptureVideoDataOutput()
        captureSession.addOutput(captureOutput)

        captureOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "videoQueue"))

        let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer.frame = view.frame
        view.layer.addSublayer(previewLayer)

        captureSession.startRunning()

    }

    // called everytime a frame is captured
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {

        guard let model_one = try? VNCoreMLModel(for: imagenet_ut().model) else { return }

        let request = VNCoreMLRequest(model: model_one) { (finishedRequest, error) in
            guard let results = finishedRequest.results as? [VNClassificationObservation] else { return }
            guard let Observation = results.first else { return }

            DispatchQueue.main.async(execute: {

                // use model here
            })
        }

        guard let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }

        // executes request
        try? VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:]).perform([request])

        self.label.text = "label text"

    }

    func setupLabel() {
        let label: UILabel = {
            let label = UILabel()
            label.textColor = .white
            label.translatesAutoresizingMaskIntoConstraints = false
            label.text = "Label"
            label.font = label.font.withSize(30)
            return label
        }90

        view.addSubview(label)
        label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        label.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -50).isActive = true
    }

    func createButton () {
        let button = UIButton();
        button.setTitle("Start Camera", for: .normal)
        button.setTitleColor(UIColor.white, for: .normal)
        button.frame = CGRect(x: 5, y: 710, width: 200, height: 100)

        button.addTarget(self, action: #selector(ViewController.buttonPressed(_:)), for: .touchUpInside)
        self.view.addSubview(button)

    }

    @objc func buttonPressed(_ sender: UIButton!) {
        setupCaptureSession()

        if let buttonTitle = sender.title(for: .normal) {
            print(buttonTitle)
            if buttonTitle == "Stop Camera" {
                print("was stopped")
            }
        }

        sender.setTitle("Stop Camera", for: .normal)
    }

    func stopCamera() {
        captureSession.stopRunning()  // error occurs here
    }
}
like image 919
jKraut Avatar asked Jul 08 '18 00:07

jKraut


1 Answers

To Stop Capture Session:)

func stopSession() {
    if captureSession.isRunning {
        DispatchQueue.global().async {
            self.captureSession.stopRunning()
        }
    }
}
like image 62
SAXENA Avatar answered Nov 12 '22 07:11

SAXENA