We are using latest Swift Code and AVFoundation API's to create a camera App which has Flash, Reverse camera and Capture photo functionality. Code needs to support ios10 onwards.
Issue we are having is Camera flash appears, but doesn't get captured in the photo(basically camera flash appears a bit sooner than the photo capture or photo capture is bit slower than the flash) Which is making our flash funcitonality useless.
here is the code for our Camera Capture:
//Function to capture the image from the camera session -> this gets called from the ViewController Outlet action OnCapture
func capture() throws {
guard captureSession.isRunning else {
throw CameraRuntimeError.captureSessionIsMissing
}
let settings = AVCapturePhotoSettings()
if getCurrentCamera().isFlashAvailable {
settings.flashMode = self.flashMode
}
self.photoOutput?.capturePhoto(with: settings, delegate: self)
}
And here is the delegate:
extension CameraFunctions: AVCapturePhotoCaptureDelegate {
private static let failedToConvertToJPEGErrorCode = "JPEGERROR"
private static let failedToCaptureImage = "CAMERROR"
public func photoOutput(_ captureOutput: AVCapturePhotoOutput,
didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?,
previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?,
resolvedSettings: AVCaptureResolvedPhotoSettings,
bracketSettings: AVCaptureBracketedStillImageSettings?, error: Swift.Error?) {
if error != nil {
onPhotoCaptured(StringResult(error: ServicesError(CameraFunctions.failedToCaptureImage, error!.localizedDescription)))
}
if let buffer = photoSampleBuffer, let data = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: buffer, previewPhotoSampleBuffer: nil) {
let encodedString = //DO ENCODING OF THE PHOTO
onPhotoCaptured(encodedString)
} else {
onPhotoCaptured(StringResult(error: ServicesError(CameraFunctions.failedToConvertToJPEGErrorCode, CameraRuntimeError.failedToConvertImageToJPEG.localizedDescription)))
}
closeCaptureSession()
}
}
onPhotoCaptured is present in a ViewController.
please let us know if we are doing something wrong.
setting the prepared Settings for photo output solved this issue:
func capture(_ delegate: AVCapturePhotoCaptureDelegate, _ onError: @escaping (Error) -> Void) throws {
guard captureSession.isRunning else {
throw CameraRuntimeError.captureSessionIsMissing
}
let settings: AVCapturePhotoSettings
if #available(iOS 11.0, *) {
settings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])
settings.isAutoStillImageStabilizationEnabled = true
} else {
settings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecJPEG])
}
if getCurrentCamera().isFlashAvailable {
settings.flashMode = self.flashMode
}
//This statement did the magic
self.photoOutput?.setPreparedPhotoSettingsArray([settings]) { (suc: Bool, err: Error?) -> Void in
if suc {
self.photoOutput?.capturePhoto(with: settings, delegate: delegate)
}
if err != nil {
onError(err!)
}
}
}