macOS set AVCaptureDevice to support wide range of lighting

How do I setup an AVCaptureDevice and/or AVCaptureSession to support a wide range of lighting scenarios ("normal" top-lit by artificial lighting, sunlight from behind, sunlight from in front, etc.)?


The code I am currently using is giving me blackened images from a MacBookPro camera circa 2012 when the user is facing the camera with her back to a window the sun is shining through. I am using as much automatic settings for exposure and whitebalance as I can, and yet the problem is still occurring.


let session = AVCaptureSession()
session.beginConfiguration()
defer {
     session.commitConfiguration()
}
if let videoDevice = AVCaptureDevice.default(for: AVMediaType.video) {
     guard let videDeviceInput = try? AVCaptureDeviceInput(device: videoDevice), session.canAddInput(videoDeviceInput) else {
          return
     }
     session.sessionPreset = .photo
     do {
          try videoDevice.lockForConfiguration()
          if videoDevice.isExposureModeSupported(.continuousAutoExposure) {
               videoDevice.exposureMode = .continuousAutoExposure
          } else if videoDevice.isExposureModeSupported(.autoExposure) {
               videoDevice.exposureMode = .autoExposure
          } else {
               NSLog("unable to set exposure mode")
          }
          if videoDevice.isWhiteBalanceModeSupported(.continuousAutoWhiteBalance) {
               videoDevice.whiteBalanceMode = .continuousAutoWhiteBalance
          } else if videoDevice.isWhiteBalanceModeSupported(.autoWhiteBalance) {
               videoDevice.whiteBalanceMode = .autoWhiteBalance
          } else {
               NSLog("unable to set white balance mode")
          }
          let centerPoint = CGPoint(x:0.50, y:0.50)
          if videoDevice.isExposurePointOfInterestSupported {
               videoDevice.exposurePointOfInterest = centerPoint
          }
          if videoDevice.isFocusPointOfInterestSupported {
               videoDevice.focusPointOfInterest = centerPoint
          }
          videoDevice.unlockForConfiguration()
     } catch let error {
          NSLog(error.localizedDescription)
     }
     session.addInput(videoDeviceInput)
     let outputCapture = AVCaptureStillImageOutput()
     guard session.canAddOutput(outputCapture) else {NSLog("unable to add output capture") ; return}
     session.addOutput(outputCapture)
}


My goal is to achieve the best possible image by telling the camera to automatically adjust all the parameters it can, like an old-school Canon AE-1 program used to back in the day.

Accepted Reply

Found it!


It turns out that it wasn't a problem in the configuration/setup. My capture code was executing:


session.startRunning()


immediately followed by:


capture.captureStillImageAsynchronously(from: connection) {...}


The solution: before calling session.startRunning(), add a notification observer to execute upon receiving an NSNotification.Name.AVCaptureSessionDidStartRunning notification - because then the camera is setup to do what it is supposed to do in most lighting conditions.

Replies

Found it!


It turns out that it wasn't a problem in the configuration/setup. My capture code was executing:


session.startRunning()


immediately followed by:


capture.captureStillImageAsynchronously(from: connection) {...}


The solution: before calling session.startRunning(), add a notification observer to execute upon receiving an NSNotification.Name.AVCaptureSessionDidStartRunning notification - because then the camera is setup to do what it is supposed to do in most lighting conditions.