user2345335
user2345335

Reputation: 73

AVFoundation videoZoomFactor not working (Swift)

All of the camera tweaks I am wanting to use are working except the zoomfactor. I am lost as to why this is happening...any ideas? The custom exposure and focus settings work fine. Did something change in iOS that im not aware of?

captureSession = AVCaptureSession()
    captureSession?.sessionPreset = AVCaptureSessionPresetPhoto
    stillImageOutput = AVCapturePhotoOutput()

    let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)

    do{
        do{
            try device?.lockForConfiguration()
            device?.setFocusModeLockedWithLensPosition(focusValue, completionHandler: {(time) -> Void in})
            device?.setExposureModeCustomWithDuration(CMTimeMake(1, exposureValue), iso: ISOValue, completionHandler: {(time) -> Void in})
            let zoomFactor:CGFloat = 16
            device?.videoZoomFactor = zoomFactor
            device?.unlockForConfiguration()

        }catch{
            print(error)
        }

        stillImageOutput.isHighResolutionCaptureEnabled = true
        let input = try AVCaptureDeviceInput(device: device)
        if(captureSession.canAddInput(input)){
            captureSession.addInput(input)
            if(captureSession.canAddOutput(stillImageOutput)){
                captureSession.addOutput(stillImageOutput)

                captureSession.startRunning()
                let captureVideoLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer.init(session: captureSession)
                captureVideoLayer.frame = self.previewView.bounds
                captureVideoLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
                self.previewView.layer.insertSublayer(captureVideoLayer, at: 0)
            }
        }
    }catch{
        print(error)
    }

Upvotes: 2

Views: 2946

Answers (3)

Mr.SwiftOak
Mr.SwiftOak

Reputation: 1844

I have faced an issue with zoom factor not working on some devices (usualy the newer ones with wide lens camera) when output.isDepthDataDeliveryEnabled was not set and therefore the default value was true . The problem was present only when AVCaptureSession.Preset was set to .photo.

Upvotes: 1

iKK
iKK

Reputation: 7012

Using Apple's example code for Photo & Video Acquisition (i.e. AVFoundation), I tried to change the device-zoom of my iPhone camera in code.

With the help of user2345335, I realised that the code-location where you place your zoom manipulation properties matters - and also, make sure you use device.lockForConfiguration() prior to any videoDevice manipulation ! Both are important (code-location and locking !!).

Here the Link and a screenshot to see the download-button where the original Apple example can be taken from :

(AVFoundation Apple Code example: Link)

enter image description here

Here is the code excerpt of the original Apple example with MY CODE THAT MANIPULATES THE ZOOM inserted at the correct spot :)

(Swift-4.2 / Xcode 10.0, iOS 11.0 SDK)

// Call this on the session queue.
private func configureSession() {
    if setupResult != .success {
        return
    }

    // ... missing original code (not important for this illustration)...

    // Add video input.
    do {
        var defaultVideoDevice: AVCaptureDevice?

        // ... missing original code (not important for this illustration)...

        if session.canAddInput(videoDeviceInput) {
            session.addInput(videoDeviceInput)
            self.videoDeviceInput = videoDeviceInput

            // ... missing original code (not important for this illustration)...

        } else {
            print("Could not add video device input to the session")
            setupResult = .configurationFailed
            session.commitConfiguration()
            return
        }

        // !!!!!!!!!!!!!!!! MY CODE THAT MANIPULATES THE ZOOM  !!!!!!!!!!!!!!!!!!!!!!!!!!!!
        // !!!!!!!!!!!!!!!! PLACE IT HERE AND ZOOM WILL WORK !!!!!!!!!!!!!!!!!!!!!!!!!!!!
        guard let device = defaultVideoDevice else { return }
        do {
            try device.lockForConfiguration()
            defer { device.unlockForConfiguration() }
            device.videoZoomFactor = 10.0
        } catch {
            debugPrint(error)
        }
        // !!!!!!!!!!!!!! END OF MY CODE THAT MANIPULATES THE ZOOM  !!!!!!!!!!!!!!!!!!!!!!!!!!

    } catch {
        print("Could not create video device input: \(error)")
        setupResult = .configurationFailed
        session.commitConfiguration()
        return
    }

    // Add audio input.
    do {
        let audioDevice = AVCaptureDevice.default(for: .audio)
        let audioDeviceInput = try AVCaptureDeviceInput(device: audioDevice!)

        if session.canAddInput(audioDeviceInput) {
            session.addInput(audioDeviceInput)
        } else {
            print("Could not add audio device input to the session")
        }
    } catch {
        print("Could not create audio device input: \(error)")
    }

    // Add photo output.
    if session.canAddOutput(photoOutput) {
        session.addOutput(photoOutput)

        photoOutput.isHighResolutionCaptureEnabled = true
        photoOutput.isLivePhotoCaptureEnabled = photoOutput.isLivePhotoCaptureSupported
        photoOutput.isDepthDataDeliveryEnabled = photoOutput.isDepthDataDeliverySupported
        livePhotoMode = photoOutput.isLivePhotoCaptureSupported ? .on : .off
        depthDataDeliveryMode = photoOutput.isDepthDataDeliverySupported ? .on : .off

    } else {
        print("Could not add photo output to the session")
        setupResult = .configurationFailed
        session.commitConfiguration()
        return
    }

    session.commitConfiguration()
}

Upvotes: 3

user2345335
user2345335

Reputation: 73

turns out i was just setting my device settings at the wrong point. If the lockconfig try block is moved below the capture session stuff it then works as intended.

Upvotes: 3

Related Questions