iosobjective-cswiftiphone

AVCaptureDevice Unsupported frame duration iPhone 11 Pro Max


I have been using AVCaptureDevice method set activeVideoMinFrameDuration prior to the new iPhone 11 without any problems however testing the same code with the new iPhone 11 Pro max (Actual device), The app crashes with error message: -

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:-[AVCaptureDevice setActiveVideoMinFrameDuration:] Unsupported frame duration - use -activeFormat.videoSupportedFrameRateRanges to discover valid ranges

The same code works well with older phones. Actually I am using the exact sample code from Apple documentation

func configureCameraForHighestFrameRate(device: AVCaptureDevice) {

    var bestFormat: AVCaptureDevice.Format?
    var bestFrameRateRange: AVFrameRateRange?

    for format in device.formats {
        for range in format.videoSupportedFrameRateRanges {
            if range.maxFrameRate > bestFrameRateRange?.maxFrameRate ?? 0 {
                bestFormat = format
                bestFrameRateRange = range
            }
        }
    }

    if let bestFormat = bestFormat, 
       let bestFrameRateRange = bestFrameRateRange {
        do {
            try device.lockForConfiguration()

            // Set the device's active format.
            device.activeFormat = bestFormat

            // Set the device's min/max frame duration.
            let duration = bestFrameRateRange.minFrameDuration
            device.activeVideoMinFrameDuration = duration
            device.activeVideoMaxFrameDuration = duration

            device.unlockForConfiguration()
        } catch {
            // Handle error.
        }
    }
}

As I have mentioned above this code works well with older devices but not iPhone 11 series (Tested on 11 Pro max).

Does anyone have a workaround or solution for this issue?


Solution

  • For anyone who will run into the same issue in the future. Here is what I did to fix the issue by following the debug error description.

     // Important part: You must get the supported frame duration and use it to set max and min frame durations. 
    let supportedFrameRanges = device.activeFormat.videoSupportedFrameRateRanges.first
    
    // Then use it, note that only fall back to bestFrameRateRange if supportedFrameRanges is nil.            
    device.activeVideoMinFrameDuration = supportedFrameRanges?.minFrameDuration ?? bestFrameRateRange.minFrameDuration
    device.activeVideoMaxFrameDuration = supportedFrameRanges?.maxFrameDuration ?? bestFrameRateRange.maxFrameDuration