AVCapturePhotoOutput - настройки нельзя использовать повторно - PullRequest
0 голосов
/ 08 января 2019

Я использую ios 12 swift 4.2.

Я реализовал базовую сессию захвата камеры и щелкаю изображения из нее. Все хорошо, пока я не переключаю вспышку между режимом авто / вкл / выкл. После того, как я щелкнул первую фотографию, а затем изменил режим вспышки, приложение вылетает с ошибкой:

[AVCapturePhotoOutput capturePhotoWithSettings:delegate:] Settings may not be re-used'

Ниже приведена реализация камеры:

var captureSession: AVCaptureSession!
var videoPreviewLayer: AVCaptureVideoPreviewLayer!
var capturePhotoOutput: AVCapturePhotoOutput!
let capturePhotoSettings = AVCapturePhotoSettings()


var previewView: UIView!


override func viewDidLoad() {
    startCameraSession()
    setupCaptureOutput()
}

@objc // Tap on a button to capture
func takePhotoOnTap() {
    guard let capturePhotoOutput = self.capturePhotoOutput else { return }

    capturePhotoSettings.isAutoStillImageStabilizationEnabled = true
    capturePhotoSettings.isHighResolutionPhotoEnabled = true
    capturePhotoSettings.flashMode = .auto
    let _ = getSettings(camera: captureDevice!, flashMode: spotmiCameraOptions.flashMode)
    capturePhotoOutput.capturePhoto(with: capturePhotoSettings, delegate: self)
}


    //This is a delegate method from the button
func toggleFlash(mode: FlashMode) {

    switch mode {
    case .auto:
        capturePhotoSettings.flashMode = .auto
    case .enabled:
        capturePhotoSettings.flashMode = .on
    case .disabled:
        capturePhotoSettings.flashMode = .off
    }

}


func setupCaptureOutput() {
    capturePhotoOutput = AVCapturePhotoOutput()
    capturePhotoOutput.isHighResolutionCaptureEnabled = true
    captureSession.addOutput(capturePhotoOutput)
}

func startCameraSession() {

    let captureDevice = AVCaptureDevice.default(.builtInDualCamera, for: AVMediaType.video, position: .back)

    do {
        let input = try AVCaptureDeviceInput(device: captureDevice!)
        captureSession = AVCaptureSession()
        captureSession.addInput(input)
        videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        videoPreviewLayer.videoGravity = .resizeAspectFill
        videoPreviewLayer.frame = self.view.layer.bounds
        camcontainer.layer.addSublayer(videoPreviewLayer)
        captureSession.startRunning()
    } catch {
        print(error.localizedDescription)
    }


}

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {
    guard error == nil, let sampleBuffer = photoSampleBuffer else {
        print("error capturing photo due to \(String(describing: error?.localizedDescription))")
        return
    }
    guard let imageData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: sampleBuffer, previewPhotoSampleBuffer: previewPhotoSampleBuffer) else  { return }

    let capturedImage = UIImage(data: imageData, scale: 1.0)
    if let image = capturedImage {
        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
    }
}

    func getSettings(camera: AVCaptureDevice, flashMode: FlashMode) -> AVCapturePhotoSettings {
    let settings = capturePhotoSettings

    if camera.hasFlash {
        switch flashMode {
//            case .auto: settings.flashMode = .auto
        case .enabled: settings.flashMode = .on
        case .disabled: settings.flashMode = .off
        default: settings.flashMode = .auto
        }
    }
    return settings
}

Я действительно не могу понять, как точно использовать captureSettings и менять его каждый раз с другим режимом вспышки. Я прошел через пару вопросов, но они в основном касаются фонарей. Я ищу вспышку.

Любая помощь очень ценится.

Ответы [ 2 ]

0 голосов
/ 08 января 2019

AVCapturePhotoSettings объект является уникальным и не может быть повторно использован, поэтому вам нужно каждый раз получать новые настройки, используя этот метод:

func getSettings(camera: AVCaptureDevice, flashMode: CurrentFlashMode) -> AVCapturePhotoSettings {
    let settings = AVCapturePhotoSettings()

    if camera.hasFlash {
        switch flashMode {
           case .auto: settings.flashMode = .auto
           case .on: settings.flashMode = .on
           default: settings.flashMode = .off
        }
    }
    return settings
}

Как видите, lockConfiguration не нужен.

CurrentFlashMode - это enum, который был создан для ясности:

enum CurrentFlashMode { дело выключено дело на чехол авто }

Тогда просто используйте его при съемке фотографии:

 @IBAction func captureButtonPressed(_ sender: UIButton) {
        let currentSettings = getSettings(camera: currentCamera, flashMode: currentFlashMode)
        photoOutput.capturePhoto(with: currentSettings, delegate: self)
    }
0 голосов
/ 08 января 2019

цитата из AVCapturePhotoSettings документа, см. Последнюю важную часть:

Краткое описание

Спецификация функций и настроек, используемых для одного запроса захвата фотографий.

Декларация

класс AVCapturePhotoSettings: NSObject Обсуждение

Чтобы сделать фотографию, вы создаете и настраиваете объект AVCapturePhotoSettings, а затем передаете его в метод AVCapturePhotoOutput capturePhoto (с помощью метода: Delegate :). Экземпляр AVCapturePhotoSettings может содержать любую комбинацию параметров независимо от того, является ли эта комбинация действительной для данного сеанса захвата. Когда вы инициируете захват, передавая объект настроек фотографии в метод AVCapturePhotoOutputcapturePhoto (с помощью метода: Delegate :), выходные данные захвата фотографий проверяют ваши настройки, чтобы обеспечить детерминированное поведение. Например, параметр flashMode должен указывать значение, присутствующее в массиве outputFlashModes для вывода фотографий. Подробные правила проверки см. В описании каждого свойства ниже.

Важно

Недопустимо повторно использовать экземпляр AVCapturePhotoSettings для нескольких захватов. Вызов метода capturePhoto (with: делегат :) вызывает исключение (invalidArgumentException), если значение uniqueID объекта настроек совпадает со значением любого ранее использованного объекта настроек. To reuse a specific combination of settings, use the init(from:) инициализатор для создания нового уникального экземпляра AVCapturePhotoSettings из существующего объекта настроек фотографий.

та же проблема, что и у вас: проблема с github

...