AVAssetWriterInput H.264 Passthrough to QuickTime(.mov) - 通过SPS / PPS创建avcC原子? [英] AVAssetWriterInput H.264 Passthrough to QuickTime (.mov) - Passing in SPS/PPS to create avcC atom?

查看:268
本文介绍了AVAssetWriterInput H.264 Passthrough to QuickTime(.mov) - 通过SPS / PPS创建avcC原子?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个由类型1(P帧),5(I帧),7(SPS)和8(PPS)组成的H.264 / AVC NAL流。我想将它们写入.mov文件而不重新编码。我正在尝试使用 AVAssetWriter 来执行此操作。 AVAssetWriterInput 的文档说明:

I have a stream of H.264/AVC NALs consisting of types 1 (P frame), 5 (I frame), 7 (SPS), and 8 (PPS). I want to write them into an .mov file without re-encoding. I'm attempting to use AVAssetWriter to do this. The documentation for AVAssetWriterInput states:


为outputSettings传递nil指示输入通过通过附加的示例,在将它们写入输出文件之前不进行处理。例如,如果要附加已经采用所需压缩格式的缓冲区,则此选项非常有用。但是,只有在写入QuickTime Movie文件时才支持passthrough(即AVAssetWriter是使用AVFileTypeQuickTimeMovie初始化的)。对于其他文件类型,您必须指定非零输出设置。

Passing nil for outputSettings instructs the input to pass through appended samples, doing no processing before they are written to the output file. 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 (i.e. the AVAssetWriter was initialized with AVFileTypeQuickTimeMovie). For other file types, you must specify non-nil output settings.

我正在尝试从这些NAL中创建CMSampleBuffers并追加它们是资产编写者的输入,但我无法以产生格式良好的.mov文件的方式输入数据,而且我无法找到任何关于如何执行此操作的线索。

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.

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

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. 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.

现在我正在尝试使用4字节(由 lengthSizeMinusOne 字段指定)长度字段传入NAL而不是附件B分隔符,就我所知,它们应该被打包到mdat原子中。

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.

我对如何让资产作者写一个avcC原子感到很茫然。我追加的每个样本都被推入mdat原子。

I am at a loss for how to get the asset writer to write an avcC atom. Every sample I append just gets shoved into the mdat atom.

有谁知道如何将原始H.264数据传递到为传递配置的AVAssetWriterInput( nil outputSettings)并让它生成一个正确形成的QuickTime文件?

推荐答案

我已经提交了一个苹果和TSI的TSI找到了答案。我希望将来节省一些时间。

I have submitted a TSI with apple and found the answer. I hope this saves someone time in the future.

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

The CMSampleBuffers have associated with them a CMFormatDescription, which contains a description of the data in the sample buffer.

创建格式描述的函数原型如下:

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
);

我从Apple技术人员那里了解到,我可以使用extensions参数传入包含字典的字典avcC原子数据。

I learned, from the Apple technician, that I can use the extensions argument to pass in a dictionary containing the avcC atom data.

扩展词典应该是以下形式:

The extensions dictionary should be of the following form:

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

[]代表字典。除了avcC之外,这个字典可能用于传递任意原子的数据。

The []'s represent dictionaries. This dictionary can potentially be used to pass in data for arbitrary atoms aside from avcC.

这是我用来创建扩展名的代码字典 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);

这篇关于AVAssetWriterInput H.264 Passthrough to QuickTime(.mov) - 通过SPS / PPS创建avcC原子?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