ios - CMSampleBufferRef 池写入 H.264 AVCC 流
<p><p>我正在使用 AVAssetWriter/AVAssetWriterInput 将 H.264 原始数据写入 MP4 文件。当我从远程服务器接收数据时,我使用以下 CoreMedia API 来获取包含 AVCC 格式的 H.264 数据的样本缓冲区 (CMSampleBufferRef),然后通过发送到 <code>AVAssetWriterInput</code> 消息 <code>(BOOL)appendSampleBuffer:(CMSampleBufferRef)sampleBuffer</code>:</p>
<blockquote>
<ol>
<li><code>CMBlockBufferCreateWithMemoryBlock</code> to create a memory block</li>
<li><code>CMBlockBufferReplaceDataBytes</code> to write the H.264 in AVCC format to the memory block</li>
<li><code>CMSampleBufferCreate</code> to create a sample buffer with the memory block and a format descriptor containing the H.264 "extradata"</li>
</ol>
</blockquote>
<p>一切都按预期工作,这种方法的唯一问题是我会定期调用上述 API,而我真正想要的是能够重用分配的资源 - 特别是 <code>CMSampleBufferRef</code> 和 <code>CMBlockBufferRef</code>。 <strong>基本上,我希望有一个 <code>CMSampleBuffer</code> 池,并且能够在我从远程服务器接收新的 H.264 数据时更新其内存内容和格式描述符</强>。</p>
<p>我知道存在 <code>AVAssetWriterInputPixelBufferAdaptor</code> 可以访问 <code>CVPixelBufferPool</code> 但是,我不能在我的情况下使用它,因为据我所知,要正确实例化一个像素缓冲区适配器,至少我需要能够传递我知道的视频帧尺寸,直到我解析流。此外,我不知道如何用 <code>CVPixelBuffer</code> 编写 H.264“额外数据”。所以,我认为我需要坚持使用 <code>CMSampleBuffer</code>。不幸的是,CoreMedia API 似乎无法在创建后更新内存块或样本缓冲区的格式描述符(据我所知,我只能访问这些对象的不可变引用)。因此,到目前为止我能做的最好的事情是重用内存块 <code>CMBlockBufferRef</code> 但我仍在重新创建样本缓冲区。我的代码如下。希望这里有人对如何实现 <code>CMSampleBuffer</code> 池或将 H.264 AVCC 流写入 MP4 的更有效方法有一些想法?</p>
<pre><code>- (CMSampleBufferRef)sampleBufferWithData:(NSData*)data formatDescriptor:(CMFormatDescriptionRef)formatDescription
{
OSStatus result;
CMSampleBufferRef sampleBuffer = NULL;
// _blockBuffer is a CMBlockBufferRef instance variable
if (!_blockBuffer)
{
size_t blockLength = MAX_LENGTH;
result = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,
NULL,
blockLength,
kCFAllocatorDefault,
NULL,
0,
blockLength,
kCMBlockBufferAssureMemoryNowFlag,
&_blockBuffer);
// check error
}
result = CMBlockBufferReplaceDataBytes(, _blockBuffer, 0, );
// check error
const size_t sampleSizes = ;
CMSampleTimingInfo timing = ;
result = CMSampleBufferCreate(kCFAllocatorDefault,
_blockBuffer,
YES,
NULL,
NULL,
formatDescription,
1,
1,
&timing,
1,
&sampleSizes,
&sampleBuffer);
// check error
return sampleBuffer;
}
</code></pre></p>
<br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
<p><p>如果您接收的是原始 H.264 数据,则无需做太多事情,也根本不需要处理 CoreMedia。</p>
<p>缓冲所有 VCL NAL 单元,直到获得 SPS/PPS NAL 单元。从它们创建额外数据,然后将所有缓冲的和新的 VCL NAL 单元附加到文件中。如果您收到附件 B 格式的 NAL 单元,您需要将它们转换为 AVCC 格式(基本上用长度代码替换起始代码)</p>
<p>如果您想要解码未压缩的图片或想要解码压缩的图片,您只需要使用“CMSampleBuffer”。由于您已经在使用原始 H.264 流并且只想将其写入 MP4 文件,因此请执行此操作。这里根本不需要接触CoreMedia。</p>
<p>关于 CoreMedia:您将视频信息包装在 <code>CMBlockBuffer</code> 中。这个缓冲区与 <code>CMVideoFormatDescriptor</code>(从 SPS/PPS 生成)加上 <code>CMTime</code> 一起构成了一个 <code>CMSampleBuffer</code>。多个 <code>CMSampleBuffers</code> 组成一个“CMSampleBufferPool”。 </p>
<p> 'CVPixelBuffer' 和 'CVPixelBufferPool' 不涉及。在处理编码/解码 h.264 视频时,这些是“VTCompressionSession”或“VTDecompressionSession”的输入或输出。</p>
<p>正如你所说的,你只是在创建一个文件,根本不需要接触任何核心框架。</p>
<p>可以在此处找到有关附件 B 和 AVCC 流格式的概述:<a href="https://stackoverflow.com/questions/24884827/possible-locations-for-sequence-picture-parameter-sets-for-h-264-stream" rel="noreferrer noopener nofollow">Possible Locations for Sequence/Picture Parameter Set(s) for H.264 Stream</a> </p></p>
<p style="font-size: 20px;">关于ios - CMSampleBufferRef 池写入 H.264 AVCC 流,我们在Stack Overflow上找到一个类似的问题:
<a href="https://stackoverflow.com/questions/20965719/" rel="noreferrer noopener nofollow" style="color: red;">
https://stackoverflow.com/questions/20965719/
</a>
</p>
页:
[1]