Коды ошибок 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)
}
}
ЗАМЕТКИ
- Пример кода Apple AVCam внимательно следил.
- Этот сбой происходит ТОЛЬКО после одного из более успешных снимков. Произведенный RAW файл отлично подойдет.
1 ответ
ОБНОВИТЬ
Ты звонишь updatePhotoSettings()
до завершения захвата изображения, что вызывает ошибки. Попробуйте сделать это из обработчика завершения или перед тем, как сделать снимок.
ps Действительно, AVFoundation должен был усложнить эту ошибку или, по крайней мере, сделать ее более понятной, что это не сработает.
предыдущие неверные догадки
Вы не показываете, как вы настраиваете AVCaptureSession
что важно, но
если вы включите
AVCapturePhotoSettings
isHighResolutionPhotoEnabled
необходимо также включитьisHighResolutionCaptureEnabled
(возможноhighResolutionCaptureEnabled
для вас - какую версию swift вы используете?):self.photoOutput.isHighResolutionCaptureEnabled = true
ваш
PhotoCaptureDelegate
Похоже, это выходит за рамки, что не поможет. Присвойте его переменной-члену, чтобы продлить его жизнь.установить
.photo
предустановлен на вашемAVCaptureSession