我正在尝试创建一个由 AVCaptureVideoDataOutputSampleBufferDelegate 中的 captureOutput 返回的 CMSampleBuffer 的副本。
由于 CMSampleBuffers 来自 (15) 个缓冲区的预分配池,因此如果我附加对它们的引用,它们将无法被重新收集。这会导致所有剩余的帧都被丢弃。
为了保持最佳性能,一些样本缓冲区直接引用可能需要由设备系统和其他捕获输入重用的内存池。对于未压缩的设备本机捕获来说,这种情况经常发生,其中内存块被复制得越少越好。如果多个样本缓冲区引用此类内存池的时间过长,则输入将不再能够将新样本复制到内存中,并且这些样本将被丢弃。
如果您的应用程序由于保留提供的 CMSampleBufferRef 对象太久而导致样本被丢弃,但它需要长时间访问样本数据,请考虑将数据复制到新缓冲区,然后释放样本缓冲区(如果它以前被保留)以便它引用的内存可以被重用。
显然我必须复制 CMSampleBuffer 但 CMSampleBufferCreateCopy() 只会创建一个浅拷贝。因此我得出结论,我必须使用 CMSampleBufferCreate()。我填了12!构造函数需要的参数,但遇到了我的 CMSampleBuffers 不包含 blockBuffer 的问题(不完全确定那是什么,但它似乎很重要)。
这个问题被问了好几次,但没有回答。
CMImageBuffer 或 CVImageBuffer 的深层复制并在 Swift 2.0 中创建 CMSampleBuffer 的副本
一个可能的答案是“我终于想出了如何使用它来创建深度克隆。所有的复制方法都重用了堆中的数据,这些数据会锁定 AVCaptureSession。所以我必须将数据提取到 NSMutableData 对象中,然后创建了一个新的样本缓冲区。” 归功于 Rob 在 SO 上。但是,我不知道如何正确地做到这一点。
如果您有兴趣,这是 的输出print(sampleBuffer)
。没有提到 blockBuffer,也就是 CMSampleBufferGetDataBuffer 返回 nil。有一个 imageBuffer,但是使用 CMSampleBufferCreateForImageBuffer 创建一个“副本”似乎也没有释放 CMSampleBuffer。
编辑:自从发布了这个问题以来,我一直在尝试更多复制内存的方法。
我做了用户Kametrixom尝试过的同样的事情。这是我对同一想法的尝试,首先复制 CVPixelBuffer 然后使用 CMSampleBufferCreateForImageBuffer 创建最终的样本缓冲区。但是,这会导致以下两个错误之一:
- memcpy 指令上的 EXC_BAD_ACCESS。AKA 尝试访问应用程序内存之外的段错误。
- 或者,内存将成功复制,但
CMSampleBufferCreateReadyWithImageBuffer()
将失败,结果代码为 -12743,“指示给定媒体的格式与给定格式描述不匹配。例如,格式描述与 CVImageBuffer 配对失败 CMVideoFormatDescriptionMatchesImageBuffer。”
您可以看到我和 Kametrixom 都曾CMSampleBufferGetFormatDescription(sampleBuffer)
尝试复制源缓冲区的格式描述。因此,我不确定为什么给定媒体的格式与给定的格式描述不匹配。