数据压缩试验:H.264码流分析(一二部分)
第一部分:H.264码流分析
H.264介绍
H.264,同时也是MPEG-4第十部分,是由ITU-T视频编码专家组(VCEG)和ISO/IEC动态图像专家组(MPEG)联合组成的联合视频组(JVT,Joint Video Team)提出的高度压缩数字视频编解码器标准。这个标准通常被称之为H.264/AVC(或者AVC/H.264或者H.264/MPEG-4 AVC或MPEG-4/H.264 AVC)。
H.264码流
结构:由一个接一个的 NALU 组成的,而它的功能分为两层,VCL(视频编码层)和 NAL(网络提取层).
VCL:包括核心压缩引擎和块,宏块和片的语法级别定义,设计目标是尽可能地独立于网络进行高效的编码。
NAL:负责将VCL产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别。
下面我们分别对两个部分进行说明。
NAL
在 VCL 数据传输或存储之前,这些编码的 VCL 数据,先被映射或封装进 NAL 单元(以下简称 NALU,Nal Unit) 中。每个 NALU 包括一个原始字节序列负荷(RBSP, Raw Byte Sequence Payload)、一组 对应于视频编码的 NALU 头部信息。RBSP 的基本结构是:在原始编码数据的后面填加了结尾 比特。一个 bit“1”若干比特“0”,以便字节对齐。
NAL解码单元的流程:
下面我们来看一看NAL Header有什么:
占一个字节,由三部分组成forbidden_bit(1bit),nal_reference_bit(2bits)(优先级),nal_unit_type(5bits)(类型)。forbidden_bit:禁止位。
nal_reference_bit:当前NAL的优先级,值越大,该NAL越重要。
nal_unit_type :NAL类型。参见下表:
sps.pps的获取:
获取pps和sps
pps及sps不能从packet获得,而是保存在AVCodecContext的extradata数据域中。
一般情况下,extradata中包含一个sps、一个pps 的nalu。
分析后的sps及pps依然储存在extradata域中,并添加了起始符。
我们以实际文件进行分析:
这里我们使用Sublime Text打开一个h.264编码的mp4文件作如下观察:文件名为envivo
SPS
对于H.264而言,每帧的界定符为00 00 00 01 或者00 00 01。
帧类型有:
NAL_SLICE = 1 非关键帧
NAL_SLICE_DPA = 2
NAL_SLICE_DPB = 3
NAL_SLICE_DPC =4
NAL_SLICE_IDR =5 关键帧
NAL_SEI = 6
NAL_SPS = 7 SPS帧
NAL_PPS = 8 PPS帧
NAL_AUD = 9
NAL_FILLER = 12
从H.264协议文档中可以看出视频宽高涉及到的参数有:pic_width_in_mbs_minus1 pic_height_in_map_units_minus1
宽高可从SPS字段计算得到,公式如下:
Width = (pic_width_in_mbs_minus1+1)16;
Height = (pic_height_in_map_units_minus1+1)16;
被分析文件的SPS读取
点开SPS在右边的分析框架可以见到:
这个分析器我找了好久。有需要可以联系我。
我们还可以获得该图像的视频的采样格式:在这里:
这个chroma_format_idc的意思就是表示他是4:2:0采样的。
剩下的参数我们可以通过这个书中查找参数得到:
以上图片数据来自ITU-T H.264建议书。
PPS
除了序列参数集SPS之外,H.264中另一重要的参数集合为图像参数集Picture Paramater
Set(PPS)。通常情况下,PPS类似于SPS,在H.264的裸码流中单独保存在一个NAL Unit中,只是PPS NAL
Unit的nal_unit_type值为8;而在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中。
在H.264的协议文档中,PPS的结构定义在7.3.2.2节中,具体的结构如下表所示:
被分析文件中的PPS信息的读取
我们仍然用上述文件分析器打开PPS部分:
该文件只有一个PPS。从该PPS中,我们可以看出每一帧编码所用的一些信息:
该视频每一帧编码形式:
编码形式: CABAC(Context-based Adaptive Binary Arithmetic Coding)
基于上下文的自适应二进制算术编码
slice group:所有slice属于一个
支持帧间预测
文件GOP分析
单帧分析
我们用分析软件ESEYE来进行分析:
再看一看所有的:
可以看出,编码出的比特率分布是非常不均的,这势必会为未来的固定网络带宽传输带来一定的影响。
可以看到运动矢量:这里选取的不是第一个i帧,而是随便的一帧。
可以把信息导入到csv文件中:
I帧
第一帧是I帧:
我们通过find按钮找到第一帧:输入0。
这里我们可以看见,其中量化黄色的圆圈比特数更高一点。
可以看到该帧的信息。
接下来我们看一下分区信息:
Partitions打开:
可以看出,该I帧没有使用到帧间编码,该帧完全使用了帧内编码。
除此以外,由于该帧没有前参考帧,没有使用到运动矢量。我们打开运动矢量按钮,和之前没有变化。
B帧
视频的第二帧为B帧。我们知道,B帧的数据量是I、B、P三种数据类型中相对尺寸最小的一种类型,这是因为它支持帧间预测(包括了前向预测、后向预测和前向及后向预测)和帧内预测,以支持最大程度降低数据量。在该帧中,有红色、蓝色、黄色三种编码类型。黄色是B_skip块。它代表了这一帧的数据内容与前一帧相同,跳过不编码。可以看到黄色的Macro Block所占用bit数为0bit,只需要提前使用一些比特进行说明就行。
P帧分析
图像的第五帧是P帧。(在编码时,是按照IPBBB的顺序进行编码,然后进行帧重排)
可以看到运动矢量图:
人物向前走,景物向后退。
矢量十分精准。