软件分析
实验用到的两个软件:
H264Visa(分析图像)
打开程序,选择test.mp4进行分析
Header Info:
1、传输流单位:NAL(网络中传输单位)
2、SPS(Sequence Paramater Set) 序列参数集
profile_idc
:标识当前H.264码流的profile(对视频压缩特性的描述)
在H.264中有三种常用的档次profile:base profile、main profile以及extended profile:
profile_idc = 66 → baseline profile,多应用于实时通信领域;
profile_idc = 77 → main profile,多应用于流媒体领域;
profile_idc = 88 → extended profile;
profile_idc = 100 → high profile,多应用于广电和存储领域。
这里测试视频profile_idc = 100,查阅官方手册可知此时视频的格式是高级
level_idc
:标识当前码流的Level(视频本身特性的描述–码率、分辨率、fps)
编码的Level定义了某种条件下的最大视频分辨率、最大视频帧率等参数,码流所遵从的level由level_idc指定。这里该视频level_idc=31,也就是level=31。对应720p分辨率,如下图所示:
seq_parameter_set_id
:表示当前的序列参数集的ID,取值0~15间。
这里视频序列为0(最开始的视频,我选取了第一帧)
chroma_format_idc
:与亮度取样对应的色度取样。
chroma_format_idc 的值应该在 0到 3 的范围内(包括 0 和 3)。当 chroma_format_idc 不存在时,默认值为 1(色度格式为4:2:0)
bit_depth_luma_minus8
:指亮度比特深度以及亮度量化参数范围的取值偏移。默认 bit_depth_luma_minus8=0。bit_depth_luma_minus8 取值范围应该在 0 到 4 之间(包括 0 和 4)。 该视频的该值为0。
B
i
t
D
e
p
t
h
Y
(
图
像
深
度
)
=
8
+
b
i
t
D
e
p
t
h
L
u
m
a
M
i
n
u
s
8
BitDepthY(图像深度) = 8 + bitDepthLumaMinus8
BitDepthY(图像深度)=8+bitDepthLumaMinus8
Q
p
B
d
O
f
f
s
e
t
Y
(
图
像
量
化
深
度
)
=
6
∗
b
i
t
D
e
p
t
h
L
u
m
a
M
i
n
u
s
8
QpBdOffsetY(图像量化深度) = 6 * bitDepthLumaMinus8
QpBdOffsetY(图像量化深度)=6∗bitDepthLumaMinus8
bit_depth_chroma_minus8
:指色度比特深度以及色度量化参数范围的取值偏移,默认bit_depth_chroma_minus8 = 0。it_depth_chroma_minus8 取值范围应该在 0 到 4 之间(包括 0 和 4)此视频的该值为0。
bitDepthLumaMinus8
:在变换系数解码过程和图像构建过程中是否执行变换旁路操作。当qpprime_y_zero_transform_bypass_flag 没有特别指定时,默认为0。(这里也是没有)
seq_scaling_matrix_present_flag
:默认为0,这里表示不存在序列缩放比例列。
log2_max_frame_num_minus4
:用于计算MaxFrameNum的值,用于计算MaxPicOrderCntLsb的值,该值表示POC的上限。计算方法为:
M
a
x
F
r
a
m
e
N
u
m
=
2
(
l
o
g
2
m
a
x
f
r
a
m
e
n
u
m
m
i
n
u
s
4
+
4
)
MaxFrameNum= 2^ (log2_max_frame_num_minus4+ 4)
MaxFrameNum=2(log2maxframenumminus4+4)
pic_order_cnt_type
:指解码图像顺序的计数方法,此视频的该值为0
log2_max_pic_order_cnt_lsb_minus4
:用于计算MaxPicOrderCntLsb的值,该值表示POC的上限
MaxPicOrderCntLsb= 2^(log2_max_pic_order_cnt_lsb_minus4+ 4)
num_ref_frames
:(类似GOP长度?)规定了可能在视频序列中任何图像帧间预测的解码过程中用到的短期参考帧和长期参考帧、互补参考场对以及不成对的参考场的最大数量。这里是16帧
gaps_in_frame_num_value_allowed_flag
:标识位,说明frame_num中是否允许不连续的值。(这里设置0表示不允许)
当 gaps_in_frame_num_value_allowed_flag 不为 1,即 frame_num 连续的情况下,每个图像的frame_num 由前一个参考帧图像对应的值加 1,着重点是“前一个参考帧”。
frame_num是参考帧特有的,它的主要作用是在该图像被其他图像引用作运动补偿的参考时提供一个标识。但 H.264 在非参考帧图像中也保留这一句法元素,原因是在 POC 的第二种和第三种解码方法中可以通过非参考帧的 frame_num 值计算出他们的 POC 值。
当 gaps_in_frame_num_value_allowed_flag 等于 1,表示如果发生网络阻塞,编码器可以将编码后的若干图像丢弃,而不用另行通知解码器。在这种情况下,解码器必须有机制将缺失的frame_num 及所对应的图像填补,否则后续图像若将运动矢量指向缺失的图像将会产生解码错误。
pic_width_in_mbs_minus1
:计算图像的宽度。单位为宏块个数,因此图像的实际宽度为: 16x(39+1)=640
pic_height_in_map_units_minus1
:计算视频中一帧图像的高度。(这里为22+1)=23宏块。23*16=368
(结合长宽:这里视频的分辨率九尾640x368)
frame_mbs_only_flag
:标识位,说明宏块的编码方式。当该标识位为0时,宏块可能为帧编码或场编码;该标识位为1时,所有宏块都采用帧编码。(这里视频为帧编码)
3、PPS(Picture Paramater Set 图像参数集)
pic_parameter_set_id
: 表示当前图像参数集的ID,当前图片ID为0。
seq_parameter_set_id
: 表示当前PPS对应序列SPS中的ID值,PPS可直接引用Seq-id取到对应SPS中的参数,当前图像序列该值为0。
entropy_coding_mode_flag
:熵编码模式标识,表示码流中熵编码/解码选择的算法,当前码流值为1,即选择CABAC算法。
pic_order_present_flag
: POC的三种计算方法在片层还各需要用一些句法元素作为参数,本句法元素等于1时表示在片头会有句法元素指明这些参数;当前码流中该元素等于0时,表示图像这些参数使用默认值。
num_slice_groups_minus1
: 表示某一帧中slice group的个数。当该值为0时,一帧中所有的slice都属于一个slice group。这里即所有的slice都属于一个slice group。
num_ref_idx_l0_default_active_minus1
: 表示当前参考图像列表的最大参考索引号 (这里为15)
num_ref_idx_active_override_flag
:表示重载PPS中的参考帧队列中实际可用的参考帧的数目。(这里为0表示不重载)
前面图像参数集中我们看到已经出现句法元素num_ref_idx_l0_active_minus1 和num_ref_idx_l1_active_minus1 指定当前参考帧队列中实际可用的参考帧的数目。在片头可以重载这对句法元素,以给某特定图像更大的灵活度。这个句法元素就是指明片头是否会重载,如果该句法元素等于 1,下面会出现新的 num_ref_idx_l0_active_minus1 和num_ref_idx_l1_active_minus1 值。
weighted_pred_flag
:标识位,表示在P/SP slice中是否开启加权预测。当前码流中该值为1,则为开启
weighted_bipred_idc
:表示是否在B Slice中使用加权预测的方法,0表示默认加权预测,1表示显式加权预测,2表示隐式加权预测。当前码流的该值=2,表示隐式加权,取值范围为[0,2]
pic_init_qp_minus26
:表示初始的量化参数,这里为0
chroma_qp_index_offset
: 用于计算色度分量的量化参数,观察上图可知该值为-2
deblocking_filter_control_present_flag
:表示Slice header中是否存在用于去块滤波器控制的信息,0表示没有相应的信息, 1表示包含去块滤波器相应的信息。
constrained_intra_pred_flag
:值为0,表示I宏块可以使用来自Inter类型宏块的信息。
redundant_pic_cnt_present_flag
: 表示Slice header中是否存在redundant_pic_cnt语法元素。当该标识位为0时,slice header中没有相应的信息。
transform_8x8_mode_flag
: 这里为1 表表示正在使用 8x8 变换解码过程
pic_scaling_matrix_present_flag
这里等于 1 表示存在用来修改在序列参数集中指定的缩放比例列表的参数,等于 0 表示用于该图像中的缩放比例列表应等于由序列参数集规定的,默认其值为 0。
分析IBP帧
1、I帧
选取第一帧I帧分析:
选择第一个小宏块,可以看出第一个宏块类型为16*16_2_1_0的宏块
🔑🔑这里QP专门查了一下:
量化参数QP是量化步长Qstep的序号。
对于亮度(Luma)编码,量化步长Qstep共有52个值,QP取值0-51
对于色度(Chroma)编码,QP的取值0-39。量化参数是25
QP越大,量化步长越大,最终图像质量越差;QP越小,量化越精细,图像质量越好
这里量化步长为25(较大,说明不是细节纹理区域)
点击查看宏块,发现非常明显的是用黑色圈画出来的地方,mb_type块非常大采用的是16x16宏块(这部分纹理细节变化不大,不需要精细搜索)
黄色部分块非常非常小,采用的是4x4宏块也表示这里纹理细节变化大,需要精细搜索
2、B帧
选取第二帧进行查看:
帧内所有帧都为B帧(蓝色表示),也就是所有帧都是双向预测类型帧。
而且在所有的帧类型中,出现了名叫B_skip的宏块类型,这个类型表示无运动矢量残差,直接利用前、后向MV得到像素预测值。像素重构值=像素预测值,这里也可说明这些位置的预测误差接近于0。
加入运动矢量查看:
发现图像下方有明显的镜头上移动趋势~
这里也稍微提醒一下:运动矢量向哪里移动,镜头就像那里移动
3、P帧
这里绿色的表示为P帧编码,值得注意的是,图像里面还有帧内编码类型~(可以理解为,实在找不到类似的图像了,只能进行帧内编码)
不过大部分还是以P帧为主
这里P帧宏块大小变化很小,几乎没什么变换~都在16*16附近。
通过summary也可以看出来,这里P帧的平均比特率为10.870,平均量化参数为30.558
总结
- P帧内也会存在帧内编码帧(I帧类型)
- 图片纹理越细腻,采用的宏块就越小,寻找就越精细
- B帧的平均比特率最少(B_Skip出现的机率非常大,也表明这样能很好的降低传输数据量)
Eseye_u(分析图像序列)
GOP:我们熟知的GOP结构IBPPBPP…
一个GOP包含多个不同类型的图像帧,是后期我们编辑、存取和压缩编码的基本单元。
第一步:找到GOP中的第一个I帧(不用怀疑,就是红色那个,bit数据量最大的那个)
当前为序号为1的GOP组,该帧为第30帧,也就意味着,前面有29帧图像(一个GOP结构有30帧图像)序号从0开始编
0~29:第一个GOP组
这里也可以看出来其实编码时候得到的码率是非常不均匀的,I帧的数据量会很大,相比于B帧P帧差距非常非常大,所以为了传输到CBR信道,缓冲区是非常有必要的。
这里利用tools也能查看码率的平均值
将数据导出为csv格式:
GOP结构为:IPBPBPB…(这里也可以看出来,这肯定是一个点播序列,否则不会允许出现这么多B帧)
第一个GOP结构:非常奇怪~I帧的数据量反而最小(存疑?)
第二个GOP就非常正常,很符合我们所学的例子:
I帧的数据量非常大,B帧数据量最小~
总结
- 图像的数据量: I>P>B
- 增大GOP或提高GOP中P/B帧的占比,能够提高压缩比,降低码率。
- 在码率一定的条件下,GOP越大,图像质量越好(P/B帧的比重更大);在图像质量一定的条件下,GOP越大,码率越低。
- 正是因为观察到的严重码率不均现象,才引入了buffer 缓存器的概念:
这里简单用一张图说一下: