在 captureOutput 上应用过滤器非常滞后,并在特定时间后崩溃
Applying a filter on captureOutput is very laggy and crashes after a specific time
我已经成功地在我的相机预览中实现了一个滤镜。这里是初始化,在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 中初始化它,所以这是不可能的。
我的问题在哪里?
我强烈建议您查看 Apple 的 AVCamFilter
示例项目。它涵盖了使用 MTKView
有效显示处理过的帧以及使用高级 Core Image 或低级 Metal 过滤视频帧。
我已经成功地在我的相机预览中实现了一个滤镜。这里是初始化,在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 中初始化它,所以这是不可能的。
我的问题在哪里?
我强烈建议您查看 Apple 的 AVCamFilter
示例项目。它涵盖了使用 MTKView
有效显示处理过的帧以及使用高级 Core Image 或低级 Metal 过滤视频帧。