H264编解码参数说明
音视频基础学习实验地址:https://github.com/chensongpoixs/caudio_video
一、H264码流分层
1、NAL层
Network Abstraction Layer,视频数据网络抽样层。
①、如何判断帧类型(是图像参考帧还是I、P帧等)?
NALU类型是我们判断帧类型的利器,从官方文档中得出如下图:
我们还是接着看最上面图的码流对应的数据来层层分析,以00 00 00 01分割之后的下一个字节就是NALU类型,将其转为二进制数据后,解读顺序为从左往右算,如下:
(1)第1位禁止位,值为1表示语法出错
(2)第2~3位为参考级别
(3)第4~8为是nal单元类型
例如上面00000001后有67,68以及65
其中0x67的二进制码为:
0110 0111
4-8为00111,转为十进制7,参考第二幅图:7对应序列参数集SPS
其中0x68的二进制码为:
0110 1000
4-8为01000,转为十进制8,参考第二幅图:8对应图像参数集PPS
其中0x65的二进制码为:
0110 0101
4-8为00101,转为十进制5,参考第二幅图:5对应IDR图像中的片(I帧)
所以判断是否为I帧的算法为: (NALU类型 & 0001 1111) = 5 即 NALU类型 & 31 = 5
比如0x65 & 31 = 5
②、 帧格式
H264帧由NALU头和NALU主体组成。
NALU头由一个字节组成,它的语法如下:
±--------------+
|0|1|2|3|4|5|6|7|
±±±±±±±±+
|F|NRI| Type |
±--------------+
F: 1个比特.
forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.
NRI: 2个比特.
nal_ref_idc. 取00~11,似乎指示这个NALU的重要性,如00的NALU解码器可以丢弃它而不影响图像的回放,0~3,取值越大,表示当前NAL越重要,需要优先受到保护。如果当前NAL是属于参考帧的片,或是序列参数集,或是图像参数集这些重要的单位时,本句法元素必需大于0。
Type: 5个比特.
nal_unit_type. 这个NALU单元的类型,1~12由H.264使用,24~31由H.264以外的应用使用,简述如下:
0:未规定
1:非IDR图像中不采用数据划分的片段
2:非IDR图像中A类数据划分片段
3:非IDR图像中B类数据划分片段
4:非IDR图像中C类数据划分片段
5:IDR图像的片段
6:补充增强信息(SEI)
7:序列参数集(SPS)
8:图像参数集(PPS)
9:分割符
10:序列结束符
11:流结束符
12:填充数据
13:序列参数集扩展
14:带前缀的NAL单元
15:子序列参数集
16 – 18:保留
19:不采用数据划分的辅助编码图像片段
20:编码片段扩展
21 – 23:保留
24 – 31:未规定
NAL的头占用了一个字节,按照比特自高至低排列可以表示如下:
③、 SPS格式解析代码分析 ParseAndRewriteSps方法
2、 VCL层
VIdeo Coding Layer, 视频数据编码层。
3、 码流基本概念
①、 SODB(String Of Data Bits)
原始数据比特流,长度不一定是8的倍数,故需要补齐。它是由VCL层产生的。
②、 RBSP(Raw Byte Sequence Payload)
SODB+trailing bits
算法是如果SODB最后一个字节不对齐,则补1和多个0.
③、 NALU 单元
NAL Header(1byte) + RBSP
NALUnit.png
h264_slice_block.png
h264_slice.png
h264_rtp_annexb.png
④ SPS/PPS/Slice Header
⑤ webrtc中对应RBSP的代码 段 方法SpsVuiRewriter::ParseAndRewriteSps
二, SPS中两个重要的参数分别是 Profile 与 Level
1、 H264 Profile
h264_profile.png
h264_profile_main_high.png
对视频压缩特性的描述,Profile越高,就说明采用了越高级的压缩特性
2、 H264 Level
h264_level.png
Level是对视频的描述,Level越高,视频的码率、分辨率、fps越高
3、 分辨率
pic_width_in_mbs_minues1 | 图像宽度包括的宏块个数-1 |
pic_heigh_in_mbs_minus1 | 图像高度包括的宏块个数-1 |
frame_mbs_only_flag | 帧编码还是场编码 (场是隔行扫描、产生两张图) |
frame_cropping_flag | 图像算法需要裁剪 |
frame_crop_left_offset | 减去左侧的偏移量 |
frame_crop_right_offset | 减去右侧的偏移量 |
frame_crop_top_offset | 减去顶部的偏移量 |
frame_crop_bottom_offset | 减去底部的偏移量 |
4、 帧相关的
①、 帧数 log2_max_frame_num_minus4
②、 参考帧数 max_num_ref_frames
解码设置缓冲区大小的
③、 显示帧序号 pic_order_cnt_type
解码
5、 帧率的计算
framerate = (float)(sps->vui.vui_time_scale)/(float)(sps->vui.vui_num_units_in_tick)/2;
三、 PPS与 Slice Header
entropy_coding_mode_flag | 熵编码,1表示使用CABAC编码 |
num_slice_groups_minus1 | 分片数量 |
weighted_pred_flag | 在P/SP Slice中开启权重预测 |
weighted_bipred_idc | 在B Slice中加权预测的方法 |
pic_init_qp_minus26/pic_init_qs_minus26 | 初始化量参数,实际参数在Slice header |
chroma_qp_index_offset | 用于计算色度分量的量化参数 |
deblocking_filter_control_present_flag | 表示Slice header中是否存在用于去块滤波器控制的信息 |
constrainged_intra_pred_flag | 若该标识为1,表示I宏块在进行帧内预测时只能使用来自I和SI类型宏块的信息 |
redundant_pic_cnt_preset_flag | 用于表示Slice Header中是否存在redundant_pic_cnt语法元素 |