Jim*_* B. 1 macos h.264 cmsamplebufferref cmsamplebuffer video-toolbox
我正在编写代码来解压本机附件 B H.264 流,我正在完成解析流的过程,从 SPS/PPS NALU 创建 CMVideoFormatDescription,并包装我从流中提取的其他 NALU在 CMSampleBuffers 中。
我在如何处理解码器的 CMBlockBuffer 和 CMSampleBuffer 内存方面遇到了心理障碍。我相信我的问题更多是缺乏对 CF 如何处理内存的透彻理解,所以我的问题更多的是关于这一点,但我希望上下文有帮助。
如果我像这样创建一个 CMBlockBuffer:
CMBlockBufferRef blockBuffer;
OSStatus status = CMBlockBufferCreateWithMemoryBlock(NULL,
memoryBlock,
blockBufferLength,
kCFAllocatorNull,
NULL,
0,
blockBufferLength,
kCMBlockBufferAlwaysCopyDataFlag | kCMBlockBufferAssureMemoryNowFlag,
&blockBuffer);
Run Code Online (Sandbox Code Playgroud)
并将其添加到 CMSampleBuffer 中,如下所示:
CMSampleBufferRef sampleBuffer;
status = CMSampleBufferCreate(kCFAllocatorDefault,
blockBuffer,
true,
NULL,
NULL,
formatDescription,
1,
0,
NULL,
1,
&sampleSize,
&sampleBuffer);
Run Code Online (Sandbox Code Playgroud)
我应该如何处理块缓冲区?SampleBuffer 是否保留块缓冲区的内存,或者我是否需要做一些事情来确保它没有被释放?
另外,关于异步解码过程,是否有一种明智的方法可以知道解码器何时使用 CMSampleBuffer 完成以便我可以处理它?
我的直觉告诉我 CMSampleBuffer 会保留 CMBlockBuffer,而 VTDecodeSession 会保留 CMSampleBuffer 直到它完成解码,但这是一个未记录的领域,我正在寻找一些方向。我得到的结果暗示我的直觉可能是错误的,所以我需要排除内存管理作为一个问题来保持我的理智......
CMSampleBuffers 和 CMBlockBuffers——对象本身——遵循典型的 CF Retain/Release 语义。只要您需要这些对象,您就应该持有保留,并假设接受它们的接口也这样做。这意味着您可以在将 CMBlockBuffer 交给 CMSampleBuffer 后立即释放它,并且在将其传递到渲染链后可以自由释放 CMSampleBuffer。
使用 CMBlockBufferCreateWithMemoryBlock() 创建的 CMBlockBuffer 指向的内存遵循稍微不同的规则。首先,该方法不会复制 memoryBlock 指向的数据;它直接使用该指针。这意味着 BlockBuffer 需要了解应该如何管理内存。这由 CMBlockBufferCreateWithMemoryBlock() 的第四个或第五个参数处理:如果其中任何一个是非 kCFAllocatorNull/NULL,BlockBuffer 将在完成内存后调用其中一个的解除分配器。这通常在 BlockBuffer 的 Finalize() 中完成。如果它们都是 kCFAllocatorNull/NULL(在您的代码片段中),则 BlockBuffer 将在内存完成后将指针放在地板上。
这意味着,如果您使用 CMBlockBufferCreateWithMemoryBlock() 创建 CMBlockBuffer 并打算在将其传递到渲染管道后释放该 BlockBuffer 上的保留,则应为分配器/释放器使用非 NULL 参数,以便稍后可以回收内存。当然,这些分配器/释放器的实现取决于 memoryBlock 的来源。