【问题标题】:How to use the AVFoundation to capture video data in macOS?如何使用 AVFoundation 在 macOS 中捕获视频数据?
【发布时间】:2019-01-02 15:41:08
【问题描述】:

我根据我在网上找到的几个示例编写了以下代码,以便从 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

非常感谢任何帮助使其正常工作!另外,如果需要更多信息,请通知我。

编辑 遇到this question后,我已经排除是沙盒的问题了。

【问题讨论】:

  • 您是否在任何地方的捕获会话中致电startRunning()
  • @NoHalfBits 是的,我愿意。它不包含在此代码中,但我有一个函数start(),在创建会话后我在其中调用startRunning()。这就是导致消息显示的原因。
  • 如果您在 Target > Capabilities > App Sandbox 中启用相机,您的代码就可以工作
  • @RhythmicFistman 我确实将它添加到沙盒中,但无济于事
  • 奇怪,这是我的代码的工作版本:github.com/rfistman/video-capture-macos

标签: swift macos avfoundation


【解决方案1】:

您需要从您的 did captureOutput:didOutput 方法中删除关键字 private

我猜它改变了签名足以让你的方法不被调用。

【讨论】:

  • 这就是问题所在!但是,如果没有private,Xcode 建议将其设为私有,这就是我首先这样做的原因。明确地设置public 可以解决警告并使其正常工作
  • 我没有那样做。您的项目发生了一些事情,这肯定比我的玩具示例更复杂。
  • 好吧,至少问题解决了。感谢您指出这一点!
【解决方案2】:

您的代码似乎没问题。尝试

  • 在 Xcode 中创建一个新的“CocoaApp/Swift”项目
  • 将两个代码 sn-ps 粘贴到 AppDelegate 中
  • 在应用委托声明中添加AVCaptureVideoDataOutputSampleBufferDelegate
  • self.captureSession.startRunning()添加到AppDelegate的applicationDidFinishLaunching函数中
  • 在沙盒设置中启用摄像头使用
  • NSCameraUsageDescription 添加到 Info.plist(macOS 10.14 及更高版本)

我刚刚测试过,委托函数重复调用。 我在 macOS 10.14 / XCode 10 上看到了提到的日志输出(它没有出现在 macOS 10.13 / Xcode 9 上),但它不会阻止捕获。

所以问题不在问题中给出的代码中。确保所有对象都按预期实际创建,捕获会话设置运行,并且没有对象(尤其是输出委托)被过早释放。

【讨论】:

  • 这有效(使用@RhythmicFistman 的代码),这让我想知道为什么当我将代码放在单独的类中时它会停止工作。我已经在CameraInputdeinit 中放了一个打印,但它没有被调用。
  • 奇怪 - 你把你懒惰的 cameraInput 设为 nil 吗?
【解决方案3】:

我遇到了这个确切的错误。标记的答案帮助我开始了正确的道路,但我觉得我的问题足够不同,值得另一个答案

我的代码在它不工作时是这样的。

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 并不总是完美无缺。

【讨论】:

  • 如果雷达值得我徘徊。
猜你喜欢
  • 2017-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-03
  • 2010-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多