2016-11-29 15 views
0

私は、ネイティブのAnnex-B H.264ストリームを解凍するコードを書いています。ストリームの解析、SPS/PPS NALUからのCMVideoFormatDescriptionの作成、他のNALUは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を保持していることを示しています.DVDDecodeSessionはデコードが完了するまでCMSampleBufferを保持しますが、これはドキュメント化されていない領域なので方向性を探しています。私の直感を暗にしている結果は間違っている可能性があるので、私は自分の正気を保つための問題としてメモリ管理を排除する必要があります...

答えて

1

CMSampleBuffersとCMBlockBuffers - 典型的なCF保持/解放のセマンティクスに従います。これらのオブジェクトが必要である限り、保持を保持し、それらを受け入れるインターフェイスが同じであると仮定します。つまり、CMBlockBufferをCMSampleBufferに渡すとすぐにCMBlockBufferを解放することができ、レンダリングチェーンに渡した後でCMSampleBufferを解放することができます。

CMBlockBufferCreateWithMemoryBlock()で作成されたCMBlockBufferが指すメモリは、わずかに異なる規則に従います。まず、そのメソッドはmemoryBlockが指すデータをコピーしません。そのポインタを直接使用します。これは、BlockBufferがそのメモリをどのように管理すべきかについて何らかの知識が必要であることを意味します。これは、CMBlockBufferCreateWithMemoryBlock()の第4引数または第5引数のいずれかによって処理されます。どちらかがkCFAllocatorNull/NULLでなければ、BlockBufferはメモリが終了したときにそれらのいずれかのデオロケータを呼び出します。これは通常、BlockBufferのFinalize()で行われます。それらが両方ともkCFAllocatorNull/NULL(コードスニペットに含まれている)の場合、BlockBufferはメモリが終了したらポインタを床にドロップします。

これは、あなたがCMBlockBufferCreateWithMemoryBlockを(使用してCMBlockBuffer)を作成し、メモリができるようにBlockBufferは、レンダリングパイプラインをそれを通過した後、あなたはアロケータ/デアロケータのために非NULLの引数を使用する必要があることに保持リリースする予定であればということを意味後で回収される。もちろん、これらのアロケータ/デアロケータの実装は、memoryBlockの起源に依存しています。

+0

ありがとう、これは役に立ちます。したがって、mallocを使用してCMBlockBufferを割り当てる場合、正しいアロケータ値は何ですか? –

+0

もう1つメモしておきましたが、これはうまくいきましたが、VTDecompressionSessionCreateに渡された別のデータ構造CMVideoFormatDescriptionがセッションでコピーされないように見えました。クラッシュする これらの条件のクラッシュはアセンブリでCFEqualルーチンに表示されます。レベルを1つ上に見た場合、その時点でCMVideoFormatDescriptionを読み取ろうとしています。 –

+1

kCFAllocatorMallocのドキュメントでは、malloc、realloc、およびfreeを使用していることを示しています。しかし、もし私がそのルートに行くなら、おそらく同じアロケータを使用して、malloc()への呼び出しがfree()へのアロケータの呼び出しと一致すると仮定するのではなく、直接メモリを割り当てます。ドキュメントが同じであると主張していても、より安全で明示的/理解しやすいようです。 – DSaracino

関連する問題