【数据压缩(十)】H264文件分析1

一、实验要求

  1. 选择一个.mp4或者.264文件。
  2. 在码流分析仪软件中打开该文件,从几个层次进行分析:
    (1)分析SPS和PPS里都包含哪些主要的信息,给出参数值。(例如分辨率、帧率、GOP结构等等)
    (2)以一个GOP为例,分析如下信息:
     每个图像帧的类型及所用的编码比特数、QP值;并以图像帧号为横坐标、每帧所用比特数为纵坐标画出曲线图;以图像帧号为横坐标、每帧所用QP为纵坐标画出曲线图。
     以第一个I帧作为分析对象,基于该帧图像的空间特性,分析每个宏块所采用的编码类型及其比例。
     以第一个P帧作为分析对象,基于该帧图像的空间和时间特性,分析每个宏块所采用的编码类型及其比例。
     以某一个B帧作为分析对象,基于该帧图像的空间和时间特性,分析每个宏块所采用的编码类型及其比例。

二、实验步骤

本次实验选择老师提供的demo.mp4文件举例分析。
在这里插入图片描述

1、分析SPS

在H.264标准协议中规定了多种不同的NAL Unit类型,其中类型7表示该NAL Unit内保存的数据为Sequence Paramater Set。在H.264的各种语法元素中,SPS中的信息至关重要。如果其中的数据丢失或出现错误,那么解码过程很可能会失败。SPS及后续将要讲述的图像参数集PPS在某些平台的视频处理框架(比如iOS的VideoToolBox等)还通常作为解码器实例的初始化信息使用。

SPS即Sequence Paramater Set,又称作序列参数集。SPS中保存了一组编码视频序列(Coded video sequence)的全局参数。所谓的编码视频序列即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列。而每一帧的编码后数据所依赖的参数保存于图像参数集中。一般情况SPS和PPS的NAL Unit通常位于整个码流的起始位置。但在某些特殊情况下,在码流中间也可能出现这两种结构,主要原因可能为:

  • 解码器需要在码流中间开始解码;
  • 编码器在编码的过程中改变了码流的参数(如图像分辨率等);

在做视频播放器时,为了让后续的解码过程可以使用SPS中包含的参数,必须对其中的数据进行解析。

用H264Visa.exe分析软件打开mp4文件并查看SPS。
在这里插入图片描述

其中的每一个语法元素及其含义如下:

(1) profile_idc

标识当前H.264码流的profile。我们知道,H.264中定义了三种常用的档次profile:

基准档次:baseline profile;

主要档次:main profile;

扩展档次:extended profile;

在H.264的SPS中,第一个字节表示profile_idc,根据profile_idc的值可以确定码流符合哪一种档次。判断规律为:

profile_idc = 66 → baseline profile;

profile_idc = 77 → main profile;

profile_idc = 88 → extended profile;

在新版的标准中,还包括了High、High 10、High 4:2:2、High 4:4:4、High 10 Intra、High
4:2:2 Intra、High 4:4:4 Intra、CAVLC 4:4:4 Intra等,每一种都由不同的profile_idc表示。

在我们实验码流中,profile_idc = 0x42 = 66,因此码流的档次为baseline profile。

constraint_set0_flag ~ constraint_set5_flag是在编码的档次方面对码流增加的其他一些额外限制性条件。

(2) level_idc

标识当前码流的Level。编码的Level定义了某种条件下的最大视频分辨率、最大视频帧率等参数,码流所遵从的level由level_idc指定。

当前码流中,level_idc = 0x1e = 31,因此码流的级别为3.1。

(3) seq_parameter_set_id

表示当前的序列参数集的id。通过该id值,图像参数集pps可以引用其代表的sps中的参数。

当前码流中,seq_parameter_set_id = 0,因此当前的序列参数集的id = 0。

(4) log2_max_frame_num_minus4

用于计算MaxFrameNum的值。计算公式为MaxFrameNum = 2^(log2_max_frame_num_minus4 +
4)。MaxFrameNum是frame_num的上限值,frame_num是图像序号的一种表示方法,在帧间编码中常用作一种参考帧标记的手段。

当前码流中,log2_max_frame_num_minus4 = 4,故MaxFrameNum = 2^(4 + 4) = 256。

(5) pic_order_cnt_type

