我iOS的文档中发现了AVAssetWriterInput可以传递nil的outputSettings字典来指定输入数据不应该被重新编码.
用于编码附加到输出的媒体的设置.传递nil以指定不应重新编码附加的样本.
我想利用这个功能传递原始H.264 NAL流,但是我无法将原始字节流调整为CMSampleBuffer可以传递到AVAssetWriterInput的appendSampleBuffer方法.我的NAL流只包含SPS/PPS/IDR/P NAL(1,5,7,8).我无法找到有关如何使用AVAssetWriter预编码H264数据的文档或结论性答案.生成的视频文件无法播放.
如何正确打包NAL单元CMSampleBuffers?我需要使用开始代码前缀吗?长度前缀?我需要确保每个只放一个NAL CMSampleBuffer吗?我的最终目标是使用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"); …Run Code Online (Sandbox Code Playgroud) 我有一个H.264/AVC NAL流,包括类型1(P帧),5(I帧),7(SPS)和8(PPS).我想将它们写入.mov文件而不重新编码.我试图用AVAssetWriter这个来做.AVAssetWriterInput各州的文件:
为outputSettings传递nil指示输入传递附加的样本,在将它们写入输出文件之前不进行任何处理.例如,如果要附加已经采用所需压缩格式的缓冲区,则此方法很有用.但是,只有在写入QuickTime Movie文件时才支持passthrough(即AVAssetWriter是使用AVFileTypeQuickTimeMovie初始化的).对于其他文件类型,您必须指定非零输出设置.
我正在尝试从这些NAL中创建CMSampleBuffers并将它们附加到资产编写器输入,但我无法以产生格式良好的.mov文件的方式输入数据,我无法在任何地方找到任何线索关于如何做到这一点.
到目前为止,我得到的最好结果是以附件B字节流格式传递NAL(按照顺序7 8 5 1 1 1 ....重复)并在VLC中播放结果.因此,我知道NAL包含有效数据,但由于.mov文件没有avcC原子且mdat原子填充了附件B字节流,因此QuickTime不会播放视频.
现在我试图用4字节(由lengthSizeMinusOne字段指定)长度字段而不是附件B分隔符传入NAL,就我所知,它们应该被打包到mdat原子中. .
我不知道如何让资产作者写一个avcC原子.我附加的每个样本都被推入mdat原子.
有谁知道如何将原始H.264数据传递到为传递(nil outputSettings)配置的AVAssetWriterInput并让它生成正确形成的QuickTime文件?