【编解码】从零开始写H264解码器(5) SPS解析-参数含义,伪代码

1.引言

前面我们学会了指数哥伦布解码,翻翻白皮书,依靠这个知识,基本上我们就能一口气解码完SPS,PPS,SEI,Slice Header了。在Slice Data里会出现一些ae(v)类型的熵编码,这个我们后面再看 。
接下来的重点就是,认真的看一下解码出来的每个参数的作用。这些参数在后续的计算YUV的过程中都会起到对应的作用。
首先,我们从SPS开始。

2. SPS

SPS,即sequence parameter set,序列参数集合。
在H264中,具体的图像数据在宏块中传输,但是这些图像所依赖的一些参数,会被汇总到SPS、PPS中,并被赋予较高的优先级,优先保证这些数据包的完整和准确。
基本的参考流程就是,
宏块参考slice数据,slice参考slice头,slice头参考PPS,PPS依赖SPS。
我们可以依次收到多份SPS数据,并按照SPS id将他们保存下来,在后面的参考过程中,如果有参考SPS的id匹配上的,即可以获取对应的数据。
下面我们来翻到白皮书《Rec. ITU-T H.264 (03/2010)》的43页,章节为7.3.2.1.1 Sequence parameter set data syntax, 如下图:
在这里插入图片描述
在这里插入图片描述
可以看出来,在白皮书中,不仅把每个参数的格式列出来,连伪代码都写好了,像是if,for等逻辑全都在。如果不是优化效率,只是要实现功能的需求,基本上按照这个流程往下解参数就可以了。
每个参数的解析方法在上一章,指数哥伦布里已经介绍了,本章我们主要介绍一下SPS 中各个参数的作用。

3. 参数解析

  • profile_idc: profile 级别,大体分为base,main,extend,high四大类。对应不同的功能组合。包含有没有使用CABAC,有没有使用B帧,YUV的格式等等。
    具体对照表格看 这里 的图表.
    profile的对应值如下:
profile_idc含义重要特征
66baseline profileI/P帧,progressive(无交错),CAVLC
77main profileI/P/B/SP/SI帧,progressive(无交错) , CAVLC
88extended profileI/P/B帧,progressive(无交错) + interlaced(交错),CAVLC + CABAC
100High
110High 10
122High 4:2:2
144High 4:4:4

在这里插入图片描述

在这里插入图片描述

  • constraint_set0_flag:强制使用Baseline profile进行编码

  • constraint_set1_flag:强制使用Main profile进行编码

  • constraint_set2_flag:强制使用Extended profile进行编码

  • constraint_set3_flag:配合profile_idc一起控制一些功能的开关

  • constraint_set4_flag:配合profile_idc一起控制一些功能的开关

  • constraint_set5_flag :配合profile_idc一起控制一些功能的开关

  • level_idc:level级别,告知解码器当前码流所需要的资源级别,比如size,帧率在一个什么级别。个人感觉是用于解码器预先分配解码资源(比如开多少内存,开多少线程等等)。
    部分级别说明如下:
    在这里插入图片描述

  • seq_parameter_set_id:本组SPS的id,范围[0,31],用于PPS索引到这组参数。

  • chroma_format_idc :YUV格式,范围[0,3],默认1:yuv420。只有profile达到High422,High444,才支持YUV422和YUV444的格式。
    如下表,从左往右依次是:baseline, extend,mail,high,high10, high422,high444
    在这里插入图片描述

  • separate_colour_plane_flag:针对YUV444使用,把Y,U,V当做三个独立的图像进行编码。

在这里插入图片描述

