学习笔记——基于实例分析CAVLC的具体流程


前言

H.264中,CAVLC(基于上下文自适应的可变长编码)被用于亮度和色度残差数据的编码。


设一个4*4的残差系数块经过zigzag扫描,数据重排列后为:0,3,0,1,-1,-1,0,1,0,0,0,0,0,0,0,0. NC的值为1

一、CAVLC编码步骤

Step1.对非零系数的数目(TotalCoeffs)以及拖尾系数的数目(TrailingOnes)进行编码

拖尾系数:重排列后,序列末尾连续出现+1或者-1的个数(中间可以间隔任意多个0),若连续出现+1或者-1的个数大于3,则取最后3个为拖尾系数。
:用来编码TotalCoeffs及TrailingOnes的码表有变量NC的值确定。

本例中,TotalCoeffs=5,TrailingOnes=3(分别是-1,-1,1),查H.264标准表,可得coeff_token=0000 100,Code=0000 100。

Step2.对拖尾系数的符号进行逆序编码

其中0表示“+”号,1表示“-”号。
本例中3个拖尾系数的符号依次是0 1 1。此时Code=0000 1000 11

Step3.逆序编码除了拖尾系数以外的非零系数幅值(难点)

编码过程为:
(1)设定初始值:普通情况下,suffixLength初始化为0(当 TotalCoeffs>10&&TrailingOnes<=1时,suffixLength初始化为1)。
(2)将有符号的level转化为无符号的levelCode:如果level是正值,levelCode =(level<<1)-2;若level是负值,levelCode = -(level<<1)-1。特别的,当TrailingOnes<3时,第一个非拖系数的level要加1(幅值为负)或减1(幅值为正)后再计算levelCode。
(3)计算level_prefix:level_prefix=levelCode/(1<<suffixlength),根据level_prefix的值可以查标准表9-6,得到对应的字符串前缀。
(4)计算level_suffix:level_suffix=levelCode%(1<<suffixlength),字符串后缀是level_suffix值的二进制无符号数形式。
(5)输出残差系数的编码比特:前缀和后缀的拼接
(6)更新suffixLength值:若当前已编码的非零系数值大于给定的阈值,则suffixLength+1。

本例中,
(1)先编码1,此时levelCode=0,level_prefix=0,查表得前缀为1,suffixLength=0,故无后缀(suffixLength等于后缀长度),suffixLength+1。此时Code=0000 1000 111;
(2)再编码3,此时suffixLength=1,levelCode=4,level_prefix=2,查表得前缀为001,level_suffix=0,所以后缀为0,此时Code=0000 1000 1110 010。

Step4.对最后一个非零系数前0的数目(total_zero)进行编码

查表,当TotalCoeffs=5,total_zero=3时,bit string=111,此时,Code=0000 1000 1110 0101 11

Step5.对每个非零系数前0的个数(RunBefore)进行逆序编码

ZeroLeft:当前非零系数左边的0的个数,初始值等于total_zero,在每个非零系数的RunBefore值编码后进行更新。
注以下两种情况不需要编码:(1)最后一个非零系数(逆序)前0的个数。(2)没有剩余的0需要编码。

本例中:第一个非零系数1,ZeroLeft=3,查表,得run_before=1,码流为10;第二个非0系数为-1,ZeroLeft=2,查表得run_before=0,码流为1……此时Code=0000 1000 1110 0101 1110 1101。

一、CAVLC解码步骤

对于序列0000 1000 1110 0101 1110 1101解码过程如下:

Step1.解析TotalCoffes和TrailingOnes

根据NC和Coeff_token查表,得到TotalCoffes和TrailingOnes。

本例中:TotalCoffes=5,TrailingOnes=3

Step2.解析拖尾系数

根据Step1得到TrailingOnes,由拖尾系数符号码流可得拖尾系数。

本例中符号码流为011,故拖尾系数为-1 -1 1。

Step3.解析除拖尾系数外的非零系数的幅值(难点)

(1)确定后缀长度suffixLength
(2)根据码流查表得到前缀level_prefix
(3)根据前缀和后缀得到levelCode=(level-prefix<<suffixLength)+level-suffix
(4)levelCode为偶数时,level=(levelCode+2)/2;level=(-levelCode-1)/2
(5)更新阈值suffixLength

本例中,当suffixLength=0时,查表得到1对应的前缀为level_prefix=0,计算得到LevelCode=0,level=1,更新suffixLength,suffixLength=1,查表得0010对应的前缀为level_prefix=2,计算得到LevelCode=4,level=3。

Step4.解析每个非零系数前0的个数

根据TotalCoffes和码流查表,得到totalzeros,初始化zeroleft=TotalZeros。

本例中:zeroleft=3时,根据码流10查表,得runbefore=1,输出3.1.-1.-1.0.1;zeroleft=2时,根据码流1查表,得runbefore=0,输出3.1.-1.-1.0.1;zeroleft=2时,根据码流1查表,得runbefore=0,输出3.1.-1.-1.0.1;zeroleft=2时,根据码流01查表,得runbefore=1,输出3.0.1.-1.-1.0.1;zeroleft=1时输出0.3.0.1.-1.-1.0.1;

Step5.解析完毕,剩下的元素用0补齐

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值