HEVC熵编码

一、HEVC中熵编码采用的技术

1、零阶(或者k阶)哥伦布指数编码(变长编码,类似于哈夫曼编码那样),主要用于VPS、SPS、PPS、slice头部信息的编码

2、CABAC(算数编码),主要用于数据和参数的编码

二、零阶哥伦布指数编码(假设对数字4进行编码,n=4)

1、把n转换成二进制,即100

2、对二进制加上一,即101

3、计算二进制的比特数,假设为x,101的比特数是3

4、在二进制比特的前面加上(x-1)个比特的0,即00 101

三、零阶哥伦布指数编码技术

1、对于一个数字,先把它转换成索引index(书上把它叫做codeNum),

if n > 0

     index= 2n - 1

else

     index= -2n

2、编码器中设置了一张全局表存放了从0到N的零阶哥伦布指数编码的码字,以index作为索引,在表中进行查找,得到码字

三、CABAC算数编码介绍

1、两个关键字L和R,L表示区间下界,R表示区间范围

2、算数编码对错误敏感

3、常规方式的编码主要有三个步骤:

     (1)二进制化

     (2)上下文建模

     (3)二进制算数编码

4、旁路编码主要由两个步骤:

     (1)二进制化

     (3)编码(旁路编码假设每个符号出现的概率相等,因此不需要建模)

四、CABAC算数编码技术

1、二进制化

     (1)采用截断莱斯二元化(TK)、K阶指数哥伦布指数编码(EGK)、定长二元化(FL),不同的语法元素选择不同的二进制方案

     (2)有两个语法元素cu_qp_delta_abs和coeff_abs_level_remaining才用了上面的几种方式混合来进行二进制化

2、上下文建模(建模即建立概率模型)

     (1)关键的参数r,表示上下文模型的索引。

     (2)r与两个参数相关:MPS(最大概率符号,取值一般是0和1,因为二进制也只能取这个值)和δ (概率状态索引)

     (3)CABAC中为LPS(最小概率符号)设定了64个初始值,δ 与LPS是一一对应的,LPS的更新表现为δ 的更新

     (4)上下文建模的主要目的就是要确定模型的初始MPS和a,MPS和δ 可以通过公式进行计算

     (5)初始化之后就是模型更新:

          ①如果当前bit等于MPS,那么查询MPS表格更新啊

          ②如果当前bit等于LPS,如果δ ==0,那么互换MPS和LPS,然后查询LPS表更新δ ;如果δ !=0 那么直接查询LPS表,更新δ

3、二进制编码

     (1)根据每一个bit和其概率模型参数进行编码

     (2)需要两个关键参数区间下限L和区间范围R,这两个参数表示了编码器的状态

     (3)计算索引值p,p=(R >> 6) & 3

     (4)通过δ和p在表格(rangeTabLps)中查询LPS对应的子区间R1

     (5)通过R1计算MPS对应的子区间R2,R2=R-R1

     (6)如果当前的bit等于MPS,那么选择R2作为下一个R,L不变

     (7)如果当前的bit等于LPS,那么选择R1作为下一个R,L更新,L=L+R2

五、系数的熵编码

1、普通的语法参数,比如预测模式等可以直接使用CABAC进行处理;但是系数(即量化之后的数据)则需要进行一些预处理

2、先把TB分成多个4x4的子块,然后扫描系数,扫描是基于4x4的子块进行的(子块内部的扫描方式和子块的扫描方式一样),扫描的方式有:对角扫描、水平扫描、垂直扫描

3、扫描是从最后一个系数开始的,即倒着扫描

4、一个4x4块的16个系数被称为一个系数组(CG)

5、一个TB的系数经过扫描之后就可以变成一维的数组了,需要对这一组系数进行编码

6、编码最后一个非零系数的位置,然后编码其他非0系数的位置(有若干比较关键的语法参数)

7、对非零系数的幅值进行编码(有比较多的规则)

猜你喜欢

转载自blog.csdn.net/strikedragon/article/details/82796569