chroma_format_idcseparate_colour_plane_flagChroma FormatSubWidthCSubHeightC
00monochrome--
10YUV42022
20YUV42221
30YUV44411
31YUV444--
  • bit_depth_luma_minus8:针对high模式,允许设置图像深度大于8bit的情况。
    非high的时候,都是一个字节8bit(0~255)表示一个像素的亮度或色度。
    在这里插入图片描述

  • bit_depth_chroma_minus8:同上

  • qpprime_y_zero_transform_bypass_flag: 这个用的不多,用于指定 变换系数解码时的 旁路操作 是否要在 去块效应滤波之前执行。理解不深,直接上图:
    在这里插入图片描述

  • seq_scaling_matrix_present_flag

  • seq_scaling_list_present_flag : 这两个参数也理解不深。后面有理解了再来写,目前先上图。
    在这里插入图片描述
    在这里插入图片描述

  • log2_max_frame_num_minus4:取值范围[0,12], log2和minus2都是计算方式的前后缀。关键在于 max_frame_num。很明显看出这个表示的是frame_num的max最大值。frame_num使我们在解码过程中会使用到的一个重要变量,表明了解码顺序。

  • pic_order_cnt_type:指定计算pic_order_cnt 的 方式,pic_order_cnt 是图像播放的顺序,也是真实录制的顺序,可以理解为真正的时间轴,不过是一个相对值。pic_order_cnt 有3种计算方式。具体计算方式可以参加毕厚杰《新一代视频压缩编码标准 第二版》7.3节(P181)的流程。

  • log2_max_pic_order_cnt_lsb_minus4:log2和minus4的前后缀是计算方式,主要含义就是 pic_order_cnt的max最大值的lsb,msb是需要解码器自己算的。这个涉及到POC的计算方法。

  • delta_pic_order_always_zero_flag:用于计算POC

  • offset_for_non_ref_pic:取值范围int, 用于计算非参考帧的POC

  • offset_for_top_to_bottom_field,用于计算场的POC

  • num_ref_frames_in_pic_order_cnt_cycle,范围[0,255],用于计算POC

  • offset_for_ref_frame,范围int,用于计算POC

  • max_num_ref_frames : reference frame 的最大值。一般参考图像范围0~MaxDpbSize.

  • gaps_in_frame_num_value_allowed_flag:允许码流中 frame num是不连续的。

  • pic_width_in_mbs_minus1:minus1是后缀,指明图像宽有多少个MB(每个MB是16x16)。这样很容算出图像亮度宽度 = (pic_width_in_mbs_minus1 + 1)* 16。

  • pic_height_in_map_units_minus1:minus1是后缀,指明图像高有多少个map unit(每个map unit是16x16 或 16x32),所以图像高度 = (pic_height_in_map_units_minus1 + 1)* 16或者32。

  • frame_mbs_only_flag:表明是否存在图像场,0代表存在,有场处理起来就比较麻烦。但是从main profile开始就加入了interlace的交错场功能,也算支持比较早。虽然现在用的不多了。

  • mb_adaptive_frame_field_flag:表明是图像帧还是图像场还是帧场自适应。
    以上两个参数配合,可以推断出图像的帧场属性

frame_mbs_only_flag = 0frame_mbs_only_flag = 1
mb_adaptive_frame_field_flag 不存在-图像全是帧
mb_adaptive_frame_field_flag = 0图像是 场 和 帧-
mb_adaptive_frame_field_flag = 1图像是 场 和 帧场自适应-

没有帧和帧场自适应共存的模式。

  • direct_8x8_inference_flag,计算B_SKIP, B_direct等宏块的运动矢量使用。
  • frame_cropping_flag:图像是否需要crop,因为宏块都是16x16的,但是真实的图形不能都是16对齐的,所以有这个标志用来切除多余的边。为0时表示不需要切。
  • frame_crop_left_offset:裁边的参数
  • frame_crop_right_offset:裁边的参数
  • frame_crop_top_offset:裁边的参数
  • frame_crop_bottom_offset:裁边的参数

4. 伪代码分析

SPS的解析过程分支不多,我们按照流程来过一遍。

解析 profile_idc, 
解析constraint_set0/1/2/3/4/5_flag
reserved_zero_2bits 用0补齐
|
解析level_idc
|
解析seq_parameter_set_id
|
if (profile_idc 等于 100/110/122/244/44/83/86/118/128) 说明high profile功能,开启了部分扩展功能 { 
	解析 chroma_format_idc, YUV格式是420,mono,422,还是444
	if (YUV 格式是 YUV444) {
		读取separate_colour_plane_flag 值,
	}
	读取亮度和色度的位宽参数
	读取缩放参数
}
|
读取frame_num的最大值
|
读取POC计算方法
if (POC计算使用方法0) {
	读取最大POC值
} else if (POC计算使用方法1) {
	读取一些后面用于计算POC的数据
}
|
读取图像宽高,图像帧场属性
|
读取是否需要裁边以及裁边的宽高
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值