编码分为硬编码和软编码。
硬解码:由显卡核心GPU来对高清视频进行解码工作,CPU占用率很低,画质效果比软解码略差一点,需要对播放器进行设置。
优点:播放流畅、低功耗
缺点:受视频格式限制、功耗大、画质没有软解码好
软解码:由CPU负责解码进行播放
优点:不受视频格式限制、画质略好于硬解
缺点:会占用过高的资源、对于高清视频可能没有硬解码流畅(主要看CPU的能力)
下面我们具体说说硬解码吧
苹果在iOS 8.0系统之前,没有开放系统的硬件编码解码功能,不过Mac OS系统一直有,被称为Video ToolBox的框架来处理硬件的编码和解码,终于在iOS 8.0后,苹果将该框架引入iOS系统。
由此,开发者便可以在iOS里面,调用Video Toolbox框架提供的接口,来对视频进行硬件编解码的工作,为VOIP视频通话,视频流播放等应用的视频编解码提供了便利。
(PS:按照苹果WWDC2014 513《direct access to media encoding and decoding》的描述,苹果之前提供的AVFoundation框架也使用硬件对视频进行硬编码和解码,但是编码后直接写入文件,解码后直接显示。Video Toolbox框架可以得到编码后的帧结构,也可以得到解码后的原始图像,因此具有更大的灵活性做一些视频图像处理。)
一,VideoToolbox基本数据结构。
Video Toolbox视频编解码前后需要应用的数据结构进行说明。
(1)CVPixelBuffer:编码前和解码后的图像数据结构。
(2)CMTime、CMClock和CMTimebase:时间戳相关。时间以64-bit/32-bit的形式出现。
(3)CMBlockBuffer:编码后,结果图像的数据结构。
(4)CMVideoFormatDescription:图像存储方式,编解码器等格式描述。
(5)CMSampleBuffer:存放编解码前后的视频图像的容器数据结构。
图1.1视频H264编解码前后数据结构示意图
如图1.1所示,编解码前后的视频图像均封装在CMSampleBuffer中,如果是编码后的图像,以CMBlockBuffe方式存储;解码后的图像,以CVPixelBuffer存储。CMSampleBuffer里面还有另外的时间信息CMTime和视频描述信息CMVideoFormatDesc。
二,硬解码使用方法。
通过如图2.1所示的一个典型应用,来说明如何使用硬件解码接口。该应用场景是从网络处传来H264编码后的视频码流,最后显示在手机屏幕上。
1,将H264码流转换成编码前的CMSampleBuffer。
由图1.1所示,解码前的CMSampleBuffer = CMTime + FormatDesc + CMBlockBuffer。需要从H264的码流里面提取出以上的三个信息。最后组合成CMSampleBuffer,提供给硬解码接口来进行解码工作。
H264的码流由NALU单元组成,NALU单元包含视频图像数据和H264的参数信息。其中视频图像数据就是CMBlockBuffer,而H264的参数信息则可以组合成FormatDesc。具体来说参数信息包含SPS(Sequence Parameter Set)和PPS(Picture Parameter Set)。图2.2显示一个H264码流的结构。
图2.2 H264码流结构
(1)提取sps和pps生成format description。
a,每个NALU的开始码是0x00 00 01,按照开始码定位NALU。
b,通过类型信息找到sps和pps并提取,开始码后第一个byte的后5位,7代表sps,8代表pps。
c,CMVideoFormatDescriptionCreateFromH264ParameterSets函数来构建CMVideoFormatDescriptionRef。
(2)提取视频图像数据生成CMBlockBuffer。
a,通过开始码,定位到NALU。
b,确定类型为数据后,将开始码替换成NALU的长度信息(4 Bytes)。
c,CMBlockBufferCreateWithMemoryBlock接口构造CMBlockBufferRef。
(3)根据需要,生成CMTime信息。(实际测试时,加入time信息后,有不稳定的图像,不加入time信息反而没有,需要进一步研究,这里建议不加入time信息)
根据上述得到CMVideoFormatDescriptionRef、CMBlockBufferRef和可选的时间信息,使用CMSampleBufferCreate接口得到CMSampleBuffer数据这个待解码的原始的数据。见下图的H264数据转换示意图。