【发布时间】:2014-01-07 06:58:40
【问题描述】:
我正在使用 AVAssetWriter/AVAssetWriterInput 将 H.264 原始数据写入 MP4 文件。当我从远程服务器接收数据时,我使用以下 CoreMedia API 来获取包含 AVCC 格式的 H.264 数据的样本缓冲区 (CMSampleBufferRef),然后通过发送到 @987654321 将其附加到 MP4 文件@留言(BOOL)appendSampleBuffer:(CMSampleBufferRef)sampleBuffer:
CMBlockBufferCreateWithMemoryBlock创建内存块CMBlockBufferReplaceDataBytes将 AVCC 格式的 H.264 写入内存块CMSampleBufferCreate使用内存块和包含 H.264“额外数据”的格式描述符创建一个样本缓冲区
一切都按预期工作,这种方法的唯一问题是我会定期调用上述 API,而我真正想要的是能够重用分配的资源 - 特别是 CMSampleBufferRef 和 CMBlockBufferRef . 基本上,我想拥有一个CMSampleBuffer 的池,并且能够在我从远程服务器接收新的 H.264 数据时更新其内存内容和格式描述符。。 p>
我知道存在 AVAssetWriterInputPixelBufferAdaptor 可以访问 CVPixelBufferPool 但是,我不能在我的情况下使用它,因为据我所知,要正确实例化像素缓冲区适配器,至少我需要能够传递在我解析流之前我会知道的视频帧尺寸。此外,我不知道如何使用CVPixelBuffer 编写 H.264“额外数据”。所以,我认为我需要坚持使用CMSampleBuffer。不幸的是,CoreMedia API 似乎无法在创建后更新内存块或样本缓冲区的格式描述符(据我所知,我只能访问这些对象的不可变引用)。因此,到目前为止我能做的最好的事情就是重用内存块CMBlockBufferRef,但我仍在重新创建样本缓冲区。我的代码如下。希望这里有人对如何实现CMSampleBuffer 池或将 H.264 AVCC 流写入 MP4 的更有效方法有一些想法?
- (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([data bytes], _blockBuffer, 0, [data length]);
// check error
const size_t sampleSizes = [data length];
CMSampleTimingInfo timing = [self sampleTimingInfo];
result = CMSampleBufferCreate(kCFAllocatorDefault,
_blockBuffer,
YES,
NULL,
NULL,
formatDescription,
1,
1,
&timing,
1,
&sampleSizes,
&sampleBuffer);
// check error
return sampleBuffer;
}
【问题讨论】:
标签: ios objective-c video avfoundation h.264