IOS camera zoom not working swift - xcode

Viewed 156

I have iPhone 13 pro with iOS version 15.5. I am using XCode version 13.3.1. I am trying to achieve camera zoom with the AVFoundation.

Below is the code I have tried out. The camera device selected is the .builtInTripleCamera. I would like to take macro images. I am trying out different zoom factors like 1.0, 3.0 and 15.0. But the camera preview is not changing. I am not sure whether this is the current method to obtain zoomed-in camera preview as well as the output. Did anybody manage to correctly set the camera zoom factor with AVFoundation?

 private let captureSession = AVCaptureSession()
    private lazy var previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
    private let videoDataOutput = AVCaptureVideoDataOutput()
    private var cameraDevice: AVCaptureDevice?


   override func viewDidLoad() {
        super.viewDidLoad()
        
        self.setCameraInput()
        self.setCameraOutput()
        self.showCameraFeed()
   
        self.captureSession.beginConfiguration()
        self.captureSession.sessionPreset = AVCaptureSession.Preset.high;
        self.captureSession.commitConfiguration()
        self.captureSession.startRunning()
    }


    private func showCameraFeed() {
        self.previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
        self.view.layer.insertSublayer(self.previewLayer, at: 1)
        self.previewLayer.frame = self.view.frame
//        self.view.addGestureRecognizer(pgr)
    }
    
    
    private func setCameraInput() {
        let deviceTypes: [AVCaptureDevice.DeviceType]
        if #available(iOS 13, *) {
            deviceTypes = [.builtInTripleCamera, .builtInDualWideCamera, .builtInDualCamera, .builtInWideAngleCamera]
        } else {
            deviceTypes = [.builtInDualCamera, .builtInWideAngleCamera]
        }
        
        let session = AVCaptureDevice.DiscoverySession(
            deviceTypes: deviceTypes,
            mediaType: .video,
            position: .back
        )
        
        guard let device = session.devices.first else {
            fatalError("No back camera device found.")
        }
        cameraDevice = device
        addInputToSession(device: cameraDevice!, session: self.captureSession)
    }
    
    
    private func addInputToSession(device:AVCaptureDevice,session:AVCaptureSession){
        let cameraInput = try! AVCaptureDeviceInput(device: device)
        if(session.canAddInput(cameraInput)){
            
            do{
                try device.lockForConfiguration()
                cameraInput.device.videoZoomFactor = 15
                session.addInput(cameraInput)
                device.unlockForConfiguration()
            }catch{
                print(error)
            }
        }
    }
    
    private func setCameraOutput() {
        self.videoDataOutput.videoSettings = [(kCVPixelBufferPixelFormatTypeKey as NSString) : NSNumber(value: kCVPixelFormatType_32BGRA)] as [String : Any]
        self.videoDataOutput.alwaysDiscardsLateVideoFrames = true
        self.videoDataOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "camera_frame_processing_queue"))

        self.captureSession.addOutput(self.videoDataOutput)
        guard let connection = self.videoDataOutput.connection(with: AVMediaType.video),
              connection.isVideoOrientationSupported else { return }
        connection.videoOrientation = .portrait
    }
1 Answers

Handle camera zoom with pinch recognizer.

cameraDevice.videoZoomFactor 

and set it to the recognizer on .began state like this

@objc private func viewPinched(recognizer: UIPinchGestureRecognizer) {
    switch recognizer.state {
        case .began:
            recognizer.scale = cameraDevice.videoZoomFactor
        case .changed:
            let scale = recognizer.scale
            do {
                 try cameraDevice.lockForConfiguration()
                 cameraDevice.videoZoomFactor = max(cameraDevice.minAvailableVideoZoomFactor, min(scale, cameraDevice.maxAvailableVideoZoomFactor))
                 cameraDevice.unlockForConfiguration()
            }
            catch {
                print(error)
            }
        default:
            break
    }
}
Related