- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在使用 AVAssetWriter/AVAssetWriterInput 将 H.264 原始数据写入 MP4 文件。当我从远程服务器接收数据时,我使用以下 CoreMedia API 获取样本缓冲区 (CMSampleBufferRef),其中包含 AVCC 格式的 H.264 数据,该数据又通过发送到 AVAssetWriterInput
附加到 MP4 文件消息 (BOOL)appendSampleBuffer:(CMSampleBufferRef)sampleBuffer
:
CMBlockBufferCreateWithMemoryBlock
to create a memory blockCMBlockBufferReplaceDataBytes
to write the H.264 in AVCC format to the memory blockCMSampleBufferCreate
to create a sample buffer with the memory block and a format descriptor containing the H.264 "extradata"
一切都按预期工作,这种方法的唯一问题是我定期调用上述 API,而我真正想要的是能够重用分配的资源 - 特别是 CMSampleBufferRef
和 CMBlockBufferRef
。 基本上,我想要一个 CMSampleBuffer
的池,并且能够在我从远程服务器接收新的 H.264 数据时更新其内存内容和格式描述符。
我知道存在 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;
}
最佳答案
如果您接收的是原始 H.264 数据,那么根本不需要处理 CoreMedia。
缓冲所有 VCL NAL 单元,直到获得 SPS/PPS NAL 单元。从中创建额外数据,然后将所有缓冲的和新的 VCL NAL 单元附加到文件中。如果您收到附件 B 格式的 NAL 单元,您需要将它们转换为 AVCC 格式(基本上用长度代码替换起始代码)
如果你想解码未压缩的图片或者如果你想解码压缩的图片,你只需要使用'CMSampleBuffer'。因为您已经在处理原始 H.264 流并且只想将其写入 MP4 文件,所以就这样做吧。在这里根本不需要接触 CoreMedia。
关于 CoreMedia:您将视频信息包装在 CMBlockBuffer
中。此缓冲区与 CMVideoFormatDescriptor
(从 SPS/PPS 生成)加上 CMTime
组成 CMSampleBuffer
。多个 CMSampleBuffers
组成一个“CMSampleBufferPool”。
'CVPixelBuffer' 和 'CVPixelBufferPool' 不涉及。在处理编码/解码 h.264 视频时,这些是“VTCompressionSession”或“VTDecompressionSession”的输入或输出。
如您所说,根本不需要触及任何核心框架,因为您只是在创建一个文件。
有关附件 B 和 AVCC 流格式的概述可在此处找到:Possible Locations for Sequence/Picture Parameter Set(s) for H.264 Stream
关于ios - CMSampleBufferRef 池写入 H.264 AVCC 流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20965719/
根据Need to convert h264 stream from annex-b format to AVCC format : AnnexB format: ([start code] NALU
我正在尝试使用 C++ 中的 FFMPEG API 将原始 H264 编码为 mp4 容器。一切正常,但 AVCC 框为空,并返回错误:[iso 文件] 框“avcC”大小 8 无效 如果我然后在输出
我正在研究视频文件的来源识别,尤其是那些来自智能手机 s。 我知道 .mp4 视频文件中的 avcC 框中的值具有解码器在处理编码流时必须知道的编码选项(h.264)。 而且我猜大多数智能手机都使用定
我正在使用 AVAssetWriter/AVAssetWriterInput 将 H.264 原始数据写入 MP4 文件。当我从远程服务器接收数据时,我使用以下 CoreMedia API 获取样本缓
当使用 java 的 mp4parser 库读取源自 iTunes 的文件时,有没有办法访问 avcC 原子?我在一些自定义代码中使用 paspatom 手动完成了此操作,但切换到该库后我失去了对数据
我创建了一个 java 程序来解析 mp4 和 ts 段。我将带有 ffmpeg 的 ts 片段混合到 mp4 中。我试图理解为什么 ffmpeg 以这种方式形成 mdat。 以下是从 TS-PES
我尝试将 Android 相机预览帧编码为 h264,并复用到 mp4 容器。 我可以成功创建 mp4 文件。但是 mp4 格式似乎已损坏。 使用ffprobe,我得到了以下错误。 $ ffprobe
您好试图找到传递给 FFMPEG 的命令行参数,以将 ANNEX B 格式的原始 H.264 文件转换为 AVCC 格式,但我在互联网上找不到任何东西。我只找到了相反的内容(AVCC 到 ANNEX
我有一个 H.264/AVC NAL 流,由类型 1(P 帧)、5(I 帧)、7(SPS)和 8(PPS)组成。我想将它们写入 .mov 文件而不重新编码。我正在尝试使用 AVAssetWriter
我是一名优秀的程序员,十分优秀!