CMSampleBuffer

时间:2016-11-29 16:34:16

标签: macos h.264 cmsamplebufferref video-toolbox cmsamplebuffer

我正在编写代码来解压缩原生附件-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);

并将其添加到CMSampleBuffer中,如下所示:

CMSampleBufferRef sampleBuffer;

status = CMSampleBufferCreate(kCFAllocatorDefault,
                              blockBuffer,
                              true,
                              NULL,
                              NULL,
                              formatDescription,
                              1,
                              0,
                              NULL,
                              1,
                              &sampleSize,
                              &sampleBuffer);

我应该如何处理块缓冲区? SampleBuffer是否保留了块缓冲区的内存,还是需要做一些事情以确保它不被释放?

另外,关于异步解码过程,是否有一种明智的方法可以知道解码器何时完成CMSampleBuffer所以我可以处理它?<​​/ p>

我的直觉告诉我CMSampleBuffer会保留CMBlockBuffer,而VTDecodeSession会保留CMSampleBuffer,直到它完成解码,但这是一个未记录的领域,我正在徘徊,所以寻找一些方向。结果我暗示我的直觉可能是错的,所以我需要排除内存管理作为一个问题来保持我的理智......

1 个答案:

答案 0 :(得分:1)

CMSampleBuffers和CMBlockBuffers - 对象本身 - 遵循典型的CF Retain / Release语义。只要您需要这些对象,就应该保留一个保留,并假设接受它们的接口也是这样做的。这意味着您可以在将CMBlockBuffer交给CMSampleBuffer后立即释放它,并且可以在将CMSampleBuffer传递到渲染链后自由发布它。

使用CMBlockBufferCreateWithMemoryBlock()创建的CMBlockBuffer指向的内存遵循略有不同的规则。首先,该方法不复制memoryBlock指向的数据;它直接使用该指针。这意味着BlockBuffer需要了解应该如何管理内存。这由CMBlockBufferCreateWithMemoryBlock()的第四个或第五个参数处理:如果其中一个是非kCFAllocatorNull / NULL,则BlockBuffer将在完成内存时调用其中一个的解除分配器。这通常在BlockBuffer的Finalize()中完成。如果它们都是kCFAllocatorNull / NULL(你的代码片段中都有),BlockBuffer只会在内存完成时将指针放在地板上。

这意味着如果您使用CMBlockBufferCreateWithMemoryBlock()创建CMBlockBuffer并打算在将其传递给渲染管道后释放该BlockBuffer上的retain,则应该为分配器/解除分配器使用非NULL参数,以便可以回收内存后来。当然,这些分配器/解除分配器的实现取决于memoryBlock的来源。