在 captureOutput 上应用过滤器非常滞后并且在特定时间后崩溃

Posted

技术标签:

【中文标题】在 captureOutput 上应用过滤器非常滞后并且在特定时间后崩溃【英文标题】:Applying a filter on captureOutput is very laggy and crashes after a specific time 【发布时间】:2020-04-08 14:04:15 【问题描述】:

我已经成功地在我的相机预览中实现了一个过滤器。这是初始化,在 viewDidLoad() 中:

        sessionQueue.async 
        switch self.setupResult 
        case .success:
            // Only setup observers and start the session if setup succeeded.
            self.addObservers()

            // Buffer
            let videoOutput = AVCaptureVideoDataOutput()
            let dataOutputQueue = DispatchQueue(label: "video data queue",
                                                qos: .userInitiated,
                                                attributes: [],
                                                autoreleaseFrequency: .workItem)

            let x = DispatchQueue.main

            videoOutput.setSampleBufferDelegate(self,
                                                queue: x)

            if self.session.canAddOutput(videoOutput) 
                self.session.addOutput(videoOutput)
                self.session.startRunning()
            

我的捕获输出:

lazy var context = CIContext()

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) 
    let videoPreviewLayerOrientation = viewPreview.videoPreviewLayer.connection?.videoOrientation
    print("capture output called")
    connection.videoOrientation = videoPreviewLayerOrientation!

    let comicEffect = CIFilter(name: "CIComicEffect")
    let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
    let cameraImage = CIImage(cvImageBuffer: pixelBuffer!)

    comicEffect!.setValue(cameraImage, forKey: kCIInputImageKey)

    let cgImage = self.context.createCGImage(comicEffect!.outputImage!, from: cameraImage.extent)!

    DispatchQueue.main.async 
        let filteredImage = UIImage(cgImage: cgImage)
        self.imageView.image = filteredImage
    

现在应用的过滤器有效,但有时非常滞后,我收到此消息,一段时间后,预览结束,我只收到此消息:

2020-04-08 15:59:36.242047+0200 Bumi[28519:6238030] 由于执行过程中出现错误,命令缓冲区的执行被中止。导致 GPU 超时错误(IOAF 代码 2)

感觉每秒钟调用了很多次 captureOutput。

我知道我应该像这样为 videoOutput.setSampleBufferDelegate 实现队列:

DispatchQueue(label: "video data queue",
                                    qos: .userInitiated,
                                    attributes: [],
                                    autoreleaseFrequency: .workItem)

但由于我在我的 sessionQueue 中初始化它,这是不可能的。

我的问题在哪里?

【问题讨论】:

"但是由于我在我的 sessionQueue 中初始化了它,这是不可能的" 为什么?您真的不应该使用主队列来获取 处理帧。此外,在这种情况下使用UIImageView 并不理想——它并不意味着每秒显示这么多不同的图像。尝试渲染成MTKView 嗨弗兰克,我会看看 MTKView 并更改它。对于队列的东西:我制作了一个视频,当我在应用程序上打开相机并相应地实现队列后发生了什么:这是我第一次实现过滤器和东西,所以我不知道从哪里开始。也许视频很有帮助,为什么我不能在我的会话队列中使用队列?链接:youtube.com/… 啊,在主线程之外访问viewPreview.videoPreviewLayer 会导致主线程检查器打印这些警告。解决此问题的简单方法是直接保留对videoPreviewLayer 的引用(而不是通过viewPreview)并改用它。 【参考方案1】:

我强烈建议您查看 Apple 的 AVCamFilter 示例项目。它涵盖了使用MTKView 高效显示已处理帧以及使用高级核心图像或低级金属过滤视频帧。

【讨论】:

以上是关于在 captureOutput 上应用过滤器非常滞后并且在特定时间后崩溃的主要内容,如果未能解决你的问题,请参考以下文章

查看堆栈或绘图

为啥从不调用 captureOutput?

AVCaptureAudioDataOutput 没有调用 AVCaptureAudioDataOutputSampleBufferDelegate.captureOutput

Swift - captureOutput 帧提取的颜色总是接近黑色

三相PWM整流器滞环电流控制仿真

在 CameraView 上应用 Live GpuImage