Demo地址

在此之前我们通常使用的FFmpeg多媒体库,利用CPU来进行视频的编解码,占用CPU资源,效率低下,俗称软编解码.而苹果在2014年的iOS8中,开放了VideoToolbox.framwork框架,此框架使用GPU或专用的处理器来进行编解码,俗称硬编解码.而此框架在此之前只有MAC OS系统中可以使用,在iOS作为私有框架.终于苹果在iOS8.0中得到开放引入.

2014年的WWDCDirect Access to Video Encoding and Decoding中,苹果介绍了使用videoToolbox硬编解码.
使用硬编解码有几个优点:

  • 提高性能;
  • 增加效率;
  • 延长电量的使用

对于编解码,AVFoundation框架只有以下几个功能:

  1. 直接解压后显示;
  2. 直接压缩到一个文件当中;

而对于Video Toolbox,我们可以通过以下功能获取到数据,进行网络流传输等多种保存:

  1. 解压为图像的数据结构;
  2. 压缩为视频图像的容器数据结构.

    一、videoToolbox的基本数据

    Video Toolbox视频编解码前后需要应用的数据结构进行说明。

  3. CVPixelBuffer:编码前和解码后的图像数据结构。此内容包含一系列的CVPixelBufferPool内容

  4. CMTime、CMClock和CMTimebase:时间戳相关。时间以64-bit/32-bit的形式出现。

  5. pixelBufferAttributes:字典设置.可能包括Width/height、pixel format type、• Compatibility (e.g., OpenGL ES, Core Animation)

  6. CMBlockBuffer:编码后,结果图像的数据结构。

  7. CMVideoFormatDescription:图像存储方式,编解码器等格式描述。

  8. (CMSampleBuffer:存放编解码前后的视频图像的容器数据结构。

  9. CMClock

  10. CMTimebase: 关于CMClock的一个控制视图,包含CMClock、时间映射(Time mapping)、速率控制(Rate control)


二、采集视频数据可知,我们获取到的数据(CMSampleBufferRef)sampleBuffer为未编码的数据;
图1.1编码前后的数据结构示意图
图1.1
上图中,编码前后的视频图像都封装在CMSampleBuffer中,编码前以CVPixelBuffer进行存储;编码后以CMBlockBuffer进行存储。除此之外两者都包括CMTimeCMVideoFormatDesc.

二、获取已编码数据流进行解码展示(获取编码后的数据进行解码展示)

图2.1
图2.1
通过网络获取已编码的H.264数据流进行MPEG-4处理,通过使用AVSampleBufferDisplayLayer解码获取图像显示到设备上。
图2.2 AVSampleBufferDisplayLayer解码显示
图2.2

2.1. 将获取到的已编码的数据流进行处理成CMSampleBuffer.
图2.3 处理H.264码流
图2.3
由图1.1可知:解码前的图像数据结构$$CMSampleBuffer = CMTime + FormatDesc + CMBlockBuffer$$组成 因此需要从H.264的码流需要以上三个信息组合成CMSampleBuffer.

H.264码流由一系列的NALU单元组成.NALU单元包含视频图像数据(或视频帧片段)和H.264的参数信息。其中视频图像信息数据是CMBlockBuffer,而H.264参数信息可以组合成FormatDesc,包括编码所用的profile,level,图像的宽和高,deblock滤波器等.具体包含第一个NALU的SPS(Sequence Parameter Set)和第二个NALU的PPS(Picture Parameter Set)。

图2.3 H.264组成结构
图2.4

1
2
3
4
5
6
7
8
9
10
* frame的数据可以分为多个slice(片段).
* 每个slice中的数据,在帧内预测只用到自己slice的数据, 与其他slice 数据没有依赖关系。
* NAL 是用来将编码的数据进行大包的。 比如,每一个slice 数据可以放在NAL 包中。
* I frame 是自己独立编码,不依赖于其他frame 数据。
* P frame 依赖 I frame 数据。
* B frame 依赖 I frame, P frame 或其他 B frame 数据。
* H.264码流的第三个NALU是IDR(即时解码器刷新),IDR图像都是I帧,H.264引入IDR图像为了解码的同步,使错
误不被传播,当解码器解码到IDR图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,
开一个新的序 列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不
会使用IDR之前的图像的数据来解码。

1.1 使用CMVideoFormatDescriptionCreateFromH264ParameterSets提取编码的SPS和PPS压缩转换成MPEG—4需要的SPS和PPS,组合成CMVideoFormatDescription
图2.1.1

1
2
3
(1)每个NALU的开始码是3或4字节头:00 00 01 或 00 00 00 01,按开始码可定位NALU;
(2)提取出SPS和PPS,通过获取到的编码流,判断开始码后的第一个byte的后5位,7代表SPS,8代表PPS;
(3)CMVideoFormatDescriptionCreateFromH264ParameterSets函数构建CMVideoFormatDescription.

1.2 获取CMBlockBuffer
图2.1.2

1
2
3
(1)通过开始码,定位到NALU;
(2)确认类型数据将开始码替换为NALU的长度信息(4 Byte)
(3)通过CMBlockBufferCreateWithMemoryBlock接口构造CMBlockBufferRef

1.3 添加CMTime
图2.5