Коды ошибок AVFoundation

Я получаю следующие два сообщения об ошибках при съемке RAW, а также фотографий в формате JPEG. У меня нет возможности диагностировать это:

Фотография захвата ошибки: Ошибка Домен =AVFoundationError- Код домена =-11800 "Операция не может быть завершена" Userlnfo={NSLocalizedFailur- eReason= Произошла неизвестная ошибка (42686), NSLocalizedDescription: Операция не может быть завершена, NSUnderlyingEr- ror=0x1c804fa0 {Ошибка домена =NSOSStatusError- Код домена =-12686 "(ноль)"}}

также...

Фотография захвата ошибки: Ошибка Domain=AVFoundationError- Domain Code=-11800 Операция не может быть завершена " UserInfo.{NSLocalized-FailureReason= Произошла неизвестная ошибка (-16802), NSLocalizedDescription= Операция не может быть завершена, NSUnderlyingEr-ror=0x1c4243f30 {Ошибка домена =NSOSStatusError-Domain Code=-16802 "(null)"}}

Это, кажется, происходит сразу после этой функции в AVCapturePhotoCaptureDelegate:

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

Это происходит случайно при повторном захвате фотографий.

ОБНОВИТЬ

Настройка RAW

       func updatePhotoSettings () {
self.photoOutput.setPreparedPhotoSettingsArray([])

let newPhotoSettings = AVCapturePhotoSettings(rawPixelFormatType: OSType(self.photoOutput.availableRawPhotoPixelFormatTypes.first!),
                                                          processedFormat: [AVVideoCodecKey : AVVideoCodecJPEG])
            newPhotoSettings.previewPhotoFormat = [kCVPixelBufferPixelFormatTypeKey as String: self.photoOutput.availablePhotoPixelFormatTypes[0]]
            if #available(iOS 11.0, *) {
                newPhotoSettings.embeddedThumbnailPhotoFormat =  [AVVideoCodecKey: self.photoOutput.availablePhotoCodecTypes[0]]
            }
            newPhotoSettings.isHighResolutionPhotoEnabled = true
            newPhotoSettings.flashMode = self.flashMode
            newPhotoSettings.isAutoStillImageStabilizationEnabled = false
            newPhotoSettings.livePhotoMovieFileURL = nil
            self.photoOutput.photoSettingsForSceneMonitoring = newPhotoSettings

            self.photoOutput.setPreparedPhotoSettingsArray([newPhotoSettings])

}

Захват Звонок:

final func snapImage () {

            let photoCaptureDelegate = PhotoCaptureDelegate(with: self.photoOutput.preparedPhotoSettingsArray.first!,
                                       willCapturePhotoAnimation: {
                //Shutter animation
                DispatchQueue.main.async { [unowned self] in
                    self.previewView.videoPreviewLayer.opacity = 0
                    UIView.animate(withDuration: 0.1, animations: {
                        self.previewView.videoPreviewLayer.opacity = 1
                    })
                }

            }, didCapturePhoto: {

                //Photo Saved animation

            }, completed:  { [unowned self] photoCaptureDelegate in
                self.inProgressPhotoCaptureDelegates[photoCaptureDelegate.requestedPhotoSettings.uniqueID] = nil
            })


            self.inProgressPhotoCaptureDelegates[photoCaptureDelegate.requestedPhotoSettings.uniqueID] = photoCaptureDelegate

            self.photoOutput.capturePhoto(with: self.photoOutput.preparedPhotoSettingsArray.first!, delegate: photoCaptureDelegate)

            DispatchQueue.main.async {
                //Goes to update photo settings for next shot
                self.updatePhotoSettings()
            }
        }
    }

Делегат захвата фотографий

import AVFoundation
import Photos
import MobileCoreServices

class PhotoCaptureDelegate: NSObject, AVCapturePhotoCaptureDelegate {


         private(set) var requestedPhotoSettings     : AVCapturePhotoSettings

         private let willCapturePhotoAnimation       : () -> ()
         private let didCapturePhoto                 : () -> ()
         private let completed                       : (PhotoCaptureDelegate) -> ()

         private var jpegPhotoData                   : Data?

         private var dngPhotoData                    : Data?


    // MARK: - Initialization
    init(with requestedPhotoSettings: AVCapturePhotoSettings,
        willCapturePhotoAnimation: @escaping () -> (),
        didCapturePhoto: @escaping () -> (),
        completed: @escaping (PhotoCaptureDelegate) -> ())
    {
        self.requestedPhotoSettings = requestedPhotoSettings
        self.willCapturePhotoAnimation = willCapturePhotoAnimation
        self.didCapturePhoto = didCapturePhoto
        self.completed = completed
    }


    private final func didFinish() {
        self.completed(self)
    }

    // MARK: - Will Capture
    final func capture(_ captureOutput: AVCapturePhotoOutput, willCapturePhotoForResolvedSettings resolvedSettings: AVCaptureResolvedPhotoSettings) {
        willCapturePhotoAnimation()
    }

