【问题标题】:AVCaptureVideoDataOutput captureOutput not being calledAVCaptureVideoDataOutput captureOutput 未被调用
【发布时间】:2016-10-19 20:04:02
【问题描述】:

我正在使用 AVCaptureScreenInput 在 Mac 上进行屏幕捕获,但从未调用过 AVCaptureVideoDataOutput 委托 captureOutput,我不知道为什么。我确实收到了一条通知,说捕获会话已开始。

import Cocoa
import AVFoundation

class ViewController: NSViewController, AVCaptureVideoDataOutputSampleBufferDelegate {

    var captureSession: AVCaptureSession!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    override func viewWillAppear() {
        super.viewWillAppear()
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.errorNotif), name: AVCaptureSessionRuntimeErrorNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.startedNotif), name: AVCaptureSessionDidStartRunningNotification, object: nil)
        startScreenCapture()
    }

    override func viewWillDisappear() {
        super.viewWillDisappear()
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

    func captureOutput(captureOutput: AVCaptureOutput!, didDropSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
        print("ignore frame, add code to handle later")
    }

    func startScreenCapture() {

        let displayId = CGMainDisplayID()
        captureSession = AVCaptureSession()
        if captureSession.canSetSessionPreset(AVCaptureSessionPresetHigh) {
            captureSession.sessionPreset = AVCaptureSessionPresetHigh
        }
        let captureScreenInput = AVCaptureScreenInput(displayID: displayId)
        if captureSession.canAddInput(captureScreenInput) {
            captureSession.addInput(captureScreenInput)
        } else {
            print("Could not add main display to capture input")
        }

        let output = AVCaptureVideoDataOutput()

        let queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL)
        output.setSampleBufferDelegate(self, queue: queue)
        output.alwaysDiscardsLateVideoFrames = true

        output.videoSettings = [kCVPixelBufferPixelFormatTypeKey as NSString: NSNumber(unsignedInt: kCVPixelFormatType_32BGRA)]
        captureSession.addOutput(output)
        captureSession.startRunning()
    }

    func errorNotif() {
        print("error starting capture")
    }
    func startedNotif() {
        print("started screen capture")
    }
}

【问题讨论】:

    标签: swift macos cocoa avfoundation


    【解决方案1】:

    您需要定义didOutputSampleBuffer 委托回调来实际接收捕获的帧:

    func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
        print("captured \(sampleBuffer)")
    }
    

    附言我不确定 macOS,但 viewWillAppear 可能不是进行初始化的好地方,因为在 iOS 上至少可以多次调用它。

    【讨论】:

    • 非常感谢!我从自动完成中选择了错误的 captureOutput。同意,viewWillAppear 不是一个调用 start 的好地方。我的真实应用会根据用户交互调用它
    • 我有一个类似的问题,但我没有在我的应用程序中使用 ViewController,因为我使用的是 GTK。我在其中定义了public class Vision : NSObject, AVCaptureVideoDataOutputSampleBufferDelegatecaptureOutput。在其构造函数中,我将setSampleBufferDelegate 设置为(self , queue: queue)。我的代码编译、运行并显示 GUI。但是,虽然内置摄像头确实打开了,但它会暂时保持打开状态,然后关闭,但永远不会调用 captureOutput
    • 您能否提出一个新问题并说明您是如何设置捕获会话的?
    • @gone 你找到解决问题的方法了吗?我有同样的问题
    • @ManishKumar:我当时放弃了我的努力。由于您的评论,我回到了它,并且在获得隐私权限后,发现正在调用captureOutput,但我在短时间内收到错误消息。我已将代码放入 pastebin:pastebin.com/0Ew9as5x,但如果您无法联系到,并且有一些方法可以直接与我联系,我可以与您分享。
    【解决方案2】:

    我添加了基本示例AVCaptureVideoDataOutputSampleBufferDelegate

    class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {    
    
    
        let videoQueue = DispatchQueue(label: "VIDEO_QUEUE")
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let captureSession = AVCaptureSession()
    
            guard let captureDevice = AVCaptureDevice.default(for: .video) else { return }
    
            guard let input = try? AVCaptureDeviceInput(device: captureDevice) else { return }
    
            captureSession.addInput(input)
    
            captureSession.startRunning()
    
            let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
            view.layer.addSublayer(previewLayer)
            previewLayer.frame = view.frame
    
            let dataOutput = AVCaptureVideoDataOutput()
            dataOutput.setSampleBufferDelegate(self, queue: videoQueue)
            captureSession.addOutput(dataOutput)
        }
    
        func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
            print("Camera was able to capture a frame:", Date())
        }
    }
    

    【讨论】:

    • 拯救了我的一天!谢谢。
    • 一切顺利! @Codetard
    猜你喜欢
    • 2018-12-10
    • 2017-12-13
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多