AVAssetWriterinputH.264直通到QuickTime(.mov) – 传入SPS / PPS来创buildavcCprimefaces?

我有一个由types1(P帧),5(I帧),7(SPS)和8(PPS)组成的H.264 / AVC NALstream。 我想把它们写入一个.mov文件而不用重新编码。 我试图使用AVAssetWriter来做到这一点。 AVAssetWriterInput的文档状态:

对outputSettings传递nil指示input通过附加采样,在写入输出文件之前不做任何处理。 例如,如果您正在追加已经处于所需压缩格式的缓冲区,这非常有用。 但是,只有在写入QuickTime影片文件(即AVAssetWriter用AVFileTypeQuickTimeMovie初始化)时才支持直通。 对于其他文件types,您必须指定非零输出设置。

我试图从这些NAL中创buildCMSampleBuffers并将它们附加到资产编写器input,但是我无法以产生格式正确的.mov文件的方式input数据,而且我无法在任何地方find任何线索如何做到这一点。

到目前为止,最好的结果是以附件B字节stream格式(以7 8 5 1 1 1 ….重复的顺序)传递NAL,并在VLC中播放结果。 因此,我知道NAL包含有效的数据,但由于.mov文件没有avcCprimefaces,mdatprimefaces填充了附件B字节stream,所以QuickTime不会播放video。

现在,我试图传入4个字节(由lengthSizeMinusOne字段指定)长度字段而不是附件B分隔符的lengthSizeMinusOne ,这就是应该如何将它们打包到mdatprimefaces中,直到我知道。

我不知道如何让资产编写者写一个avcCprimefaces。 我追加的每个样本都被推入mdatprimefaces。

有谁知道我可以传递原始的H.264数据到AVAssetWriterInputconfiguration为通过(nil outputSettings)并让它生成一个正确形成的QuickTime文件?

我已经提交了苹果TSI,find了答案。 我希望这能节省一些时间。

CMSampleBuffers与它们关联了一个CMFormatDescription,它包含了样本缓冲区中数据的描述。

用于创build格式描述的函数原型如下所示:

 OSStatus CMVideoFormatDescriptionCreate ( CFAllocatorRef allocator, CMVideoCodecType codecType, int32_t width, int32_t height, CFDictionaryRef extensions, CMVideoFormatDescriptionRef *outDesc ); 

我从苹果技术人员那里了解到,我可以使用扩展parameter passing包含avcCprimefaces数据的字典。

扩展词典应该是以下forms:

 [kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms ---> ["avcC" ---> <avcC Data>]] 

[]代表词典。 除了avcC之外,该字典还可能用于传递任意primefaces的数据。

这里是我用来创buildextensions字典,我传入CMVideoFormatDescriptionCreate

  const char *avcC = "avcC"; const CFStringRef avcCKey = CFStringCreateWithCString(kCFAllocatorDefault, avcC, kCFStringEncodingUTF8); const CFDataRef avcCValue = CFDataCreate(kCFAllocatorDefault, [_avccData bytes], [_avccData length]); const void *atomDictKeys[] = { avcCKey }; const void *atomDictValues[] = { avcCValue }; CFDictionaryRef atomsDict = CFDictionaryCreate(kCFAllocatorDefault, atomDictKeys, atomDictValues, 1, nil, nil); const void *extensionDictKeys[] = { kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms }; const void *extensionDictValues[] = { atomsDict }; CFDictionaryRef extensionDict = CFDictionaryCreate(kCFAllocatorDefault, extensionDictKeys, extensionDictValues, 1, nil, nil);