I have successfully implemented a filter on my camera preview. Here is the initialization, in 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()
}
My captureOutput:
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
}
}
Right now the applied filter works, but it is VERY laggy sometimes and I receive this messages, and after a time, the preview ends and I only receive this messages:
2020-04-08 15:59:36.242047+0200 Bumi[28519:6238030] Execution of the command buffer was aborted due to an error during execution. Caused GPU Timeout Error (IOAF code 2)
It feels like captureOutput is called A lot of times per second.
I know that I should implement the queue for videoOutput.setSampleBufferDelegate like this:
DispatchQueue(label: "video data queue",
qos: .userInitiated,
attributes: [],
autoreleaseFrequency: .workItem)
But since I initialize it in my sessionQueue, this is not possible.
Where is my problem here?