AVAssetWriterInput
のiOSドキュメントで、nil
のoutputSettings
ディクショナリに入力データを再エンコードしないよう指定することができます。生のNALユニットでAVAssetWriterを使用
出力に追加されたメディアのエンコードに使用される設定。追加されたサンプルを再エンコードしないように指定するには、nilを渡します。
私は生のH.264のNALのストリームに渡すためにこの機能を利用したいが、私はAVAssetWriterInputのappendSampleBuffer
メソッドに渡すことができ、トラブルCMSampleBuffer
に私の生のバイトストリームを適応を持っています。私のNALストリームには、SPS/PPS/IDR/P NAL(1,5,7,8)のみが含まれています。 AVAssetWriterで事前にエンコードされたH264データを使用する方法に関するドキュメントや決定的な回答は見つかりませんでした。結果のビデオファイルは再生できません。
NALユニットを正しくCMSampleBuffers
にパッケージ化するにはどうすればよいですか?スタートコードプレフィックスを使用する必要がありますか?長さ接頭辞? CMSampleBuffer
ごとにNALを1つだけ入れる必要がありますか?私の最終目標は、H264/AACでMP4またはMOVコンテナを作成することです。私は私が実際によ前に、有効な時間と思われるものでwriteSampleBuffer
方法の内のサンプルバッファーにCMSampleBufferSetOutputPresentationTimeStamp
を呼んでいる
-(void)addH264NAL:(NSData *)nal
{
dispatch_async(recordingQueue, ^{
//Adapting the raw NAL into a CMSampleBuffer
CMSampleBufferRef sampleBuffer = NULL;
CMBlockBufferRef blockBuffer = NULL;
CMFormatDescriptionRef formatDescription = NULL;
CMItemCount numberOfSampleTimeEntries = 1;
CMItemCount numberOfSamples = 1;
CMVideoFormatDescriptionCreate(kCFAllocatorDefault, kCMVideoCodecType_H264, 480, 360, nil, &formatDescription);
OSStatus result = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, NULL, [nal length], kCFAllocatorDefault, NULL, 0, [nal length], kCMBlockBufferAssureMemoryNowFlag, &blockBuffer);
if(result != noErr)
{
NSLog(@"Error creating CMBlockBuffer");
return;
}
result = CMBlockBufferReplaceDataBytes([nal bytes], blockBuffer, 0, [nal length]);
if(result != noErr)
{
NSLog(@"Error filling CMBlockBuffer");
return;
}
const size_t sampleSizes = [nal length];
CMSampleTimingInfo timing = { 0 };
result = CMSampleBufferCreate(kCFAllocatorDefault, blockBuffer, YES, NULL, NULL, formatDescription, numberOfSamples, numberOfSampleTimeEntries, &timing, 1, &sampleSizes, &sampleBuffer);
if(result != noErr)
{
NSLog(@"Error creating CMSampleBuffer");
}
[self writeSampleBuffer:sampleBuffer ofType:AVMediaTypeVideo];
});
}
注:ここでは
は私がプレーしてきたコードですそれを追加しようとしています。何か助けていただければ幸いです。
少なくとも私の問題の一部は、どのように私がCMSampleTimingInfoを扱っていたかでした。実際のタイムスタンプを埋めるために 'setOutputPresentationTimeStamp'を使っていたと言いました。私は今、CMSampleTimingInfoの他のフィールドにも記入する必要があることを認識しています。 'decodeTimeStamp'を' kCMTimeInvalid'に、 'duration'を' CMTimeMake(1、30) 'に設定しています。私は今、適切な総時間でシーク可能なビデオコンテナを取得しますが、ビデオはありません(VLCでのテスト)。 – bsirang