Ios AVFoundation captureOutput didOutputSampleBuffer延迟
我正在使用AVFoundation captureOutput didOutputSampleBuffer来提取图像,然后用于过滤器Ios AVFoundation captureOutput didOutputSampleBuffer延迟,ios,swift,avfoundation,cmsamplebuffer,avcaptureoutput,Ios,Swift,Avfoundation,Cmsamplebuffer,Avcaptureoutput,我正在使用AVFoundation captureOutput didOutputSampleBuffer来提取图像,然后用于过滤器 self.bufferFrameQueue = DispatchQueue(label: "bufferFrame queue", qos: DispatchQoS.background, attributes: [], autoreleaseFrequency: .inherit) self.videoDataOutput = AVCaptureVi
self.bufferFrameQueue = DispatchQueue(label: "bufferFrame queue", qos: DispatchQoS.background, attributes: [], autoreleaseFrequency: .inherit)
self.videoDataOutput = AVCaptureVideoDataOutput()
if self.session.canAddOutput(self.videoDataOutput) {
self.session.addOutput(videoDataOutput)
self.videoDataOutput!.alwaysDiscardsLateVideoFrames = true
self.videoDataOutput!.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32BGRA)]
self.videoDataOutput!.setSampleBufferDelegate(self, queue: self.bufferFrameQueue)
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
connection.videoOrientation = .portrait
let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
DispatchQueue.main.async {
self.cameraBufferImage = ciImage
}
}
只要有新的输出样本缓冲区,上面只更新self.cameraBufferImage
然后,当按下过滤器按钮时,我使用self.cameraBufferImage如下:
func filterButtonPressed() {
if var inputImage = self.cameraBufferImage {
if let currentFilter = CIFilter(name: "CISepiaTone") {
currentFilter.setValue(inputImage, forKey: "inputImage")
currentFilter.setValue(1, forKey: "inputIntensity")
if let output = currentFilter.outputImage {
if let cgimg = self.context.createCGImage(output, from: inputImage.extent) {
self.filterImageLayer = CALayer()
self.filterImageLayer!.frame = self.imagePreviewView.bounds
self.filterImageLayer!.contents = cgimg
self.filterImageLayer!.contentsGravity = kCAGravityResizeAspectFill
self.imagePreviewView.layer.addSublayer(self.filterImageLayer!)
}
}
}
}
}
调用上述方法时,它将获取“当前”self.cameraBufferImage,并使用它应用过滤器。这在正常曝光持续时间内(低于1/15秒左右)效果良好
问题
当曝光持续时间较慢时,即1/3秒,需要一段时间(约1/3秒)来应用过滤器。此延迟仅在发射后第一次出现。如果再这样做,就不会有任何延误
思想 我知道如果曝光持续时间为1/3秒,didOutputSampleBuffer只会每1/3秒更新一次。然而,为什么会出现最初的延迟?它不应该只抓取在那个确切时间可用的self.cameraBufferImage,而不是等待吗
更新 每当输出捕获并显示时,学员都会收到此消息 输出一个新的视频帧,按照 它的videoSettings属性。学员可以使用提供的视频帧 结合其他API进行进一步处理 此方法在输出的 sampleBufferCallbackQueue属性。它被周期性地调用,因此 必须能够有效防止捕获性能问题,包括 掉帧 如果需要在外部引用CMSampleBuffer对象 此方法的作用域,您必须保留它,然后在 你完成了 为了保持最佳性能,一些示例缓冲区直接 设备可能需要重用的内存引用池 系统和其他捕获输入。这种情况经常发生在 未压缩的设备本机捕获,其中内存块被复制为 尽量少。如果多个样本缓冲区引用了这些样本池 内存太长,输入将无法再复制新样本 这些样本将被丢弃到内存中 如果您的应用程序通过保留 提供的CMSampleBuffer对象太长,但需要访问 样本数据在很长一段时间内,考虑复制数据 放入新的缓冲区,然后释放样本缓冲区(如果是 以前保留),以便可以重用它引用的内存
嗨,你有什么解决办法吗?当我前后或前后更改设备类型时,一些帧会掉落并冻结3-4秒,这很容易察觉。