我使用AVCaptureDataOutputSynchronizerDelegate处理视频、深度和元数据的捕获数据。
private let videoDataOutput = AVCaptureVideoDataOutput()
private let depthDataOutput = AVCaptureDepthDataOutput()
private let metadataOutput = AVCaptureMetadataOutput()因此,使用下面的代码,我能够在从AVCaptureDataOutputSynchronizerDelegate中使用的委托方法中获得具体的视频数据。
func dataOutputSynchronizer(_ synchronizer: AVCaptureDataOutputSynchronizer, didOutput synchronizedDataCollection: AVCaptureSynchronizedDataCollection) {
guard let syncedVideoData = synchronizedDataCollection.synchronizedData(for: self.videoDataOutput) as? AVCaptureSynchronizedSampleBufferData else { return }问题是,当我试图按下面的方式将videoData保存到一个数组中时,我会得到一个OutOfBuffers错误。如果我试图保存与此数据相关的视频数据/图像/任何与此数据相关的内容,则此问题仍然存在。
let array:[CMSampleBuffer] = []
...
array.append(syncedVideoData)
//Gets to about 5-6 sets of data, then it runs out of buffers.
//I think the buffer is being retained permanently since I am saving to a global variable here.
//Leading to out of buffer error所以,我想发生的是,因为我将任何相关数据保存到数组中,所以它将数据保存在内存中,而通常是释放的.。
OutOfBuffers早期链接的网页表示我可以
如果需要对捕获的数据执行扩展处理,请将该数据复制到缓冲区中,缓冲区的生存期由您管理,而不是依赖捕获输出提供的缓冲区。
我试图创建一个新的CMSampleBuffer
extension VideoCapture: AVCaptureDataOutputSynchronizerDelegate {
func dataOutputSynchronizer(_ synchronizer: AVCaptureDataOutputSynchronizer, didOutput synchronizedDataCollection: AVCaptureSynchronizedDataCollection) {
var newData:CMSampleBuffer?
guard let syncedVideoData = synchronizedDataCollection.synchronizedData(for: self.videoDataOutput) as? AVCaptureSynchronizedSampleBufferData else { return }
guard !syncedVideoData.sampleBufferWasDropped else {
print(syncedVideoData.droppedReason.rawValue)
return
}
let videoSampleBuffer = syncedVideoData.sampleBuffer
CMSampleBufferCreateCopy(allocator: kCFAllocatorDefault, sampleBuffer: videoSampleBuffer, sampleBufferOut: &newData)
if(newData != nil) {
self.buffer.append(newData!)
}
}但是这也导致了同样的问题-- videoData仍然停留在缓冲区中。我得到了大约5-6套videoData,然后我没有得到更多的数据.
关于如何“将数据复制到您管理的生存期而不是依赖捕获输出所支持的缓冲区的缓冲区”的任何指导。如outOfBuffers网站所示
发布于 2019-07-30 02:18:45
我能够在这个缓冲器和本指南以及其他几个苹果文档中创建一个缓冲区。
...
guard let imagePixelBuffer = CMSampleBufferGetImageBuffer(videoSampleBuffer) else { fatalError() }
//First lock buffer
CVPixelBufferLockBaseAddress(imagePixelBuffer,
CVPixelBufferLockFlags.readOnly)
//Do something with buffer
self.buffer = createMyBuffer(pixelBuffer: imagePixelBuffer)
//Unlock buffer
CVPixelBufferUnlockBaseAddress(imagePixelBuffer,
CVPixelBufferLockFlags.readOnly)
self.doSomething(self.buffer)
...
func createMyBuffer(pixelBuffer: CVPixelBuffer) -> CVPixelBuffer? {
let scaleWidth:Int = CVPixelBufferGetWidth(pixelBuffer)
let scaleHeight:Int = CVPixelBufferGetHeight(pixelBuffer)
let flags = CVPixelBufferLockFlags(rawValue: 0)
guard kCVReturnSuccess == CVPixelBufferLockBaseAddress(pixelBuffer, flags) else {
return nil
}
defer { CVPixelBufferUnlockBaseAddress(pixelBuffer, flags) }
guard let srcData = CVPixelBufferGetBaseAddress(pixelBuffer) else {
print("Error: could not get pixel buffer base address")
return nil
}
let srcBytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
var srcBuffer = vImage_Buffer(data: srcData,
height: vImagePixelCount(CVPixelBufferGetHeight(pixelBuffer)),
width: vImagePixelCount(CVPixelBufferGetWidth(pixelBuffer)),
rowBytes: srcBytesPerRow)
let destBytesPerRow = scaleWidth*4
guard let destData = malloc(scaleHeight*destBytesPerRow) else {
print("Error: out of memory")
return nil
}
var destBuffer = vImage_Buffer(data: destData,
height: vImagePixelCount(scaleHeight),
width: vImagePixelCount(scaleWidth),
rowBytes: destBytesPerRow)
let error = vImageScale_ARGB8888(&srcBuffer, &destBuffer, nil, vImage_Flags(kvImageLeaveAlphaUnchanged))
if error != kvImageNoError {
print("Error:", error)
free(destData)
return nil
}
let releaseCallback: CVPixelBufferReleaseBytesCallback = { _, ptr in
if let ptr = ptr {
free(UnsafeMutableRawPointer(mutating: ptr))
}
}
let pixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer)
var dstPixelBuffer: CVPixelBuffer?
let status = CVPixelBufferCreateWithBytes(nil, scaleWidth, scaleHeight,
pixelFormat, destData,
destBytesPerRow, releaseCallback,
nil, nil, &dstPixelBuffer)
if status != kCVReturnSuccess {
print("Error: could not create new pixel buffer")
free(destData)
return nil
}
return dstPixelBuffer
}这是可行的,但似乎是多余的。我正在使用一个函数,我发现它“缩放”了缓冲区,但是我只是将它缩放到与当前缓冲区完全相同的大小,然后它返回一个新的缓冲区,当我选择删除它时,它会返回一个新缓冲区。它是重复的,但功能有效。
https://stackoverflow.com/questions/57134958
复制相似问题