Как использовать AVFoundation для захвата видеоданных в macOS? - PullRequest
0 голосов
/ 02 января 2019

Я написал код ниже, основываясь на нескольких примерах, которые я нашел в Интернете, чтобы захватывать видеоданные со встроенной камеры в macOS.При установке AVCaptureSession не возникает никаких фатальных ошибок, но делегат не вызывается, и некоторые явные ошибки регистрируются, как только я вызываю captureSession.startRunning().

. Пока я пытался сделатьнебольшие изменения в моем коде (например, удаление videoSettings на выходе или sessionPreset из сеанса), а также проверка в системных настройках того, что мое тестовое приложение имеет разрешение на доступ к камере.Однако журналы остаются, и делегат не вызывается.

Класс CameraInput (включает делегата):

final class CameraInput: NSObject {
    private lazy var sampleBufferDelegateQueue = DispatchQueue(label: "CameraInput")
    private lazy var captureSession: AVCaptureSession = {
        let session = AVCaptureSession()
        session.sessionPreset = .hd1280x720

        let device = AVCaptureDevice.default(for: .video)!
        let input = try! AVCaptureDeviceInput(device: device)
        session.addInput(input)

        let output = AVCaptureVideoDataOutput()
        output.videoSettings = [
            kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA,
            kCVPixelBufferMetalCompatibilityKey as String: true
        ]
        output.alwaysDiscardsLateVideoFrames = true
        output.setSampleBufferDelegate(self, queue: self.sampleBufferDelegateQueue)
        session.addOutput(output)

        return session
    }()
}

extension CameraInput: CVInput {
    func start() {
        guard !self.captureSession.isRunning else {
            return
        }

        self.captureSession.startRunning()
    }

    func stop() {
        guard self.captureSession.isRunning else {
            return
        }

        self.captureSession.stopRunning()
    }
}

extension CameraInput: AVCaptureVideoDataOutputSampleBufferDelegate {
    private func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        // Handle captured frame
    }
}

ViewController (видовой контроллер по умолчанию в новом приложении какао):

class ViewController: NSViewController {
    lazy var cameraInput = CameraInput()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.cameraInput.start()
    }
}

Зарегистрированная информация:

2019-01-02 16:27:15.821858+0100 TestApp[14182:1492243] [] CMIO_Unit_ScopeElement.h:200:SafeGetElement Throwing err: -67454
2019-01-02 16:27:15.823248+0100 TestApp[14182:1492243] [] CMIOUnitFigBaseObjectImpl.c:246:CMIOUnitCreateFromDescription Invalid paramater
2019-01-02 16:27:15.840190+0100 TestApp[14182:1492243] [] CMIO_Unit_Input_Device.cpp:244:GetPropertyInfo CMIOUInputFromProcs::GetPropertyInfo() failed for id 102, Error: -67456

Любая помощь в получении этого с благодарностью!Также, пожалуйста, сообщите мне, если требуется дополнительная информация.

РЕДАКТИРОВАТЬ После ответа на на этот вопрос я исключил, что это проблема в песочнице.

Ответы [ 3 ]

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

Вам необходимо удалить ключевое слово private из вашего метода did captureOutput:didOutput.

Я полагаю, это достаточно изменяет сигнатуру, чтобы ваш метод не вызывался.

0 голосов
/ 26 апреля 2019

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

Мой код был таким, когда он не работал.

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!)

Это то, что было раньше.Я использовал автозаполнение XCode, чтобы получить текущую версию этого.

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection)

Итак, мораль этой истории ... Conversion to Swift <insert version> is Available не всегда работает идеально.

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

Ваш код, кажется, в порядке.Попробуйте

  • создать новый проект "CocoaApp / Swift" в Xcode
  • и вставить оба ваших фрагмента кода в AppDelegate
  • добавить AVCaptureVideoDataOutputSampleBufferDelegate в приложениеобъявление делегата
  • добавление self.captureSession.startRunning() к функции applicationDidFinishLaunching AppDelegate
  • , позволяющей использовать камеру в настройках песочницы
  • , добавление NSCameraUsageDescription в Info.plist(macOS 10.14 и более поздние версии)

Я только что проверил это, функция делегата вызывается повторно.Я вижу упомянутый вывод журнала в macOS 10.14 / XCode 10 (он не отображается в macOS 10.13 / Xcode 9), но он не препятствует захвату.

Так что проблема не в коде, приведенном ввопрос.Убедитесь, что все объекты действительно созданы так, как задумано, что установка сеанса захвата выполняется и что никакие объекты, особенно выходной делегат, не освобождаются преждевременно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...