CAVLC上下文自适应可变长编码

版权声明:本文为博主[email protected](阿King)原创文章,不得以任何理由任何形式进行转载 https://blog.csdn.net/lj501886285/article/details/84635899

前言

量化后的系数经过Zig-Zag重新排序(Reorder)后,通过熵编码(Entropy encoding)进一步压缩。H264熵编码有两种模式,一种是CABAC,另一种便是本文讲解的CAVLC。
在这里插入图片描述


过程

术语

假设当前有4x4矩阵
[ 0 0 1 0 5 2 0 0 3 0 0 0 1 0 0 0 ] \begin{bmatrix} 0 &0 &-1 &0\\ 5 &2 &0 &0\\ 3 &0 &0 &0\\ 1 &0 &0 &0 \end{bmatrix}\\
经过Zig-zag重新排序后:0 0 5 3 2 -1 0 0 0 1

  • 非零系数:不是0的所有系数,即5 3 2 -1 1,范围[0,16]
  • 拖尾系数:单指 ± 1 \pm1 ,范围[0,3],若个数超过3个,则取最右边的3个 ± 1 \pm1 为拖尾系数,其余都为非零系数。
  • 非零系数的个数(TotalCoeffs)
  • 拖尾系数的个数(TrailingOnes)
  • 零的总数(TotalZeros):指最右边非零系数左边零的个数。这里有1的左边零的个数TotalZeros=5
  • 间零个数(RunBefore):指当前非零系数与左边相邻的非零系数之间的0的个数,例如非零系数1的间零个数为3,非零系数2的间零个数为0。可以推算出关系:
    i = 0 T o t a l C o e f f s R u n B e f o r e = T o t a l Z e r o s \sum_{i=0}^{TotalCoeffs} RunBefore=TotalZeros
  • 前零个数(ZerosLeft):指当前非零系数的左边0的个数。可以推算出关系:
    R u n B e f o r e i = Z e r o s L e f t i Z e r o s l e f t i 1 RunBefore_{i}=ZerosLeft_i-Zerosleft_{i-1}
    Z e r o s L e f t 0 = T o t a l Z e r o s ZerosLeft_0=TotalZeros

编码

  1. 编码非零系数的个数(TotalCoeffs)和拖尾系数的个数(TrailingOnes)
    ①先计算NC(Number current)
    NC代表当前块,NA代表左边的相邻块,NB代表上边的相邻块,则当前块NC的计算方式:(表示块在同一slice内且可用)
    在这里插入图片描述
    若当前输入的系数为色度的直流系数(即2x2个4x4block的DC值),则 N C = 1 NC=-1
    ②再根据TrailingOnes,TotalCoeffs,NC来查表进行编码
    在这里插入图片描述
  2. 反向 对拖尾系数逐个编码
    由于拖尾系数只有 ± 1 \pm1 ,故我们只需用1bit来编码它们的符号即可。+1编码成0,-1编码成1
  3. 反向 编码剩下的非零系数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]
  4. 编码最右边的非零系数的 前(即左边)零个数 TotalZeros
    根据TotalZeros和TotalCoffs来查表
    (亮度块查表)
    在这里插入图片描述
    (色度的直流系数块查表)
    在这里插入图片描述
  5. 反向 编码每个非零系数的 间零个数 RunBefore
    两种情况不需要对该非零系数编码间零个数
    · 最左边非零系数的间零个数无需编码
    · 若没有剩余的0了,则不需要再编码,即 R u n B e f o r e = T o t a l Z e r o s \sum RunBefore=TotalZeros
    ①ZerosLeft初始为TotalZeros
    ②查表编码进行编码
    ③每编码一个RunBefore就更新ZerosLeft,有
    Z e r o s L e f t i + 1 = Z e r o s L e f t i R u n B e f o r e ZerosLeft_{i+1}=ZerosLeft_i-RunBefore
    在这里插入图片描述

例子

有矩阵
M = [ 2 4 0 1 3 0 0 0 3 0 0 0 1 0 0 0 ] M= \begin{bmatrix} -2 &amp;4 &amp;0 &amp;-1\\ 3 &amp;0 &amp;0 &amp;0\\ -3 &amp;0 &amp;0 &amp;0\\ 1 &amp;0 &amp;0 &amp;0 \end{bmatrix}\\
且假设当前块NC=3

  1. Zig-Zag 重排序
    -2 4 0 3 -3 0 -1 0 0 1
  2. 编码TotalCoeffs和TrailingOnes
    有6个非零系数2个拖尾系数,即TotalCoeffs=6,TrailingOnes=2。查表后编码为0000 0101
  3. 编码TrailingOnes
    按照逆序依次编码1 -1,即0 1
  4. 编码level
    按照逆序依次对-3 3 4 -2进行level编码
    在这里插入图片描述
  5. 编码TotalZeros
    一共有4个0,查表编码得101
  6. 编码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


在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lj501886285/article/details/84635899