Владение CMBlockBuffer в CMSampleBuffer

Я пишу код для распаковки собственного потока H.264 приложения B, и я прохожу процесс синтаксического анализа потока, создания CMVideoFormatDescription из NALU SPS/PPS и упаковки других 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, чтобы я мог им распоряжаться?

Моя интуиция подсказывает мне, что CMSampleBuffer будет сохранять CMBlockBuffer, а VTDecodeSession будет сохранять CMSampleBuffer до тех пор, пока не завершит декодирование, но это недокументированная территория, по которой я блуждаю, поэтому ищу какое-то направление. Результаты, которые я получаю, подразумевают, что моя интуиция может быть неправильной, поэтому мне нужно исключить управление памятью как проблему, чтобы сохранить мое здравомыслие...

1 ответ

Решение

CMSampleBuffers и CMBlockBuffers - сами объекты - следуют типичной семантике CF Retain/Release. Вы должны хранить retain, пока вам нужны эти объекты, и предполагать, что интерфейсы, которые их принимают, делают то же самое. Это означает, что вы можете освободить CMBlockBuffer, как только вы передадите его CMSampleBuffer, и вы сможете освободить CMSampleBuffer после того, как передадите его в цепочку рендеринга.

Память, на которую указывает CMBlockBuffer, созданная с помощью CMBlockBufferCreateWithMemoryBlock(), следует немного другим правилам. Во-первых, этот метод не копирует данные, на которые указывает memoryBlock; он использует этот указатель напрямую. Это означает, что BlockBuffer должен знать, как управлять этой памятью. Это обрабатывается либо четвертым, либо пятым аргументами CMBlockBufferCreateWithMemoryBlock(): если они не являются kCFAllocatorNull/NULL, BlockBuffer вызовет освобождение одного из них, когда это будет сделано с памятью. Обычно это делается в Finalize() BlockBuffer. Если они оба kCFAllocatorNull/NULL (которые есть в вашем фрагменте кода), BlockBuffer просто уронит указатель на пол, когда это будет сделано с памятью.

Это означает, что если вы создаете CMBlockBuffer с помощью CMBlockBufferCreateWithMemoryBlock() и намереваетесь освободить свое сохранение для этого BlockBuffer после передачи его по конвейеру рендеринга, вы должны использовать не-NULL аргументы для распределителя / освобождающих средств, чтобы память могла быть освобождена позже. Реализация этих распределителей / разветвителей, конечно, зависит от источника блока памяти.

Другие вопросы по тегам