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