    final func capture(_ output: AVCapturePhotoOutput, willBeginCaptureForResolvedSettings resolvedSettings: AVCaptureResolvedPhotoSettings) {

    }


    // MARK: - iOS 11 Did Finish Photo
    @available(iOS 11.0, *)
    final func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {

            if let error = error {

                PhotoCaptureDelegate.showError(sentMessage: "Error processing photo: \(error)")
                self.didCapturePhoto()

            } else {

                if photo.isRawPhoto {
                    self.dngPhotoData = photo.fileDataRepresentation()
                    return

                } else {
                    if self.jpegPhotoData == nil {
                        self.jpegPhotoData = photo.fileDataRepresentation()
                        self.didCapturePhoto()
                        return
                    }
                }
            }
    }


    // MARK: - Did Finish Capture
    final func capture(_ captureOutput: AVCapturePhotoOutput, didFinishCaptureForResolvedSettings resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) {

        if let error = error {
            PhotoCaptureDelegate.showError(sentMessage: "Error capturing photo: \(error)")
            didFinish()
            return


        if PHPhotoLibrary.authorizationStatus() == .authorized {

                var temporaryDNGFileURL : URL? = nil
                self.dngPhotoData != nil {
                        temporaryDNGFileURL = URL(fileURLWithPath: NSTemporaryDirectory().appending("\(resolvedSettings.uniqueID).dng"))
                        do {
                            try self.dngPhotoData!.write(to: temporaryDNGFileURL!, options: [.atomic])
                        } catch let error as NSError {
                            PhotoCaptureDelegate.showError(sentMessage: "Could not write DNG Data: \(error)")
                            return
                        }
                }

                PHPhotoLibrary.shared().performChanges({
                    let creationRequest = PHAssetCreationRequest.forAsset()
                    if (self.jpegPhotoData != nil) {

                        creationRequest.addResource(with: .photo, data: self.jpegPhotoData!, options: nil)

                        if let temporaryDNGFileURL = temporaryDNGFileURL {

                            let companionDNGResourceOptions = PHAssetResourceCreationOptions()
                            companionDNGResourceOptions.shouldMoveFile = true
                            creationRequest.addResource(with: .alternatePhoto, fileURL: temporaryDNGFileURL, options: companionDNGResourceOptions)

                        }
                    }
                }, completionHandler: { [unowned self] success, error in

                    if let error = error {
                        PhotoCaptureDelegate.showError(sentMessage: "Error occurered while saving photo to photo library: \(error)")
                    }
                    if (temporaryDNGFileURL != nil) {
                        if FileManager.default.fileExists(atPath: temporaryDNGFileURL!.path) {
                            do {
                                try FileManager.default.removeItem(at: temporaryDNGFileURL!)
                            } catch let error as NSError {
                                PhotoCaptureDelegate.showError(sentMessage: "Could not remove DNG File: \(error)")
                            }
                        }
                    }

                })


            }

        else {
            PhotoCaptureDelegate.showError(sentMessage: "Not authorized to save photo")
            self.didFinish()
            return
        }

}



    private static func showError (sentMessage: String) {
        let alertController = UIAlertController(title: nil, message: sentMessage, preferredStyle: UIAlertControllerStyle.alert)
        let cancelAction = UIAlertAction(title: NSLocalizedString("OK", comment: "Alert button title."), style: UIAlertActionStyle.cancel, handler: nil)
        alertController.addAction(cancelAction)
        let appDelegate  = UIApplication.shared.delegate as! AppDelegate
        appDelegate.window!.rootViewController!.present(alertController, animated: true, completion: nil)
    }

}

ЗАМЕТКИ

  1. Пример кода Apple AVCam внимательно следил.
  2. Этот сбой происходит ТОЛЬКО после одного из более успешных снимков. Произведенный RAW файл отлично подойдет.

1 ответ

Решение

ОБНОВИТЬ

Ты звонишь updatePhotoSettings() до завершения захвата изображения, что вызывает ошибки. Попробуйте сделать это из обработчика завершения или перед тем, как сделать снимок.

ps Действительно, AVFoundation должен был усложнить эту ошибку или, по крайней мере, сделать ее более понятной, что это не сработает.

предыдущие неверные догадки

Вы не показываете, как вы настраиваете AVCaptureSession что важно, но

  1. если вы включите AVCapturePhotoSettingsisHighResolutionPhotoEnabledнеобходимо также включить isHighResolutionCaptureEnabled (возможно highResolutionCaptureEnabled для вас - какую версию swift вы используете?):

    self.photoOutput.isHighResolutionCaptureEnabled = true
    
  2. ваш PhotoCaptureDelegate Похоже, это выходит за рамки, что не поможет. Присвойте его переменной-члену, чтобы продлить его жизнь.

  3. установить .photo предустановлен на вашем AVCaptureSession

Другие вопросы по тегам