2016-11-29 125 views
0

我正在編寫解壓本地annex-B H.264數據流的代碼,並且我正在通過解析流,從SPS/PPS NALU創建CMVideoFormatDescription幷包裝其他NALUs我從CMSampleBuffers中的流中提取。CMSampleBuffer中的CMBlockBuffer所有權

我忍受着如何處理解碼器的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保留/釋放語義。只要你需要這些對象,你就應該保留一個保留,並且假定接受它們的接口是一樣的。這意味着只要將它傳遞給CMSampleBuffer,您就可以自由地釋放CMBlockBuffer,並且可以在將它傳遞到渲染鏈後自由釋放CMSampleBuffer。

由CMBlockBufferCreateWithMemoryBlock()創建的CMBlockBuffer指向的內存遵循稍微不同的規則。首先,該方法不會複製memoryBlock指向的數據;它直接使用該指針。這意味着BlockBuffer需要掌握如何管理內存的一些知識。這由CMBlockBufferCreateWithMemoryBlock()的第四個或第五個參數來處理:如果其中任一個是非kCFAllocatorNull/NULL,則BlockBuffer將在內存完成時調用其中一個的解除分配器。這通常是在BlockBuffer的Finalize()中完成的。如果它們都是kCFAllocatorNull/NULL(你在你的代碼片段中),BlockBuffer會在內存完成時將指針放在地板上。

這意味着如果您使用CMBlockBufferCreateWithMemoryBlock()創建CMBlockBuffer,並且打算在將它傳遞給渲染管道後在該BlockBuffer上釋放您的保留,則應該爲allocator/deallocators使用非NULL參數,以便內存可以稍後回收。這些分配器/釋放器的實現當然取決於memoryBlock的來源。

+0

謝謝,這很有幫助。所以如果我使用malloc來分配CMBlockBuffer,那麼正確的分配器值是什麼? –

+0

另外一個注意事項是,我確實得到了這個工作,但是我發現交給VTVideoFormatDescription的另一個數據結構看起來並沒有被會話複製,而且我還需要確保我保持在該塊上,否則我得到一個崩潰。 這些條件的崩潰出現在CFEqual例程中的彙編中,如果您向上看一級,則會看到當時正試圖讀取CMVideoFormatDescription。 –

+1

kCFAllocatorMalloc的文檔說它使用malloc,realloc和free。但是,如果我要走這條路線,我可能會使用相同的分配器直接分配內存,而不是假定我對malloc()的調用將分配器的調用與free()匹配。看起來更安全,更明確/更易於理解,儘管文檔聲稱它們是相同的。 – DSaracino