我注意到在iOS的
请注意,我正在
AVAssetWriterInput
文档中,你可以传递nil
来指定输入数据不需要重新编码。我想利用这个功能来传递一串原始的H.264 NALs流,但是我遇到了麻烦,无法将我的原始字节流调整为用于编码附加到输出的媒体的设置。传递
nil
以指定追加的样本不需要重新编码。
CMSampleBuffer
,以便我可以将其传递到AVAssetWriterInput的appendSampleBuffer
方法中。我的NALs流仅包含SPS / PPS / IDR / P NALs(1,5,7,8)。我找不到有关如何在AVAssetWriter中使用预编码H264数据的文档或确定性答案。生成的视频文件无法播放。我应该如何正确地将NAL单元打包成CMSampleBuffers
?我需要使用起始码前缀吗?长度前缀?我需要确保每个CMSampleBuffer
只放置一个NAL吗?我的最终目标是创建一个带有H264 / AAC的MP4或MOV容器。下面是我正在尝试的代码:-(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];
});
}
请注意,我正在
writeSampleBuffer
方法中对样本缓冲区调用CMSampleBufferSetOutputPresentationTimeStamp
,并使用我认为有效的时间戳尝试追加它。任何帮助都将不胜感激。
setOutputPresentationTimeStamp
来填充实际时间戳。现在我意识到我还需要填充CMSampleTimingInfo的其他字段。我将decodeTimeStamp
设置为kCMTimeInvalid
,将duration
设置为CMTimeMake(1, 30)
。现在我得到了一个可寻址的视频容器,具有适当的总时间,但是没有视频(在VLC中测试)。 - bsirang