AVFoundation Error Codes

I am getting following two error messages when taking RAW and also JPEG photos. I have no way to diagnose these:


Error capturing photo: Error Domain=AVFoundationError- Domain Code=-11800 "The operation could not be completed" Userlnfo={NSLocalizedFailur- eReason=An unknown erroroccurred (42686), NSLocalizedDescription:The operation could not be completed, NSUnderlyingEr- ror=0x1c804bfa0 {Error Domain=NSOSStatusError- Domain Code=-12686 "(null)"}}


Error capturing photo: Error Domain=AVFoundationError-Domain Code=-11800 The operation could not be completed" UserInfo.{NSLocalized-FailureReason=An unknown error occurred (-16802), NSLocalizedDescription=The operation could not be completed, NSUnderlyingEr-ror=0x1c4243f30 {Error Domain=NSOSStatusError-Domain Code=-16802 "(null)"}}


This seems to happen right after this function in AVCapturePhotoCaptureDelegate:


optional func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?)


These seem to happen randomly upon repeated photo capturing.

Accepted Answer

-12686 indicates that there was a buffer allocation failure near the beginning of the camera pipeline.

-16802 is similarly an indication of still image failure at the driver layer.


Neither of these are ever supposed to happen. Have you filed a bug at bugreport.apple.com, including code that reproduces the problem?

As it turned out, using preparedPhotoSettingsArray and updating it while the capture is not finished is the cause.


We had to completely ditch preparedPhotoSettingsArray and just allocated photosettings right before each capture.

The correct way to use preparedPhotoSettingsArray is to set up an array of all possible photo capture settings you might use ***BEFORE*** you start running. This will give the photo output the opportunity to preallocate the memory for the worst case scenario.


You should not be setting this property while you've got captures in flight.

" ***BEFORE*** you start running"

Before the session starts? However, since photo settings has to be reallocated after each time, Don't you have to refresh this array each time?


This was my basic approach:


  1. setupPhotoSettings (empty preparedPhotoSettingsArray, allocate new AVCapturePhotoSettings, append to preparedPhotoSettingsArray) prior to capturing
  2. Capture
  3. setupPhotoSettings for next capture (empty preparedPhotoSettingsArray, allocate new AVCapturePhotoSettings, append to preparedPhotoSettingsArray)


With above method somehow step 3 was taking pleace while step 2 was finishing with fast repeated captures.

" ***BEFORE*** you start running"

Before the session starts?


Yes.


However, since photo settings has to be reallocated after each time, Don't you have to refresh this array each time?


Don't think of AVCapturePhotoSettings as being a new allocation of memory. Much of the memory used by the capture render pipeline is pooled , so it doesn't need to be reallocated with each request.


This was my basic approach:


  1. setupPhotoSettings (empty preparedPhotoSettingsArray, allocate new AVCapturePhotoSettings, append to preparedPhotoSettingsArray) prior to capturing
  2. Capture
  3. setupPhotoSettings for next capture (empty preparedPhotoSettingsArray, allocate new AVCapturePhotoSettings, append to preparedPhotoSettingsArray)


With above method somehow step 3 was taking pleace while step 2 was finishing with fast repeated captures.



You shouldn't set up for the next capture (sending new prepared settings) before the in-flight photo requests have completed. You are free to set it at a quiescent time when you're not issuing photo requests. But as I mentioned earlier, you can just send an array of all the capture settings you might use at the outset, and photo output will be prepared for the worst.

Since I am a little lost on this, let me post some code snippet:


func configureSession() {
     .....setup session code

     //Get ready for first capture
     self.setupPhotoSettings()
}

func setupPhotoSettings() {
     self.photoOutput.setPreparedPhotoSettingsArray([])
     var newPhotoSettings : AVCapturePhotoSettings
     if #available(iOS 11.0, *) {
                newPhotoSettings = AVCapturePhotoSettings(format: self.heifSetting)
                newPhotoSettings.isHighResolutionPhotoEnabled = true
                newPhotoSettings.flashMode = self.flashMode
                newPhotoSettings.isAutoStillImageStabilizationEnabled = true
                newPhotoSettings.livePhotoMovieFileURL = nil
                self.photoOutput.photoSettingsForSceneMonitoring = newPhotoSettings

     } else {
                newPhotoSettings = AVCapturePhotoSettings(format: self.jpegSetting)
                newPhotoSettings.isHighResolutionPhotoEnabled = true
                newPhotoSettings.flashMode = self.flashMode
                newPhotoSettings.isAutoStillImageStabilizationEnabled = true
                newPhotoSettings.livePhotoMovieFileURL = nil
                self.photoOutput.photoSettingsForSceneMonitoring = newPhotoSettings

    }
    self.photoOutput.setPreparedPhotoSettingsArray([newPhotoSettings])
}

func capture() {

     let photoCaptureDelegate = PhotoCaptureDelegate(with: self.photoOutput.preparedPhotoSettingsArray.first!,
                                willCapturePhotoAnimation:
     {

     }, didCapturePhoto: {


     }, completed:  { [unowned self] photoCaptureDelegate in
          self.inProgressPhotoCaptureDelegates[photoCaptureDelegate.requestedPhotoSettings.uniqueID] = nil
          //Get ready for next capture
          self.setupPhotoSettings()

     })


}


If I am way off here, please consider including preparedPhotoSettingsArray in future sample code.

AVFoundation Error Codes
 
 
Q