前言
在学习了落影大神的相关博客及WWDC有关编解码的视频后准备总结下所思所得,先写有关硬编码的内容之后会再写关于硬解码的内容.
概念简要
众所周知,我们平时在网络上收看视频会经历视频编码及解码的过程.编码是为了减小视频网络传输消耗的资源,解码是为了将压缩后的视频恢复成可以观看的格式,目前编码大多采用的是H.264规格.
H.264是一种广为认可的编码格式, 包含由一系列NALU组成的码流,这些NALU承载着SPS,PPS,I Frame,P Frame,B Frame信息,其组成如下图图一(图源数据来自WWDC).其中SPS,即Sequence Parameter Set(序列参数集)以及PPS, Picture Parameter Set(图像参数集)在I帧中获取.I帧为关键帧,在序列中处于关键位置,为后面的P帧乃至B帧提供参考对象(编码中有关空间编码与时间编码这里不作赘述).
图一
编码周知
IOS提供了VideoToolbox来处理有关视频编解码内容,其中提供编码作用的是VTCompressionSession,相应解码为VTDecompressionSession.
1.针对编码所需了解的概念:
- CVPixelBuffers :存储未压缩像素缓存
- CMSampleBuffers :存储压缩或未压缩像素缓存
2.编码数据导向流程
将CVPixelBuffers里视讯内容经由VTCompression Session相应编码处理后将编码后的数据保存在CMSampleBuffers,再将其上传网络传输等.如下图图二所示
图二
编码实现
第一:创建VTCompressionSession
利用VTCompressionSessionCreate()创建VTCompressionSession,主要有以下几个参数
- 编码后输出数据尺寸
- 编码格式,如(kCMVideoCodecType_H264)
- PixelBufferAttributes(可选)
- 编码输出回调方法(VTCompressionOutputCallback)
第二:配置VTCompressionSession
利用VTSessionSetProperty() 配置VTCompressionSession相关参数,如:
kVTCompressionPropertyKeyAllowFrameReordering
kVTCompressionPropertyKeyAverageBitRate
kVTCompressionPropertyKeyH264EntropyMode
kVTH264EntropyModeCAVLC/kVTH264EntropyModeCABAC
kVTCompressionPropertyKeyRealTime
kVTCompressionPropertyKey_ProfileLevel
第三:对硬件捕获到的数据进行编码
利用VTCompressionSessionEncodeFrame()对数据进行编码,这里有代码如下,可先从捕捉到的CMSampleBufferRef中获取未压缩的CVImageBufferRef数据,再调用压缩方法进行编码.
注:用 VTCompressionSessionCompleteFrames()方法结束编码.
- (void) encode:(CMSampleBufferRef )sampleBuffer
{
CVImageBufferRef imageBuffer = (CVImageBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer);
// 帧时间,如果不设置会导致时间轴过长。
CMTime presentationTimeStamp = CMTimeMake(frameID++, 1000);
VTEncodeInfoFlags flags;
OSStatus statusCode = VTCompressionSessionEncodeFrame(EncodingSession,
imageBuffer,
presentationTimeStamp,
kCMTimeInvalid,
NULL, NULL, &flags);
if (statusCode != noErr) {
NSLog(@"H264: VTCompressionSessionEncodeFrame failed with %d", (int)statusCode);
VTCompressionSessionInvalidate(EncodingSession);
CFRelease(EncodingSession);
EncodingSession = NULL;
return;
}
NSLog(@"H264: VTCompressionSessionEncodeFrame Success");
}
第四:VTCompressionOutputCallback
功能
VTCompressionOutputCallback 相应函数中主要作用是应实现将编码后得到的 CMSampleBuffers数据转换到H.264基础码流包功能.(咳咳,总感觉这句话还是看看英文的好 ,Converting CMSampleBuffers into H.264 elementary stream packaging).其流程功能如图三图四所示
图三
图四
具体实现
- 转变参数集
利用CMVideoFormatDescriptionGetH264ParameterSetAtIndex()分别将CMVideoFormatDescription中的SPS以及PPS单独获取出来,当然这是针对I帧操作的.
- 更改NAL Unit headers 需要将每个NALU 头部由00 00 80 00 更改为 00 00 01 或00 00 00 01
VTCompressionSession Summary
Creation of VTCompressionSession
Configuring the compressor
Providing CVPixelBuffers to VTCompressionSession
Converting CMSampleBuffers into H.264 elementary stream packaging
这是最后有关VTCompressionSession总结,写的太好,我就不班门弄斧了.