我注意到在AVAssetWriterInput
的iOS文档中,您可以为nil
字典传递outputSettings
,以指定不应重新编码输入数据。
用于编码附加到输出的媒体的设置。传递nil以指定不应重新编码附加的样本。
我想利用此功能传入原始H.264 NAL流,但我无法将原始字节流调整为CMSampleBuffer
,我可以将其传递给AVAssetWriterInput的{{1} } 方法。我的NAL流只包含SPS / PPS / IDR / P NAL(1,5,7,8)。我无法找到有关如何使用AVAssetWriter预编码H264数据的文档或结论性答案。生成的视频文件无法播放。
如何将NAL单位正确打包到appendSampleBuffer
?我需要使用开始代码前缀吗?长度前缀?我是否需要确保每CMSampleBuffers
只放一个NAL?我的最终目标是使用H264 / AAC创建MP4或MOV容器。
这是我一直在玩的代码:
CMSampleBuffer
请注意,我在-(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];
});
}
方法内部的示例缓冲区上调用CMSampleBufferSetOutputPresentationTimeStamp
,我认为这是我实际尝试追加它之前的有效时间。
感谢任何帮助。
答案 0 :(得分:3)
我设法让视频播放工作在VLC但不是QuickTime。我使用类似于上面发布的代码将H.264 NAL放入CMSampleBuffers。
我有两个主要问题:
要解决#1,我设置timing.duration = CMTimeMake(1, fps);
,其中fps是预期的帧速率。然后我设置timing.decodeTimeStamp = kCMTimeInvalid;
表示将按解码顺序给出样本。最后,我通过计算绝对时间来设置timing.presentationTimeStamp
,我也使用了startSessionAtSourceTime
。
要解决#2,通过反复试验我发现以下列形式提供我的NAL单位:
[7 8 5] [1] [1] [1]..... [7 8 5] [1] [1] [1]..... (repeating)
每个NAL单元的前缀是32位起始码,等于0x00000001
。
大概是因为它没有在QuickTime中播放,我仍然无法将生成的.mov文件移动到相册(ALAssetLibrary
方法videoAtPathIsCompatibleWithSavedPhotosAlbum
未能说明“电影”无法播放。“希望有人知道发生了什么事可以评论。谢谢!