认为DPB管理这块是理解H264的难点。时代变化很快,重点研究H265才是王道。
1 VCL ,NAL
H264分为VCL和NAL层
VCL层出来的就是经过编码器编码的比特流,比特流经过传输介质传输前,首先需要进行封装打包,即我们的所谈的NAL packet,简称为NALU。
2 NALU格式
NALU格式:NAL header+RBSP;
在bistreame里通过start code来寻找NALU;
RBSP是在原始比特流SODP的基础上,对齐补零后实现的;
Start code: 每个NAL前添加起始码0x000001xx,有时为了保证NAL单元在长度上对齐,通常会在起始码前加若干字节的0来填充,直到该NAL的长度符合要求。”xx”用来表示不同的NALU包。H.264规定当检测到0x000000时也可以表征当前NAL的结束,这是因为连着的三个字节的0中的任何一个字节的0要么属于起始码,要么是起始码前面添加的0.
如果在数据中出现0x000001或者0x000000,在最后一个字节前添加0x03,由编码器完成。解码器检测到时,将0x03抛弃,恢复原始数据。
3 Slice类型:
H264里其实没有很明确的I帧,P帧等概念,它出来的压缩包都是slice。
I slice,片内参考
B slice,双向参考
P slice,前向参考
码流里会有一些特殊的I slice,即IDR帧。IDR一定是I帧,I帧不一定是IDR;IDR图像是为了解码的重同步,当解码器解码到IDR图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。
场图:顶,底场编码方式可能不一样,如顶场为I slice,底场可能为P slice;
帧图:只能为I,P,B中的一种。
4 句法/语义
编码器出来的每个bit都属于某一个句法元素,码流本身是由一个个句法元素依次衔接组成,码流中除了句法元素并不存在专门用于控制或同步的内容。句法元素被组织成有层次的结构,分别描述各个层次的信息。
H264中,句法元素共被组织成序列,图像,片,宏块,子宏块五个层次。
H264分层结构最大的不同是取消了序列层和图像层,并将原本属于序列和图像头部的大部分句法元素游离出来形成序列和图像两级参数集,其余的部分则放入片层。
语义:就是每层句法元素集合的解释含义。
5 句法元素与变量
编码器将数据编码为句法元素然后依次发送,在解码器端,通常要将句法元素作求值计算,得出一些中间数据,这些中间数据就是H.264定义的变量。
6 句法/语法/描述子
句法是句法元素的组织结构,而对一个结构的描述必然少不了对应的语法,语法提供判断,循环等必要的描述方法。
描述子是指从比特流提取句法元素的方法,即句法元素的解码算法。
句法表:spec中对每层句法元素的集合定义,如seq header的组成;
语义:对句法表中的句法元素作详细解释;
7 Frame num含义
参考帧,非参考帧都有
对于非参考帧来说,它的frame_num值在解码过程中是没有意义的,因为frame_num值是参考帧所特有的。
Frame_num是参考帧的标识,但是在解码器中,并不是直接引用的frame_num值,而是由frame_num进一步计算出来的变量PicNum,
从frame_numàpic_num是有一系列算法的。
计算POC的时候,第二种和第三种解码方法也会引用到frame num。
8 POC含义
POC用来标志图像的播放顺序
对编码帧而言,每个帧有两个poc,分别是顶场POC,TopFieldOrderCnt和底场POC BottomFieldOrderCnt;
对于每个编码场有一个图像序列号,编码顶场称为TopFieldOrderCn,编码底场BottomFieldOrderCnt;
上述两个cnt都是相对于前一个IDR图像(或者解码顺序中前一个包含memory_manager_control_operation=5的参考图像)的第一个输出场的相对位置。
每一个参考帧都会有一个唯一性的标志,即句法元素frame_num,但是,当编码器要指定当前图像的参考图像时,并不是直接指定该图像的frame_num值,而是通过下面步骤最终得出的reg_id号;
Frame_num-------------PicNum--------------ref_id
计算POC有三种方法,具体描述需要参考spec。。
9 DPB管理
DPB简称Decoded Picture Buffer,用来缓存解码后的图像。
9.1 参考图像序列初始化
在解码每个P,B slice前都需要进行参考图像列表的初始化,从而生成参考图像序列表RefPicList0。另外,当解码B Slice时,还将生成另一个参考图像序列RefPicList1。
P帧参考帧队列初始化:
List0: 短期参考帧按pic num降序,长期参考帧按pic num升序;
B帧参考帧队列初始化,
List 0:短期参考帧按POC降序,长期参考帧按pic num,图像序号
List1:短期参考帧按POC升序,长期参考帧按pic num,图像序号
具体的初始化算法需要参考spec。
9.2 参考图像序列重排序
初始化之后,根据码流中的相关语法元素,对于对上述的Reflist0,RefList1在做一次重排序。
如ref_pic_list_reordering_flag_l0
Ref_pic_list_reordering_flag_l1
Reordering_of_pic_nums_idc
具体的重排序算法需要参考spec。
9.3 参考图像标记
自适应输出
滑动参考帧输出
用来通知DPB哪些参考帧不再用作参考,可以输出等。JM里通过insert_fs_to_dpb实现。具体的标记算法需要参考spec。