0 Replies
      Latest reply on May 18, 2020 5:07 PM by gdmoli.fb
      gdmoli.fb Level 1 Level 1 (0 points)

        Hi, I seem to have run into a problem with the focus modes while trying to capture synchronized videos in an AVCaptureMultiCamSession from the device .builtInDualWideCamera on iPhone 11 Pro Max.

         

        Basically, setting up synchronized recording seems to be working ok with the wide and ultra-wide camera (capturing to AVCaptureMovieFileOutput for each consituent strream).

         

        However, I am trying to set the focusMode in order to lock the wide camera's focus point, and it does not really behave in a way that I'd expect.  The .autoFocus mode doesn't appear to ever stop adjusting (it never locks), and transitioning to .locked mode from either .autoFocus or .continuousAutoFocus does not seem to have any effect.

         

        When I start up the camera, I first set it to .locked mode.  This seems to put it in a state where the lens position for the wide camera appears to be at a position of 1.0.

         

        // Try to set the focus.
                do {
                        try dualWideCamera.lockForConfiguration()
                        dualWideCamera.autoFocusRangeRestriction = .none
                        dualWideCamera.setFocusModeLocked(lensPosition: AVCaptureDevice.currentLensPosition );
                        dualWideCamera.unlockForConfiguration()
                    } catch {
                        print("failed to set the focus!")
                        return false
                    }

         

        Then, elsewhere, I have the following code which can toggle the focus mode between .autoFocus and .locked if a button is pressed:

         

        @IBActionfunc lockFocusTouched(_ sender: UIButton) {
        
                session.beginConfiguration();
                defer {
                        session.commitConfiguration();
                    }
               
        
                print("current position = \(dualWideCameraDeviceInput!.device.lensPosition)")
               
                if(focusLocked){
                   
                    focusLocked = false
                   
                    // Try to set the focus.
                    do {
                            try dualWideCameraDeviceInput!.device.lockForConfiguration()
                            dualWideCameraDeviceInput!.device.autoFocusRangeRestriction = .none
                            dualWideCameraDeviceInput!.device.focusPointOfInterest = CGPoint(x: 0.5, y:0.5)
                            dualWideCameraDeviceInput!.device.focusMode = .autoFocus
                            dualWideCameraDeviceInput!.device.unlockForConfiguration()
                        print("back to autofocus mode")
                        } catch {
                            print("failed to set the focus!")
                        }
                   
                    lockFocusButton.setTitle("Lock Focus", for: .normal);
                   
                }else{  //  Go back to locking the focus
                    focusLocked = true;
                    lockFocusButton.setTitle("Unlock Focus", for: .normal);
                               
                    do{
                    try
                        dualWideCameraDeviceInput!.device.lockForConfiguration()
                        dualWideCameraDeviceInput!.device.focusMode = .locked
                        dualWideCameraDeviceInput!.device.setFocusModeLocked(lensPosition: AVCaptureDevice.currentLensPosition );
                        dualWideCameraDeviceInput!.device.unlockForConfiguration()
                    print("locked mode")
                    } catch {
                        print("failed to set the focus!")
                    }
                }
               
            }

         

        I tried a few ways to set the focus mode to locked (either setFocusModeLocked to currentLensPosition, or just setting focusMode to .locked directly).  Does not seem to matter.

         

        To debug a bit, I added an observer on .isAdjustingFocus and also the lens position.  It seems that isAdjustingFocus starts as FALSE until I switch into autoFocus mode, but then the focuse never settles sAdjustingFocus will never go to FALSE afterwards.  I thought the .autoFocus method should lock at some point, but it doesn't appear to do that.  Neither does the focus stop adjusting if I set .locked.  The observer on .isAdjustingFocus never seems to update to FALSE no matter how I try to lock the focus.

         

        Here is some debug output that shows the isAdjustingFocus gets set to true and never changes back to false.

         

        observer lens position:  Optional(0.827451)          
        observer lens position:  Optional(1.0)                // device starts in .locked, lens is at 1.0
        current position = 1.0
        back to autofocus mode        // switch to .autoFocus
        isAdjustingFocus:  Optional(true)     // observer notices it is now adjusting focus
        observer lens position:  Optional(0.96862745)
        observer lens position:  Optional(0.9372549)
        observer lens position:  Optional(0.90588236)
        observer lens position:  Optional(0.8745098)
        observer lens position:  Optional(0.84313726)
        observer lens position:  Optional(0.8117647)
        observer lens position:  Optional(0.78039217)
        observer lens position:  Optional(0.7607843)
        observer lens position:  Optional(0.7647059)
        observer lens position:  Optional(0.7176471)
        observer lens position:  Optional(0.67058825)
        current position = 0.67058825
        locked mode       // switch back to .locked
        observer lens position:  Optional(0.76862746)     // however lens appears to still be adjusting
        observer lens position:  Optional(0.827451)     // notice no observer for "isAdjustingFocus" ever shows it to be now FALSE
        observer lens position:  Optional(0.8862745)
        observer lens position:  Optional(0.94509804)
        observer lens position:  Optional(1.0)
        observer lens position:  Optional(0.827451)
        observer lens position:  Optional(0.78039217)
        observer lens position:  Optional(0.73333335)
        observer lens position:  Optional(0.7921569)
        observer lens position:  Optional(0.8509804)
        observer lens position:  Optional(0.9098039)
        observer lens position:  Optional(0.96862745)
        observer lens position:  Optional(1.0)
        current position = 1.0
        back to autofocus mode       // toggle back to auto-focus mode  ;   observer on isAdjustingFocus doesn't change
        observer lens position:  Optional(0.94509804)
        observer lens position:  Optional(0.8980392)
        observer lens position:  Optional(0.8509804)
        observer lens position:  Optional(0.7607843)
        observer lens position:  Optional(0.6784314)
        observer lens position:  Optional(0.54509807)
        observer lens position:  Optional(0.745098)
        observer lens position:  Optional(0.6980392)
        observer lens position:  Optional(0.65098035)
        observer lens position:  Optional(0.7490196)
        observer lens position:  Optional(0.80784315)
        observer lens position:  Optional(0.8666667)
        observer lens position:  Optional(0.9254902)
        current position = 0.9254902
        locked mode       // .locked doesn't appear to do anything even though it says the mode is supported when queried
        observer lens position:  Optional(0.9843137)
        observer lens position:  Optional(0.85882354)
        observer lens position:  Optional(0.8117647)
        observer lens position:  Optional(0.7647059)
        observer lens position:  Optional(0.67450976)
        observer lens position:  Optional(0.5921569)

         

        Any thoughts on what the problem could be?  All I really wanted to accomplish with this was to be able to capture synchronized videos from the ultra-wide and wide on the iPhone 11 Pro Max, with the focus on the wide camera locked to a set position.

         

        I see that I cannot set the lens to a custom position (not supported in this mode).  However, it does say that it is supported to at least lock the lens to AVCaptureDevice.currentLensPosition in the documentation.

         

        So my thinking was that to get the lens to a desired position I could set to autoFocus, wait until the lens focuses at the distance that I want it, and then lock the focus to currentLensPosition by pushing a button in the UI.

         

        That said, I think it's a bit restrictive to not allow the wide lens to be focused to a custom lens position for this application (computer vision).  In some cases we want to control its focus position.  For instance if someone wanted to try depth from defocus with this, they would want to be able to set the focus to a number of known positions manually while capturing synchronized camera data.  In such an application we might not rely on calibration data from the iPhone (could use other methods).  It would be nice if there were a method to just control the focus or set manual exposure settings etc, without interrference, and still capture synchronized data.