表示解码picture order count(POC)的方法。POC是另一种计量图像序号的方式,与frame_num有着不同的计算方法。该语法元素的取值为0、1或2。

当前码流中,pic_order_cnt_type = 2。

(6) num_ref_frames

用于表示参考帧的数目。

当前码流中,num_ref_frames = 2。

(7) gaps_in_frame_num_value_allowed_flag

标识位,说明frame_num中是否允许不连续的值。

当前码流中,gaps_in_frame_num_value_allowed_flag = 0,说明不允许不连续的值。

(8) pic_width_in_mbs_minus1

用于计算图像的宽度。单位为宏块个数,因此图像的实际宽度为:
frame_width = 16 × (pic_width_in_mbs_minus1 + 1);

当前码流中,pic_width_in_mbs_minus1 = 53,故frame_width = 16 × (53 + 1) = 864。

在这里插入图片描述
这里计算得出的帧宽度和属性中所查到的帧宽度并不相等,但原因尚未可知,待解决。

(9) pic_height_in_map_units_minus1

使用PicHeightInMapUnits来度量视频中一帧图像的高度。PicHeightInMapUnits并非图像明确的以像素或宏块为单位的高度,而需要考虑该宏块是帧编码或场编码。PicHeightInMapUnits的计算方式为:
PicHeightInMapUnits = pic_height_in_map_units_minus1 + 1;

当前码流中,pic_height_in_map_units_minus1 = 29,故PicHeightInMapUnits = 29 + 1 = 30。

(10) frame_mbs_only_flag

标识位,说明宏块的编码方式。当该标识位为0时,宏块可能为帧编码或场编码;该标识位为1时,所有宏块都采用帧编码。根据该标识位取值不同,PicHeightInMapUnits的含义也不同,为0时表示一场数据按宏块计算的高度,为1时表示一帧数据按宏块计算的高度。

按照宏块计算的图像实际高度FrameHeightInMbs的计算方法为:
FrameHeightInMbs = ( 2 − frame_mbs_only_flag ) * PicHeightInMapUnits

因此图像的实际高度frame_height的计算方法为:
frame_height = 16 × FrameHeightInMbs

当前码流中,frame_mbs_only_flag = 1,PicHeightInMapUnits = 30,故FrameHeightInMbs = ( 2 − 1 ) * 30 = 30。
因此图像的实际高度为:frame_height = 16 × 30 =480

在这里插入图片描述
可以看到与属性中的帧高度相同。

(11) direct_8x8_inference_flag

标识位,用于B_Skip、B_Direct模式运动矢量的推导计算。

当前码流中,direct_8x8_inference_flag = 1

(12) frame_cropping_flag

标识位,说明是否需要对输出的图像帧进行裁剪。

当前码流中,frame_cropping_flag = 1即需要对输出的图像帧进行裁剪。

(13) vui_parameters_present_flag

标识位,说明SPS中是否存在VUI信息。

当前码流中,vui_parameters_present_flag = 1即SPS中存在VUI信息。

2、分析PPS

除了序列参数集SPS之外,H.264中另一重要的参数集合为图像参数集Picture Paramater Set(PPS)。通常情况下,PPS类似于SPS,在H.264的裸码流中单独保存在一个NAL Unit中,只是PPS NAL Unit的nal_unit_type值为8;而在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中。

用H264Visa.exe分析软件打开mp4文件并查看PPS。
在这里插入图片描述
其中的每一个语法元素及其含义如下:

(1) pic_parameter_set_id

表示当前PPS的id。某个PPS在码流中会被相应的slice引用,slice引用PPS的方式就是在Slice header中保存PPS的id值。该值的取值范围为[0,255]。

当前码流中,pic_parameter_set_id = 0即当前PPS的id为0。

(2) seq_parameter_set_id

表示当前PPS所引用的激活的SPS的id。通过这种方式,PPS中也可以取到对应SPS中的参数。该值的取值范围为[0,31]。

当前码流中,seq_parameter_set_id = 0即当前PPS所引用的激活的SPS的id为0。

(3) entropy_coding_mode_flag

熵编码模式标识,该标识位表示码流中熵编码/解码选择的算法。对于部分语法元素,在不同的编码配置下,选择的熵编码方式不同。例如在一个宏块语法元素中,宏块类型mb_type的语法元素描述符为“ue(v) | ae(v)”,在baseline profile等设置下采用指数哥伦布编码,在main profile等设置下采用CABAC编码。

