简体   繁体   English

AVAssetWriterInput H.264传递到QuickTime(.mov)-传递SPS / PPS创建avcC原子吗?

[英]AVAssetWriterInput H.264 Passthrough to QuickTime (.mov) - Passing in SPS/PPS to create avcC atom?

I have a stream of H.264/AVC NALs consisting of types 1 (P frame), 5 (I frame), 7 (SPS), and 8 (PPS). 我有一个H.264 / AVC NAL流,它由类型1(P帧),5(I帧),7(SPS)和8(PPS)组成。 I want to write them into an .mov file without re-encoding. 我想将它们写入.mov文件而无需重新编码。 I'm attempting to use AVAssetWriter to do this. 我正在尝试使用AVAssetWriter来执行此操作。 The documentation for AVAssetWriterInput states: AVAssetWriterInput的文档指出:

Passing nil for outputSettings instructs the input to pass through appended samples, doing no processing before they are written to the output file. 为outputSettings传递nil指示输入传递附加的样本,在将它们写入输出文件之前不进行任何处理。 This is useful if, for example, you are appending buffers that are already in a desirable compressed format. 例如,如果您要添加已经采用所需压缩格式的缓冲区,则此功能很有用。 However, passthrough is currently supported only when writing to QuickTime Movie files (ie the AVAssetWriter was initialized with AVFileTypeQuickTimeMovie). 但是,当前仅在写入QuickTime电影文件时(即AVAssetWriter已使用AVFileTypeQuickTimeMovie初始化)时才支持直通。 For other file types, you must specify non-nil output settings. 对于其他文件类型,必须指定非空输出设置。

I'm trying to create CMSampleBuffers out of these NALs and append them to the asset writer input, but I am unable to input the data in a way that yields a well-formed .mov file, and I can't find any clue anywhere on how to do this. 我正在尝试从这些NAL中创建CMSampleBuffers并将它们附加到资产编写者输入中,但是我无法以产生格式正确的.mov文件的方式输入数据,而且在任何地方都找不到任何线索关于如何做到这一点。

The best result I've gotten so far was passing in the NALs in Annex B byte stream format (in the order 7 8 5 1 1 1....repeating) and playing the result in VLC. 到目前为止,我得到的最好结果是以附件B字节流格式(按7 8 5 1 1 1 ....重复的顺序)传递NAL,并在VLC中播放结果。 Because of this, I know the NALs contain valid data, but because the .mov file did not have an avcC atom and the mdat atom was filled with an Annex B byte stream, QuickTime will not play the video. 因此,我知道NAL中包含有效数据,但是由于.mov文件中没有avcC原子,而mdat原子中填充有Annex B字节流,因此QuickTime将无法播放视频。

Now I'm trying to pass in the NALs with a 4-byte (as specified by the lengthSizeMinusOne field) length field instead of the Annex B delimiter, which is how they're supposed to be packed into the mdat atom as far as I know. 现在,我尝试使用长度为4字节(由lengthSizeMinusOne字段指定)的lengthSizeMinusOne (而不是附件B分隔符)传递给NAL,这是我应该将它们打包到mdat原子中的方式知道。

I am at a loss for how to get the asset writer to write an avcC atom. 我不知如何使资产编写者编写avcC原子。 Every sample I append just gets shoved into the mdat atom. 我追加的每个样本都被推入mdat原子中。

Does anyone know how I can pass raw H.264 data into an AVAssetWriterInput configured for pass through (nil outputSettings) and have it generate a properly formed QuickTime file? 有谁知道我如何将原始H.264数据传递到配置为通过的AVAssetWriterInput中(无outputSettings),并使其生成格式正确的QuickTime文件?

I have submitted a TSI with apple and found the answer. 我已经与苹果公司提交了TSI,并找到了答案。 I hope this saves someone time in the future. 我希望这可以节省将来的时间。

The CMSampleBuffers have associated with them a CMFormatDescription, which contains a description of the data in the sample buffer. CMSampleBuffers与它们相关联的CMFormatDescription,其中包含对样本缓冲区中数据的描述。

The function prototype for creating the format description is as follows: 用于创建格式描述的函数原型如下:

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

I learned, from the Apple technician, that I can use the extensions argument to pass in a dictionary containing the avcC atom data. 我从Apple技术人员那里得知,我可以使用extensions参数传入包含avcC原子数据的字典。

The extensions dictionary should be of the following form: 扩展字典应采用以下形式:

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

The []'s represent dictionaries. []代表字典。 This dictionary can potentially be used to pass in data for arbitrary atoms aside from avcC. 除了avcC之外,该词典还可能用于传递任意原子的数据。

Here is the code I used to create the extensions dictionary that I pass into CMVideoFormatDescriptionCreate : 这是我用来创建extensions字典的代码,该字典传递给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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM