How to accurately set fast shutter speeds (exposure duration) on an AVCaptureDevice?
Asked Answered
G

0

9

I'm working on a camera app for IOS (13). For that I use an AVCaptureSession in conjunction with an AVCaptureVideoPreviewLayer. So far everything works fine.

Now I want to let the user choose and set a custom shutter speed (exposure duration) out of an given array of typical shutter speed values (in 1/3-exposure-stops) as an [Int32]:

let shutterSpeedValues: [Int32] = [1, 2, 3, 4, 5, 6, 8, 10, 13, 15, 20, 25, 30, 40, 50, 60, 80, 100, 125, 160, 200, 250, 320, 400, 500, 640, 800, 1000, 1250, 1600, 2000, 2500, 3200, 4000, 5000, 6400, 8000, 10000, 12800, 16000, 20000, 2400]

I set the desired exposure the - as far as I understand - only possible way with following function:

captureDevice?.setExposureModeCustom(duration: CMTimeMake(value: 1, timescale: shutterSpeedValues[index]), iso: AVCaptureDevice.currentISO, completionHandler: nil)

Checking AVCaptureDevice's exposureDuration value shows that this gives totaly accurate results for slower shutter speeds (up to 1/200th of a second). Than the discrepancies become exponentially bigger the faster the choosen exposure duration is. E.g.:

1/250th -> 1/251th
1/400th -> 1/403th
1/640th -> 1/648th
1/1000th -> 1/1021th
1/4000th -> 1/4366th
1/8000th -> 1/9615th
1/1200th -> 1/16129th
1/16000th -> 1/24390th
1/20000th -> 1/24390th
1/24000th -> 1/49999th (which is the activeFormat's minExposureDuration in this case)

I understand that there is a difference between the nominal shutter speeds (rounded approximate numbers which are more convenient for the user), and the precise actual shutter speed the camera uses (see https://www.scantips.com/lights/fstop2.html). Latter ones differing from each other exactly by a factor of 2x or 1/2 exposure of the adjacent stop (which would be values like 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, 1/128, 1/256, 1/512, 1/1024, ..., 1/4096, ..., 1/8192...). This however still doesn't explain these extreme discrepancies I get with faster shutter speeds.

I also tried setting a (random) fast shutter speed explicitly like this:

captureDevice?.setExposureModeCustom(duration: CMTimeMake(value: 1, timescale: 10000, iso: AVCaptureDevice.currentISO, completionHandler: nil)

or this

captureDevice?.setExposureModeCustom(duration: CMTimeMakeWithSeconds(0.0001, preferredTimescale: 1000000000), iso: AVCaptureDevice.currentISO, completionHandler: nil) 

but both still results in a exposure duration of 1/12048th (instead of 1/10000)...

Am I missing something CMTime related, has this something to do with the frame rate of the video (though changing the captureDevice's activeVideoMinFrameDuration and activeVideoMaxFrameDuration didn't have any effect) or is it simply impossible to set completely custom exposure durations?

Btw. I encountered the same problem while trying to implement a feature which should allow the user to define a minimum shutter speed in (continuous) auto exposure mode (for which I used the captureDevice's activeMaxExposureDuration function)...

Any ideas or hints would be greatly appreciated.

Gerlac answered 28/11, 2019 at 18:45 Comment(1)
have you found out anything about this? I'm experiencing a similar issue at the moment.Velleman

© 2022 - 2024 — McMap. All rights reserved.