标识位entropy_coding_mode_flag的作用就是控制这种算法选择。当该值为0时,选择左边的算法,通常为指数哥伦布编码或者CAVLC;当该值为1时,选择右边的算法,通常为CABAC。

当前码流中,entropy_coding_mode_flag = 0即选择通常为哥伦布编码或者CAVLC。

(4)pic_order_present_flag

POC的三种计算方法在片层还各需要用一些句法元素作为参数,本句法元素等于1时表示在片头会有句法元素指明这些参数;本句法元素等于0时,表示片头不会给出这些参数,这些参数使用默认值。

当前码流中,pic_order_present_flag = 0即片头不会给出这些参数,这些参数使用默认值。

(5) num_slice_groups_minus1

表示某一帧中slice group的个数。当该值为0时,一帧中所有的slice都属于一个slice group。slice group是一帧中宏块的组合方式。

当前码流中,num_slice_groups_minus1 = 0即此帧中所有的slice都属于一个slice group。

(6) 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 slice的语法元素num_ref_idx_l0_active_minus1和num_ref_idx_l1_active_minus1的默认值。

当前码流中,二者默认值为:num_ref_idx_l0_active_minus1 = 0,num_ref_idx_l1_active_minus1 = 1

(7) weighted_pred_flag

标识位,表示在P/SP slice中是否开启加权预测。

当前码流中,weighted_pred_flag = 0即不开启加权预测。

(8) weighted_bipred_idc

表示在B Slice中加权预测的方法,取值范围为[0,2]。0表示默认加权预测,1表示显式加权预测,2表示隐式加权预测。

当前码流中,weighted_bipred_idc = 0即默认加权预测。

(9) pic_init_qp_minus26和pic_init_qs_minus26

表示初始的量化参数。实际的量化参数由该参数、slice header中的slice_qp_delta/slice_qs_delta计算得到。

当前码流中,pic_init_qp_minus26 = 0,pic_init_qs_minus26 = 0。

(10) chroma_qp_index_offset

用于计算色度分量的量化参数,取值范围为[-12,12]。

当前码流中,chroma_qp_index_offset = 0。

(11) deblocking_filter_control_present_flag

标识位,用于表示Slice header中是否存在用于去块滤波器控制的信息。当该标志位为1时,slice header中包含去块滤波相应的信息;当该标识位为0时,slice header中没有相应的信息。

当前码流中,deblocking_filter_control_present_flag = 1即slice header中包含去块滤波器相应的信息。

(12) constrained_intra_pred_flag

若该标识为1,表示I宏块在进行帧内预测时只能使用来自I和SI类型宏块的信息;若该标识位0,表示I宏块可以使用来自Inter类型宏块的信息。

当前码流中,constrained_intra_pred_flag = 0即I宏块可以使用来自Inter类型宏块的信息。

(13) redundant_pic_cnt_present_flag

标识位,用于表示Slice header中是否存在redundant_pic_cnt语法元素。当该标志位为1时,slice header中包含redundant_pic_cnt;当该标识位为0时,slice header中没有相应的信息。

当前码流中,redundant_pic_cnt_present_flag = 0即slice header中没有redundant_pic_cnt相应的信息。

3、分析一个GOP

3.1 帧类型及所用比特数

运用分析软件将帧类型和所用编码比特数生成为csv文件,并在其中以帧号为横坐标,每帧所用比特数为纵坐标作图如下:
在这里插入图片描述

3.2 第一个I帧

在这里插入图片描述
在这里插入图片描述
从信息中可以读出:

  1. 该帧每个宏块所用的平均编码比特数为166.599bits,QP(量化参数)值为26.000。
  2. 该帧为I帧,所有编码类型均为帧内预测编码。

3.3 第一个P帧

在这里插入图片描述
在这里插入图片描述
从信息中可以读出:

  1. 该帧每个宏块所用的平均编码比特数为3.078bits,QP(量化参数)值为26.000。
  2. 该帧为P帧,编码类型包括帧内预测和前向预测。数量比为10:1610;总比特数比为753:4234。

三、实验结论

  1. 与我们所掌握的知识一样,I帧采用帧间预测,P帧采用前向预测和帧间预测。
  2. 一个GOP中虽然I帧只有一帧,但占用了绝大多数比特。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值