Torch brightness control using AVCaptureDevice.setTorchModeOn behaves very erratically

Viewed 309

In every documentation I looked into, it seems that AVCaptureDevice's setTorchModeOn takes a value from 0.0 to 1.0 and sets the brightness accordingly, if cases like overheating don't occur. But in my tests with an iPhone 11, setTorchModeOn behaves very erratically.

It seems like every subsequent call to setTorchModeOn changes the brightness based on the last brightness. So, if you call device.setTorchModeOn(0.1) after calling device.setTorchModeOn(0.2), the torch brightness doesn't increase, but basically shuts down. And this persists across App restarts. The torch doesn't work anymore, because I guess the brightness is too low now (0.02 maybe) for it to even operate.

Small example for hypothesis:

guard let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else { return }

do {
  try device.lockForConfiguration()
  for i in stride(from: Float(0.5), to: 1.0, by: 0.1) {
    try device.setTorchModeOn(level: i)
    print(device.torchLevel, i)
    sleep(1)
  }
  device.unlockForConfiguration()
} catch { print(error) }

In this code, the brightness doesn't increase, but keeps on decreasing every second. And when you restart the app, it starts at a lower brightness than the first time (same as the last brightness the previous run left it at), and decreases down to nothing, and then the torch doesn't work in the app. Even if I reinstall the app, it doesn't work. The system torch and the camera flash keep working though. The only way I am able to reset it back is to restart the phone, or click a photo in the camera app with the flash on.

I am very stumped by this. Do I have to reset the state of the device or something to prevent this? I am trying to vary the torch brightness up and down in a specific pattern, but it feels like it's impossible to go back up. Exceptions are thrown if you send a value outside (0,1) bounds. I tried mixing it with AVCaptureDevice.maxAvailableTorchLevel which didn't work reliably either. Can anyone confirm that this happens to them too?

PS: device.torchLevel doesn't seem to get reflect the arguments I sent. Instead, seems to have strange behaviour too. The stdout of the above code is:

0.0 0.5
0.0 0.6
0.0 0.7
0.0 0.8
0.0 0.9

This is in both the cases. In the first run, where the brightness decreases 5 times, and the second run, when brightness starts low, and decreases once before going off.

On iOS 13.4, Swift 5.2

0 Answers
Related