通过前面的分析,我们可以看出常规情况下,是将视频以帧的单位进行处理,比如I帧,P帧,B帧等。
但是这些帧是如何以文件方式保存的呢,这节我们主要对H264的保存方式作一个了解。
一帧图片通过编码后,会编码成一个片或多个片slice。但是为什么会有图像切片,原因如下
(1)鲁棒性良好,把一张图片分成一个个独立的slice,在解码时遇到错误,也可以实现再同步,减少错误蔓延,而代价仅仅是失去了一个slice。
(2)匹配MTU(Maximum Transmission Unit)大小,这涉及到网络层的概念,网络上发包时,每个包的大小受到限制,把图像分割成slice可以减小打包的大小。
(3)并行处理,由于每个slice相互独立的缘故,编码、解码以至环路滤波均可以并行处理,加快处理速度,提高效率。
slice切片以NALU行式保存,如下:在存储过程中,一个切片前面还会对应一个NALU头部
图1 切片以NALU方式保存
h264的文件序列如下
图2 文件保存方式
RBSP叫原始字节序列负荷:封装于网络所抽象单元的数据。
一般情况下,一帧图像包括多个切片,一个切片又包括切片头和切片数据,一个切片数据是由多个宏块Macroblock构成,宏块又包括宏块类型、预测类型、CPB、QP和宏块数据,而宏块数据是就是YUV的颜色分量。h264是以NALU形式保存,保存方式如图1和图2所示。另外一帧视频的细节是怎样的,可以查看下图的分解步骤。
图3 一帧图像由宏观到微观描述
下面的图片是h264的码流分层结构的具体细节
在一个h264视频中,最前面的数据是起始码,起始码是在NALU头部之前,假如NALU对应的Slice为一帧的开始,用十六进制00,00,00,01四个字节表示,否则用00,00,01的三个字节表示。另外在编码中,每遇到两个00 00 就会在其后插入一个03字节,保证干扰起始码的确认。在解码过程删除03字节。
最后描述的是视频序列,图像,切片,宏块,子块之前的关系。如下图所示
一个h264文件中相应的存储方式图如下:
上图中的几个概念,描述如下:
序列参数集SPS:包括一个图像序列的所有信息,即两个 IDR 图像间的所有图像信息,如图像尺寸、视频格式等
picture参数集PPS:包括一个图像的所有分片的所有相关信息, 包括图像类型、序列号等,解码时某些序列号的丢失可用来检验信息包的丢失与否
下面打开一个h264文件,可以看出,绿框所描述的是起始码,而箭头所示的67表示SPS开头,68表示PPS开头,65表示I帧的开头
整个文件大概内容如下。而帧内部的slice区分靠000001起始码。