H.264码流分析
Posted crema_h
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了H.264码流分析相关的知识,希望对你有一定的参考价值。
目录
前言
H264视频压缩算法现在无疑是所有视频压缩技术中使用最广泛,最流行的。随着 x264/openh264以及ffmpeg等开源库的推出,大多数使用者无需再对H264的细节做过多的研究,这大降低了人们使用H264的成本。
H264压缩技术主要采用了以下几种方法对视频数据进行压缩。包括:
帧内预测压缩:解决的是空域数据冗余问题。
帧间预测压缩(运动估计与补偿):解决的是时域数据冗徐问题。
整数离散余弦变换(DCT):将空间上的相关性变为频域上无关的数据然后进行量化。
CABAC压缩
经过压缩后的帧分为:I帧,P帧和B帧:
I帧:关键帧,采用帧内压缩技术。
P帧:向前参考帧,在压缩时,只参考前面已经处理的帧。采用帧音压缩技术。
B帧:双向参考帧,在压缩时,它即参考前而的帧,又参考它后面的帧。采用帧间压缩技术。
除了I/P/B帧外,还有图像序列GOP。
GOP:两个I帧之间是一个图像序列,在一个图像序列中只有一个I帧。如下图所示:
一、实验内容
选择一个.mp4或者.264文件。
在码流分析仪软件中打开该文件,从几个层次进行分析:
- 分析SPS和PPS里都包含哪些主要的信息,给出参数值。(例如分辨率、帧率、GOP结构等等)
- 以一个GOP为例,分析如下信息:
- 每个图像帧的类型及所用的编码比特数、QP值;并以图像帧号为横坐标、每帧所用比特数为纵坐标画出曲线图;以图像帧号为横坐标、每帧所用QP为纵坐标画出曲线图。
- 以第一个I帧作为分析对象,基于该帧图像的空间特性,分析每个宏块所采用的编码类型及其比例。
- 以第一个P帧作为分析对象,基于该帧图像的空间和时间特性,分析每个宏块所采用的编码类型及其比例。
- 以某一个B帧作为分析对象,基于该帧图像的空间和时间特性,分析每个宏块所采用的编码类型及其比例。
二、实验分析
1.SPS和PPS
使用H264.Visa打开test.mp4,可看见文件总体信息,为YUV420模式
- SPS
序列参数集SPS(Sequence parameter set): 主要保存了一组编码视频序列(Coded Video Sequence)的全局参数。所谓的编码视频序列即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列。而每一帧的编码后数据所依赖的参数保存于图像参数集(PPS)中。一般情况SPS和PPS的NAL Unit通常位于整个码流的起始位置。NAL 类型为7时,表示该Unit内保存的数据类型为SPS(Sequence Parameter Set)。
profile_idc | 标识当前H.264码流的profile。H.264中定义了三种常用的档次profile,基准档次(baseline profile)、主要档次(main profile)、 扩展档次(extended profile)。 在新版的标准中,还包括了High、High 10、High 4:2:2、High 4:4:4、High 10 Intra、High 4:2:2 Intra等,每一种都由不同的profile_idc表示。本视频为100,即High Profile。 |
level_idc | 标识当前码流的Level。编码的Level定义了某种条件下的最大视频分辨率、最大视频帧率等参数,码流所遵从的level由level_idc指定,本视频为31,对应码流级别如下: |
seq_parameter_set_id | 表示当前的序列参数集的id。通过该id值,图像参数集pps可以引用其代表的sps中的参数。 |
log2_max_frame_num_minus4 | 用于计算MaxFrameNum的值。计算公式为MaxFrameNum = 2^(log2_max_frame_num_minus4+4)。MaxFrameNum是frame_num的上限值,frame_num是图像序号的一种表示方法,在帧间编码中常用作一种参考帧标记的手段。 |
MaxFrameNum | frame_num的上限值,frame_num是图像序号的一种表示方法,在帧间编码中常用作一种参考帧标记的手段。 |
pic_order_cnt_type | 表示解码picture order count(POC)的方法。POC是另一种计量图像序号的方式,与frame_num有着不同的计算方法。该语法元素的取值为0、1或2。 |
log2_max_pic_order_cnt_lsb_minus4 | 用于计算MaxPicOrderCntLsb的值,该值表示POC的上限。计算方法为MaxPicOrderCntLsb = 2^(log2_max_pic_order_cnt_lsb_minus4 + 4)。 |
max_num_ref_frames | 参考帧的最大数目 |
pic_width_in_mbs_minus1 | 用于计算图像的宽度。单位为宏块个数,图像实际宽度: frame_width = 16 × (pic_width_in_mbs_minus1 + 1) |
pic_height_in_map_units_minus1 | 度量视频中一帧图像的高度。PicHeightInMapUnits并非图像明确的以像素或宏块为单位的高度,而需要考虑该宏块是帧编码或场编码。PicHeightInMapUnits的计算方式为: PicHeightInMapUnits = pic_height_in_map_units_minus1 + 1 |
frame_mbs_only_flag | 标识位,说明宏块的编码方式。当该标识位为0时,宏块可能为帧编码或场编码;该标识位为1时,所有宏块都采用帧编码。标识位取值为0时PicHeightInMapUnits表示一场数据按宏块计算的高度,为1时表示一帧数据按宏块计算的高度。 按照宏块计算的图像实际高度FrameHeightInMbs计算方法: FrameHeightInMbs = ( 2 − frame_mbs_only_flag ) * PicHeightInMapUnits |
vui_parameters_present_flag | 标识位,说明SPS中是否存在VUI信息。 |
- PPS
PPS(Picture Paramater Set):图像参数集。通常情况下,PPS类似于SPS,在H.264的裸码流中单独保存在一个NAL Unit中,只是PPS NAL Unit的nal_unit_type值为8;而在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中。
pic_parameter_set_id | 当前PPS的id。某个PPS在码流中会被相应的slice引用,slice引用PPS的方式就是在Slice header中保存PPS的id值。该值的取值范围为[0,255]。 |
seq_parameter_set_id | 当前PPS所引用的激活的SPS的id。通过这种方式,PPS中也可以取到对应SPS中的参数。该值的取值范围为[0,31]。 |
entropy_coding_mode_flag | 熵编码模式标识,该标识位表示码流中熵编码/解码选择的算法。对于部分语法元素,在不同的编码配置下,选择的熵编码方式不同。 |
bottom_field_pic_order_in_frame_present_flag | 标识位,用于表示另外条带头中的两个语法元素delta_pic_order_cnt_bottom和delta_pic_order_cn是否存在的标识。这两个语法元素表示了某一帧的底场的POC的计算方法。 |
num_slice_groups_minus1 | 某一帧中slice group的个数。当该值为0时,一帧中所有的slice都属于一个slice group。slice group是一帧中宏块的组合方式,定义在协议文档的3.141部分。 |
num_ref_idx_l0_default_active_minus1、num_ref_idx_l0_default_active_minus1 | 当Slice Header中的num_ref_idx_active_override_flag标识位为0时,P/SP/B |
weighted_pred_flag | 标识位,表示在P/SP slice中是否开启加权预测。 |
weighted_bipred_idc | 表示在B Slice中加权预测的方法,取值范围为[0,2]。0表示默认加权预测,1表示显式加权预测,2表示隐式加权预测。 |
pic_init_qp_minus26和pic_init_qs_minus26 | 初始的量化参数。实际的量化参数由该参数、slice header中的slice_qp_delta/slice_qs_delta计算得到。 |
chroma_qp_index_offset | 用于计算色度分量的量化参数,取值范围为[-12,12]。 |
deblocking_filter_control_present_flag | 标识位,用于表示Slice header中是否存在用于去块滤波器控制的信息。当该标志位为1时,slice header中包含去块滤波相应的信息;当该标识位为0时,slice header中没有相应的信息。 |
redundant_pic_cnt_present_flag | 标识位,用于表示Slice header中是否存在redundant_pic_cnt语法元素。当该标志位为1时,slice header中包含redundant_pic_cnt;当该标识位为0时,slice header中没有相应的信息。 |
2.以一个GOP为例分析视频信息
用Elecard StreamEye Tools打开测试视频
将视频信息导出为csv文件
- 以图像帧号为横坐标、每帧所用比特数为纵坐标画出曲线图
以第一个GOP为例,由码流分析仪内容易知一个GOP组为250帧
- 以第一个I帧作为分析对象,基于该帧图像的空间特性,分析每个宏块所采用的编码类型及其比例
I帧均采用帧内预测编码,共有920个宏块。颜色变化不大的地方大多采用16×16帧内预测,但在颜色变化大(如背景与人物衔接的边缘),量化等级更高,为I帧4×4预测。由于该帧没有前参考帧,没有使用到运动矢量。
每个宏块大致信息如图:
采用了不同的15种的编码类型,占比如下图:
- 以第一个P帧作为分析对象,基于该帧图像的空间和时间特性,分析每个宏块所采用的编码类型及其比例
第一个P帧的顺序为第4位,在两个B帧之后
黄色为skip宏块,表示这一帧的数据内容与前一帧相同,跳过不编码,蓝色是采用前向预测编码的宏块。
可看出运动矢量主要集中在面部,面部有些许变化,背景变化很小。
共采用不同的12种的编码类型,前向预测的宏块数量较多
- 以第一个B帧作为分析对象,基于该帧图像的空间和时间特性,分析每个宏块所采用的编码类型及其比例
黄色为skip宏块,表示这一帧的数据内容与前一帧相同,跳过不编码,蓝色是采用前向预测编码的宏块。运动矢量依旧大部分存在于面部。
该帧为双向预测编码帧,前后向的帧都有参考,宏块有920个,采用了7种不同的编码类型,skip的宏块数量较多。
H.264码流打包分析
以上是关于H.264码流分析的主要内容,如果未能解决你的问题,请参考以下文章