版权声明:本文为博主[email protected](阿King)原创文章,不得以任何理由任何形式进行转载 https://blog.csdn.net/lj501886285/article/details/84635899
前言
量化后的系数经过Zig-Zag重新排序(Reorder)后,通过熵编码(Entropy encoding)进一步压缩。H264熵编码有两种模式,一种是CABAC,另一种便是本文讲解的CAVLC。
过程
术语
假设当前有4x4矩阵
经过Zig-zag重新排序后:0 0 5 3 2 -1 0 0 0 1
- 非零系数:不是0的所有系数,即5 3 2 -1 1,范围[0,16]
- 拖尾系数:单指 ,范围[0,3],若个数超过3个,则取最右边的3个 为拖尾系数,其余都为非零系数。
- 非零系数的个数(TotalCoeffs)
- 拖尾系数的个数(TrailingOnes)
- 零的总数(TotalZeros):指最右边非零系数左边零的个数。这里有1的左边零的个数TotalZeros=5
- 间零个数(RunBefore):指当前非零系数与左边相邻的非零系数之间的0的个数,例如非零系数1的间零个数为3,非零系数2的间零个数为0。可以推算出关系:
- 前零个数(ZerosLeft):指当前非零系数的左边0的个数。可以推算出关系:
编码
- 编码非零系数的个数(TotalCoeffs)和拖尾系数的个数(TrailingOnes)
①先计算NC(Number current)
NC代表当前块,NA代表左边的相邻块,NB代表上边的相邻块,则当前块NC的计算方式:(表示块在同一slice内且可用)
若当前输入的系数为色度的直流系数(即2x2个4x4block的DC值),则
②再根据TrailingOnes,TotalCoeffs,NC来查表进行编码
- 反向 对拖尾系数逐个编码
由于拖尾系数只有 ,故我们只需用1bit来编码它们的符号即可。+1编码成0,-1编码成1 - 反向 编码剩下的非零系数Levels
①先计算levelCode
当level>0时,有levelCode=|level-1|<<1
当level<0时,有levelCode=|level-1|<<1+1
可以发现levelCode到level的映射为下图,即正数level映射到偶数,负数level映射到奇数
②得到SuffixLength(SuffixLength是会不断更新的)
初始化:
· 当TotalCoeffs>10 && TrailingOnes<=3 时,SuffixLength=1
· 其余情况下,SuffixLength=0
更新:
查表,当level的值超过阈值时,SuffixLength++
③通过LevelCode和SuffixLength计算level-prefix和level-suffix
Level-prefix = LevelCode / (1 << SuffixLength)
Level-prefix = LevelCode % (1 << SuffixLength)
可以发现level-suffix是取levelCode的后SuffixLength位,level-prefix取levelCode前面部分
④编码level-prefix:
查表即可,且由表可知输出的bit string即在1前面添加level-prefix数量个0罢了
⑤求LevelSuffixSize(LevelSuffixSize表示为实际level-suffix的编码位数)
· 当level-prefix=14 && suffixLength=0时,LevelSuffixSize=4
· 当level-prefix=15时,LevelSuffixSize=12
· 其余情况,LevelSuffixSize=SuffixLength
⑥将level-suffix编码成LevelSuffixSize位数
⑦level的编码即为 [level-prefix][level-suffix] - 编码最右边的非零系数的 前(即左边)零个数 TotalZeros
根据TotalZeros和TotalCoffs来查表
(亮度块查表)
(色度的直流系数块查表)
- 反向 编码每个非零系数的 间零个数 RunBefore
两种情况不需要对该非零系数编码间零个数:
· 最左边非零系数的间零个数无需编码
· 若没有剩余的0了,则不需要再编码,即
①ZerosLeft初始为TotalZeros
②查表编码进行编码
③每编码一个RunBefore就更新ZerosLeft,有
例子
有矩阵
且假设当前块NC=3
- Zig-Zag 重排序
-2 4 0 3 -3 0 -1 0 0 1 - 编码TotalCoeffs和TrailingOnes
有6个非零系数2个拖尾系数,即TotalCoeffs=6,TrailingOnes=2。查表后编码为0000 0101 - 编码TrailingOnes
按照逆序依次编码1 -1,即0 1 - 编码level
按照逆序依次对-3 3 4 -2进行level编码
- 编码TotalZeros
一共有4个0,查表编码得101 - 编码RunBefore
按照逆序依次对1 -1 -3 3 4 -2进行RunBefore编码
故-2 4 0 3 -3 0 -1 0 0 1经过CAVLC编码后输出为
0 0000 1010 1000 0010 0100 0010 1111 0101 0110