与原始NAL单位一起使用AVAssetWriter
我注意到在AVAssetWriterInput
的iOS文档中,你可以传递nil
给outputSettings
字典来指定input数据不应该被重新编码。
用于编码附加到输出的媒体的设置。 通过零来指定附加的样本不应该被重新编码。
我想利用这个function来传递一个H.264原始NALstream,但是我无法将我的原始字节stream转换成一个CMSampleBuffer
,我可以将它传递到AVAssetWriterInput的appendSampleBuffer
方法中。 我的NALstream只包含SPS / PPS / IDR / P NAL(1,5,7,8)。 我一直无法find有关如何使用预编码的H264数据与AVAssetWriter的文件或结论性的答案。 生成的video文件无法播放。
我如何正确打包NUM单元到CMSampleBuffers
? 我是否需要使用起始码前缀? 长度前缀? 我是否需要确保每个CMSampleBuffer
只放置一个NAL? 我的最终目标是创build一个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
,我认为这是一个有效的时间,然后才实际尝试附加它。
任何帮助表示赞赏。
我设法让video播放工作在VLC,但不是QuickTime。 我使用的代码类似于我上面发布的将H.264 NAL转换为CMSampleBuffers的代码。
我有两个主要问题:
- 我没有正确设置CMSampleTimingInfo(正如我的评论上述状态)。
- 我没有正确打包原始NAL数据(不知道在哪里logging,如果有的话)。
为了解决#1,我设置了timing.duration = CMTimeMake(1, fps);
fps是预期的帧速率。 然后我设置timing.decodeTimeStamp = kCMTimeInvalid;
意味着样本将按解码顺序给出。 最后,我通过计算绝对时间来设置timing.presentationTimeStamp
,我也使用startSessionAtSourceTime
。
为了解决#2,通过试验和错误,我发现给我的NAL单位在以下forms工作:
[7 8 5] [1] [1] [1]..... [7 8 5] [1] [1] [1]..... (repeating)
每个NAL单元的前缀是一个32位的起始码,等于0x00000001
。
大概出于同样的原因,它不是在QuickTime中播放,我仍然无法将生成的.mov文件移动到相册( ALAssetLibrary
方法videoAtPathIsCompatibleWithSavedPhotosAlbum
失败,指出“电影无法播放”。希望有人有想法关于发生了什么事可以发表评论。谢谢!
- AVAssetWriter输出大文件(即使应用压缩设置)
- AVAssetWriterinputH.264直通到QuickTime(.mov) – 传入SPS / PPS来创buildavcCprimefaces?
- AVAssetWriter可以使用透明度编写文件吗?
- 我如何使用AVAssetWriter?
- GPUImageMovieWriter – 崩溃时,状态为2时无法调用方法
- 如何使用AVAssetWriter将静态和dynamic叠加添加到video?
- OpenGL ES 2.0到iPad / iPhone上的video
- 像素格式,CVPixelBufferRefs和glReadPixels
- 更改AVCaptureDeviceInput导致AVAssetWriterStatusFailed