7

タイプ 1 (P フレーム)、5 (I フレーム)、7 (SPS)、および 8 (PPS) で構成される H.264/AVC NAL のストリームがあります。再エンコードせずに .mov ファイルに書き込みたい。私はこれを行うために使用しようとしAVAssetWriterています。状態のドキュメントAVAssetWriterInput:

outputSettings に nil を渡すと、追加されたサンプルを通過するように入力が指示され、出力ファイルに書き込まれる前に処理は行われません。これは、たとえば、既に適切な圧縮形式になっているバッファを追加する場合に便利です。ただし、パススルーは現在、QuickTime ムービー ファイルへの書き込み時のみサポートされています (つまり、AVAssetWriter は AVFileTypeQuickTimeMovie で初期化されています)。他のファイル タイプの場合は、nil 以外の出力設定を指定する必要があります。

これらの NAL から CMSampleBuffers を作成し、それらをアセット ライターの入力に追加しようとしていますが、整形式の .mov ファイルを生成する方法でデータを入力することができず、どこにも手がかりが見つかりません。これを行う方法について。

私がこれまでに得た最良の結果は、NAL を Annex B バイト ストリーム形式で渡し (7 8 5 1 1 1....繰り返し)、その結果を VLC で再生することでした。このため、NAL に有効なデータが含まれていることはわかっていますが、.mov ファイルに avcC アトムがなく、mdat アトムが Annex B バイト ストリームで満たされているため、QuickTime はビデオを再生しません。

lengthSizeMinusOne今、私は知っている限り、Annex B 区切り文字の代わりに4 バイト (フィールドで指定されている) の長さフィールドを使用して NAL を渡そうとしています。 .

アセット ライターに avcC アトムを書き込む方法がわかりません。追加するすべてのサンプルは、mdat アトムに押し込まれます。

生の H.264 データをパススルー (nil outputSettings) 用に構成された AVAssetWriterInput に渡し、適切な形式の QuickTime ファイルを生成する方法を知っている人はいますか?

4

1 に答える 1

9

Apple で TSI を提出したところ、答えが見つかりました。これが将来誰かの時間を節約することを願っています。

CMSampleBuffers には、サンプル バッファー内のデータの説明を含む CMFormatDescription が関連付けられています。

フォーマット記述を作成するための関数プロトタイプは次のとおりです。

OSStatus CMVideoFormatDescriptionCreate (
  CFAllocatorRef allocator,
  CMVideoCodecType codecType,
  int32_t width,
  int32_t height,
  CFDictionaryRef extensions,
  CMVideoFormatDescriptionRef *outDesc
);

Apple の技術者から、extensions 引数を使用して、avcC アトム データを含む辞書を渡すことができることを知りました。

拡張ディクショナリは、次の形式にする必要があります。

[kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms ---> ["avcC" ---> <avcC Data>]]

[] は辞書を表します。このディクショナリは、avcC 以外の任意のアトムのデータを渡すために使用できる可能性があります。

extensions渡す辞書を作成するために使用したコードは次のCMVideoFormatDescriptionCreateとおりです。

    const char *avcC = "avcC";
    const CFStringRef avcCKey = CFStringCreateWithCString(kCFAllocatorDefault, avcC, kCFStringEncodingUTF8);
    const CFDataRef avcCValue = CFDataCreate(kCFAllocatorDefault, [_avccData bytes], [_avccData length]);
    const void *atomDictKeys[] = { avcCKey };
    const void *atomDictValues[] = { avcCValue };
    CFDictionaryRef atomsDict = CFDictionaryCreate(kCFAllocatorDefault, atomDictKeys, atomDictValues, 1, nil, nil);

    const void *extensionDictKeys[] = { kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms };
    const void *extensionDictValues[] = { atomsDict };
    CFDictionaryRef extensionDict = CFDictionaryCreate(kCFAllocatorDefault, extensionDictKeys, extensionDictValues, 1, nil, nil);
于 2013-04-03T23:16:02.787 に答える