我正在使用 AVAssetWriter/AVAssetWriterInput 将 H.264 原始数据写入 MP4 文件。当我从远程服务器接收数据时,我使用以下 CoreMedia API 获取样本缓冲区 (CMSampleBufferRef),其中包含 AVCC 格式的 H.264 数据,该数据又通过发送到 AVAssetWriterInput 附加到 MP4 文件消息 (BOOL)appendSampleBuffer:(CMSampleBufferRef)sampleBuffer:
CMBlockBufferCreateWithMemoryBlockto create a memory blockCMBlockBufferReplaceDataBytesto write the H.264 in AVCC format to the memory blockCMSampleBufferCreateto 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/
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
我想知道Ruby用来在命令行打印这些东西的输出流:irb(main):001:0>a="test"=>"test"irb(main):002:0>putsatest=>nilirb(main):003:0>a=>"test"$stdout是否用于irb(main):002:0>和irb(main):003:0>?而且,在这两次调用之间,$stdout的值是否有任何变化?另外,有人能告诉我打印/写入这些内容的Ruby源代码吗? 最佳答案 是的。而且很容易向自己测试/证明。在命令行试试这个:ruby-e'puts"foo"'>test.
print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上
我正在编写一个ruby程序,它应该执行另一个程序,通过stdin向它传递值,从它的stdout读取响应,然后打印响应。这是我目前所拥有的。#!/usr/bin/envrubyrequire'open3'stdin,stdout,stderr=Open3.popen3('./MyProgram')stdin.puts"helloworld!"output=stdout.readerrors=stderr.readstdin.closestdout.closestderr.closeputs"Output:"puts"-------"putsoutputputs"\nErrors:"p
我正在处理http://prepwork.appacademy.io/mini-curriculum/array/中概述的数组问题我正在尝试创建函数my_transpose,它接受一个矩阵并返回其转置。我对写入二维数组感到很困惑!这是一个代码片段,突出了我的困惑。rows=[[0,1,2],[3,4,5],[6,7,8]]columns=Array.new(3,Array.new(3))putscolumns.to_s#Outputisa3x3arrayfilledwithnilcolumns[0][0]=0putscolumns.to_s#Outputis[[0,nil,nil],[
我在一个ruby文件中有一个函数可以像这样写入一个文件File.open("myfile",'a'){|f|f.puts("#{sometext}")}这个函数在不同的线程中被调用,使得像上面这样的文件写入不是线程安全的。有谁知道如何以最简单的方式使这个文件写入线程安全?更多信息:如果重要的话,我正在使用rspec框架。 最佳答案 您可以通过File#flock给锁File.open("myfile",'a'){|f|f.flock(File::LOCK_EX)f.puts("#{sometext}")}
有人可以花我一些代码,在图像底部添加文本吗?我想使用Rmagick,但我也愿意使用其他工具。 最佳答案 我也发现了这个,它非常适合我。require'RMagick'includeMagick#Dimisionsbasedonanimage3072x2048unlessARGV[0]andFile.exists?(ARGV[0])puts"\n\n\nYouneedtospecifyafilename:watermark.rb\n\n\n"exitendimg=Image.read(ARGV[0]).firstnew_img="wm