gpt4 book ai didi

ios - 从 CMSampleBuffer 中提取数据以创建深拷贝

转载 作者:IT王子 更新时间:2023-10-29 05:19:21 29 4
gpt4 key购买 nike

我正在尝试创建 CMSampleBuffer 的副本,由 AVCaptureVideoDataOutputSampleBufferDelegate 中的 captureOutput 返回。

由于 CMSampleBuffers 来自预先分配的 (15) 个缓冲区池,如果我附加对它们的引用,它们将无法重新收集。这会导致所有剩余的帧被丢弃。

To maintain optimal performance, some sample buffers directly reference pools of memory that may need to be reused by the device system and other capture inputs. This is frequently the case for uncompressed device native capture where memory blocks are copied as little as possible. If multiple sample buffers reference such pools of memory for too long, inputs will no longer be able to copy new samples into memory and those samples will be dropped.

If your application is causing samples to be dropped by retaining the provided CMSampleBufferRef objects for too long, but it needs access to the sample data for a long period of time, consider copying the data into a new buffer and then releasing the sample buffer (if it was previously retained) so that the memory it references can be reused.

显然,我必须复制 CMSampleBuffer,但 CMSampleBufferCreateCopy() 只会创建一个浅拷贝。因此我得出结论,我必须使用 CMSampleBufferCreate()。我填的是12!构造函数需要的参数,但遇到了我的 CMSampleBuffers 不包含 blockBuffer 的问题(不完全确定那是什么,但它似乎很重要)。

这个问题已经被问过好几次了,但没有得到回答。

Deep Copy of CMImageBuffer or CVImageBufferCreate a copy of CMSampleBuffer in Swift 2.0

一个可能的答案是“我终于想出了如何使用它来创建深度克隆。所有复制方法都重复使用堆中的数据,这些数据会锁定 AVCaptureSession。所以我不得不将数据拉出到 NSMutableData 中对象,然后创建一个新的样本缓冲区。” credit to Rob on SO .但是,我不知道如何正确地执行此操作。

如有兴趣,thisprint(sampleBuffer) 的输出。没有提到 blockBuffer,又名 CMSampleBufferGetDataBuffer 返回 nil。有一个 imageBuffer,但使用 CMSampleBufferCreateForImageBuffer 创建“副本”似乎也不会释放 CMSampleBuffer。


编辑:自从发布这个问题后,我一直在尝试更多复制内存的方法。

我对用户 Kametrixom 做了同样的事情尝试过。 This是我对相同想法的尝试,首先复制 CVPixelBuffer 然后使用 CMSampleBufferCreateForImageBuffer 创建最终的样本缓冲区。然而,这会导致以下两个错误之一:

  • memcpy 指令上的 EXC_BAD_ACCESS。也就是尝试访问应用程序内存之外的段错误。
  • 或者,内存将成功复制,但 CMSampleBufferCreateReadyWithImageBuffer() 将失败,结果代码为 -12743,“表示给定媒体的格式与给定的格式描述不匹配。例如,与 CVImageBuffer 配对的格式描述失败了 CMVideoFormatDescriptionMatchesImageBuffer。”

您可以看到 Kametrixom 和我确实使用了 CMSampleBufferGetFormatDescription(sampleBuffer) 来尝试复制源缓冲区的格式描述。因此,我不确定为什么给定媒体的格式与给定的格式描述不匹配。

最佳答案

好吧,我想我终于明白了。我创建了一个辅助扩展来制作 CVPixelBuffer 的完整副本:

extension CVPixelBuffer {
func copy() -> CVPixelBuffer {
precondition(CFGetTypeID(self) == CVPixelBufferGetTypeID(), "copy() cannot be called on a non-CVPixelBuffer")

var _copy : CVPixelBuffer?
CVPixelBufferCreate(
nil,
CVPixelBufferGetWidth(self),
CVPixelBufferGetHeight(self),
CVPixelBufferGetPixelFormatType(self),
CVBufferGetAttachments(self, kCVAttachmentMode_ShouldPropagate)?.takeUnretainedValue(),
&_copy)

guard let copy = _copy else { fatalError() }

CVPixelBufferLockBaseAddress(self, kCVPixelBufferLock_ReadOnly)
CVPixelBufferLockBaseAddress(copy, 0)

for plane in 0..<CVPixelBufferGetPlaneCount(self) {
let dest = CVPixelBufferGetBaseAddressOfPlane(copy, plane)
let source = CVPixelBufferGetBaseAddressOfPlane(self, plane)
let height = CVPixelBufferGetHeightOfPlane(self, plane)
let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(self, plane)

memcpy(dest, source, height * bytesPerRow)
}

CVPixelBufferUnlockBaseAddress(copy, 0)
CVPixelBufferUnlockBaseAddress(self, kCVPixelBufferLock_ReadOnly)

return copy
}
}

现在您可以在 didOutputSampleBuffer 方法中使用它:

guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }

let copy = pixelBuffer.copy()

toProcess.append(copy)

但请注意,一个这样的 pixelBuffer 占用大约 3MB 的内存 (1080p),这意味着在 100 帧中您已经获得了大约 300MB,这大约是 iPhone 显示 STAHP(并崩溃)的时间点。

请注意,您实际上并不想复制 CMSampleBuffer,因为它实际上只包含一个 CVPixelBuffer,因为它是一个图像。

关于ios - 从 CMSampleBuffer 中提取数据以创建深拷贝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38335365/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com