这个库的文档基本上不存在,所以我真的需要你的帮助。
目标:我需要 H264 编码(最好同时使用音频和视频,但只有视频就可以了,我会玩几天让音频也能正常工作),这样我就可以将它传递到 MPEG 传输流中。
我有什么:我有一个记录和输出样本缓冲区的相机。输入是相机背面和内置麦克风。
几个问题: A. 是否可以让相机以 H264 格式输出 CMSampleBuffers?我的意思是,2014 年它是从 VTCompressionSessions 生成的,但是在编写我的 captureOutput 时,我看到我已经得到了一个 CMSampleBuffer ... B. 如何设置 VTCompressionSession? session 是如何使用的?一些关于此的总体顶级讨论可能有助于人们了解这个几乎没有记录的库中实际发生的事情。
此处的代码(如果需要,请索取更多;我只放了 captureOutput,因为我不知道其余代码的相关性如何):
func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
println(CMSampleBufferGetFormatDescription(sampleBuffer))
var imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
if imageBuffer != nil {
var pixelBuffer = imageBuffer as CVPixelBufferRef
var timeStamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer as CMSampleBufferRef)
//Do some VTCompressionSession stuff
}
}
谢谢大家!
最佳答案
首先初始化 VTCompression session 并设置其属性
NSDictionary* bAttributes= @{};
VTCompressionSessionRef vtComp;
OSStatus result = VTCompressionSessionCreate(NULL,
trackSize.width,
trackSize.height,
kCMVideoCodecType_H264,
NULL,
(CFDictionaryRef)bAttributes,
NULL,
compressCallback,
NULL,
&vtComp);
NSLog(@"create VTCS Status: %d",result);
NSDictionary* compProperties = @{
(id)kVTCompressionPropertyKey_ProfileLevel: (id)kVTProfileLevel_H264_High_AutoLevel,
(id)kVTCompressionPropertyKey_H264EntropyMode: (id)kVTH264EntropyMode_CABAC,
(id)kVTCompressionPropertyKey_Quality: @(0.95),
(id)kVTCompressionPropertyKey_RealTime: @(YES),
(id)kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder: @(YES),
(id)kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder: @(YES)
};
result=VTSessionSetProperties(vtComp,(CFDictionaryRef)compProperties);
compressCallback
是您的方法,它在压缩数据可用时调用。看起来像这样;
void compressCallback(void *outputCallbackRefCon, void *sourceFrameRefCon, OSStatus status, VTEncodeInfoFlags infoFlags, CMSampleBufferRef sampleBuffer)
{
AVAssetWriterInput* aw = (AVAssetWriterInput*)sourceFrameRefCon;
[aw appendSampleBuffer:sampleBuffer];
}
然后你有你的读取/压缩循环。 您从 CMSample 缓冲区获取 CVImage 缓冲区并将其传递给压缩器。
CVPixelBufferRef buffer = CMSampleBufferGetImageBuffer(cmbuf);
VTEncodeInfoFlags encodeResult;
result = VTCompressionSessionEncodeFrame (vtComp,
buffer,
currentTime,
frameDuration,
NULL, // frameProperties
writerInput, // opaque context to callback
&encodeResult);
显然,您需要检查状态和返回值,但这应该让您找到正确的方向。
关于ios - 在 WWDC2014 中使用 VTCompressionSession,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31467571/