给朋友过生日创意点子:cabac编码过程的解读

来源:百度文库 编辑:中财网 时间:2024/04/30 00:44:56

cabac编码过程的解读  

CABAC是H.264/AVC标准中两种熵编码方法中的一种,是将自适应的二进制算术编码与一个设计精良的上下文模型结合起来得到的方法。它很好地利用了语法元素数值之间的高阶信息,使得熵编码的效率得到了进一步提高。它的主要特点有:利用每个语法元素的上下文关系,根据已编码元素为待编码元素选择概率模型,即上下文建模;根据当前的统计特性自适应地进行概率估计;使用算术编码。[5]

在CABAC中编码一个单独的句法元素的通用方框图。这个编码过程主要由三个基本步骤组成:

1、二值化;

2、上下文建模;

3、基于表格的二进制算术编码。

在第一步,一个给出的非二进制值的句法元素唯一地对应到一个二进制序列,叫二进制串。当给出一个二进制值的句法元素时,这一初始步骤将被跳过,如图1所示。对于每个元素的二进制串或每个二进制值的句法元素,后面会根据编码模式有一两个子步骤。

接下来就是对二元数据进行编码,标准中有两种编码模式可供选择。在常规编码模式(regular coding mode)中,一个句法元素的每一个二进值(bin
)按其判决产生的顺序进入上下文模型器,在这里,模型器根据已经编码过的句法元素或二进值为每一个输入的二进值分配一个概率模型,这就是上下文模型化。然后该二进值和分配给它的概率模型一起被送进常规算术编码器进行编码,此外编码器还要根据该二元位的值反馈一个信息给上下文模型器,用以更新上下文模型,这就是编码中的自适应;另一种模式是旁路编码模式(bypass coding mode),在该模式中,没有模型器为每个二进值分配一个特定的概率模型,输入的二元数据是直接用一个简单的旁路编码器进行编码的,这样做是为了加快整个编码(以及另一端解码)的速度,当然,该模式只用于某些特殊的二进值。

后面将更加详细地讨论二值化,上下文建模与基于表格的二进制算术编码这三个主要步骤以及它们之间的相互联系。

    
2.2二值化

CABAC的二值化方案有四种基本类型:一元码,截断一元码,k阶指数哥伦布编码,与定长编码。此外,还有基于这些基本类型的联合的二值化方案与基于查表的二值化方案。
2.2.1 一元码(Unary)

对于一个非二进制的无符号整数值符号x≥0,在CABAC中的一元码码字由x个“1”位外加一个结尾的“0”位组成。例如,输入的句法元素值为4,其二值化结果为11110。
2.2.2 截断一元码(Truncated Unary, TU)

已知截断值S。对于一个非二进制的无符号整数值符号0≤x

 
2.2.3 k阶指数哥伦布编码(kth order Exp-Golomb, EGk)

指数哥伦布编码是由一个前缀和一个后缀的码字连接组成的。EGk码字的前缀部分由l(x)=[log2x(x/2k+1)]的值所对应的一元码组成。EGk码字的后缀部分可以通过使用长度为k+l(x)位的x+2k(1-2l(x))的二进值来计算。另外,EGk码字也可以通过下面的伪C代码推得。

while(1)

{

  if (x>=(1<

{

put(1);

x=x-(1<

k++;

}//EGk的一元码前缀

  else

  {

    put(0);//前缀的截止位“0”

    while(k--)

 put((x>>k)&0x01); //EGk的后缀

  }

  break;

}
2.2.4 定长编码(Fixed-Length, FL)

对用到定长编码二进化的句法元素值假设了一个有限的字母表 [0,1,2,…,Cmax],编码的二进制长度为  。其中,二进制1对应其中重要性最低的符号,随着重要性的增加,二进制数也会跟着增加。
2.2.5  4位FL与截断值为2的TU联合二值化方案

前缀使用长度为4位(Cmax=15)的定长编码,后缀使用截断值S=2的一元截断码。 
2.2.6  TU与EGk的联合二值化方案(Unary/kth order Exp-Golomb, UEGk)

前缀使用一元截断码,后缀使用k阶哥伦布编码。对于不同的句法元素值,有不同的截断值与阶数。 
2.2.7 各种句法元素值的二值化

宏块跳过标记mb_skip_flag、4*4亮度块的帧内预测模式标记prev_intra4x4_pred_mode_ flag、8*8亮度块的帧内预测模式标记prev_intra8x8_pred_mode_ flag、当前宏块的帧/场模式标记mb_field_decoding_flag、已编码块标记coded_block_flag、重要系数标记significant_ coeff_flag、最后一个重要系数标记last_significant_coeff_flag、系数符号位标记coeff_sign_ flag、片结束标记end_of_slice_flag、8*8转换系数块标记transform_size_8x8_flag均使用1位的定长编码。

运动矢量差的绝对值使用截断值为9的UEG3二值化。

色度帧内预测模式intra_chroma_pred_mode使用截断值为3的TU二值化。

转换系数的绝对值减1一coeff_abs_level_minus1使用截断值为14的UEG0二值化。

块编码模式coded_block_pattern使用4位FL与截断值为2的TU联合二值化方案。该句法元素指定了6个块,其中4个用于亮度,2个用于色度,表示其中是否含有非零系数。coded_block_pattern=coded_block_patternY+16*nc,首先,亮度部分的coded_block_patternY使用的是4位FL变换,而色度部分nc用的是截止值为2的TU二进制变换。

宏块类型mb_type与子宏块类型sub_mb_type的二值化通过查表获得,详情参见标准。

各句法元素的二值化方案可以参见标准中的表9-25。
2.2.8 联合二值化方案编码实例

输入的句法元素值为幅度的绝对值abs_level=20。则coeff_abs_level_minus1=19,对此使用截断值S=14,阶数k=0的UEG0二值化方案。

先编码前缀部分,按照编码规则易得二进制序列为11 1111 1111 1111(14个1)。

再编码后缀部分,下面分别按照伪C代码与编码规则进行编码:

1、按照伪C代码进行编码

x = 19 – S = 5。

进行第一次循环:5>1(即1<<0),因此put(1), x=5-1=4, k+1=1;

进行第二次循环:4>2(即1<<1),因此put(1), x=4-2=2, k+1=2;

进行第三次循环:2<4(即1<<2),因此put(0);

至此得到EG0的前缀一元码与截断位0。

进行第一次循环:k-1=1,因为(x>>k)&0x01=(2>>1)&0x01=1,所以put(1);

进行第二次循环:k-1=0,因为(x>>k)&0x01=(2>>0)&0x01=0,所以put(0);

至此得到EG0的后缀序列10。

2、按照编码规则进行编码

由x=5得l(x)=[log2x(x/2k+1)]=2,对应的一元码110即为EG0前缀。

又因为x+2k(1-2l(x))=5-3=2=(10)2,其中后缀码字长度为k+l(x)=2,则EG0后缀为10。

可见,两种方法得到的联合二值化后缀码字相同,均为11010,则最终输出的二进制 

序列为11 1111 1111 1111 11010。


2.3上下文建模

CABAC将片(Slice)作为算术编码的生命期。但对具体句法元素的编码却是发生在宏块级。实际上,在同一个宏块中,不同的句法元素是独立编码。但在不同的宏块中,相邻宏块的句法元素的上下文信息(包括概率状态state与最大概率符号MPS的值)可用于编码当前宏块的同一句法元素。
2.3.1 上下文的初始化(包括m,n,pre_state,state,mps)

在开始编码一个新的片时,都会对每个上下文模型指定相应的一对变量(m, n),并根据m, n的值计算出每个上下文模型对应的初始概率状态state与最大概率符号MPS的值。该初始化的过程有以下三个步骤:

1、计算 pre_state=((m*(QP-12))>>4)+n;//qp由下面的式子产生

PS:slice_qp_delta表示用于条带中的所有宏块的的QPy的初始值,该值在宏块层将被mb_qp_delta的值修改,该条带初始QPy量化参数按下面的公式计算:SliceQPy=26+pic_init_qp_minus26+slice_qp_delta

slice_qp_delta应该受限,这样SliceQPy的值将在-QpBdOffsetY到+51之间;

2、对于P和B帧图像限制pre_state在[0,101]内,对于I帧图像,限制pre_state在[27,74]内,即pre_state= min(101, max(0, pre_state))(对P 和B帧),pre_state=min (74,max(27, pre_state))(对I帧);

3、将pre_state按以下规则映射到数组{state, MPS}:如果pre_state<=50,{state=50- pre_state, MPS=0},否则{state= pre_state-51, MPS=1}

对于不同上下文模型的(m, n)分配参看标准。
2.3.2 上下文模型的分类

上下文模型大概可以分成4种。

第一种上下文模型包含当前要编码的句法元素的 两个相邻块的已编码句法元素 的信息,其中相邻块的具体位置就要看句法元素了,一般是根据左边与上边的相邻块。

第二种上下文模型只对mb_type与sub_mb_type的句法元素有定义。对于这种上下文模型,之前已编码的二进串的值(b0, b1, b2,…, bi-1)是用来为一个索引为i的二进制句法元素值选择模型的。

第三与第四种上下文模型都是只应用在残差数据上。与其它上下文模型不同,这两种类型都是依赖于不同块种类的上下文范围,如下文所示。

其中,第三种类型并不依赖于已编码数据,而是待编码数据在扫描路径上的位置。对于第四种类型,首先在前面已编码(已解码)的变换系数幅度中,统计出具有某个特定值的变换系数幅度出现的总次数,然后根据这个数值来为当前变换系数中的二进值确定上下文模型

除了这些基于条件概率的上下文模型,还有固定的概率模型映射到为那些已在常规模式被编码的所有二进串的,以及先前没有指定范围的的上下文模型可以用到的二进值索引。


2.3.3 上下文模型的分配与确定

通常,每个句法元素的上下文模型根据上下文索引偏移量与上下文增量来确定。其中,上下文索引偏移量对于特定类型片中的特定句法元素是唯一确定的,可以在标准中通过查表获得。而上下文增量,则是根据相邻块的编码情况(也就是上下文信息)得出。

对于不同的句法元素,所需相邻块的信息不同,但一般包括可用性(如当前块在片的边缘上,则相邻快可能由于不是在同一片中而不可用)与同一句法元素的编码值

通常用于计算上下文增量的上下文建模函数为ctx_var_spat=cond_term(A,B),A和B表示当前块的相邻块。其中cond_term()表示的是一种函数关系,有以下3种具体情况:

ctx_var_spat1=cond_term(A) + cond_term(B);

ctx_var_spat2=cond_term(A) + 2*cond_term(B);

ctx_var_spat3=cond_term(A)

另外,对于利用先前bin值(已编码值)的上下文建模函数为ctx_var_bin[k] = cond_term (b1, …, bk-1)

各句法元素的上下文增量的具体推导过程参见标准。

 
2.4二进制算术编码

算术编码是基于区间划分的,CABAC的算术编码有以下3个明显性质:

1、概率估计是对小概率符号LPS(Plps<0.5)的概率而言的,是通过基于表格中64个不同概率状态{Pk|0≤k<64}之间的相互转换而实现的。

2、区间长度R通过一组预先量化的值{Q1,Q2,Q3,Q4}进行量化以计算新的间隔区间。通过储存一个二维表格TabRangeLPS来决定LPS的新的子间隔范围Rlps,表格包含所有64*4预计算值Qi * Pk,通过快速查表这样就可以免除算术编码中的乘法运算了。

3、对近似均匀分布(Plps=0.5)的句法元素,在编码和译码时选择旁路方式,可以免除上下文建模,提高编码速度。

 


2.4.1 概率估计

在H.264/AVC中的免除乘法的二进制编码基本思想依赖于一个假设:每一个上下文模型估计的概率可以用一个有效的有限的特征值集合来表征。对于CABAC,对LPS有64个特征概率值

伸缩因子 ,N=64

一方面想要获得快速的自适应 N要小;另一方面,如果想获得更加稳定更加精确的估计,则需要更大的N。注意在MQ编码中,在CABAC方法中,不需要对LPS的概率值进行表格化在算术编码中,每一个概率仅仅用其相关的索引作为地址

这样设计的结果导致,CABAC中的每一个上下文模型可以有两个参数完全决定:LPS概率当前估计值()和MPS的值 (0或者1)。这样,在CABAC的概率估计中有128个不同的状态,每一个状态用一个7位整型数来表达。

实际上,有一个状态的索引()对应着LPS的最小概率值,但它并没有被纳入CABAC的概率估计和更新的范围,这个值被用作特殊的场合,传达特殊的信息。比如,当解码器检测到当前区间的划分依据是这个概率值时,认为这表示当前流的结束。因此只有126个有效概率状态。另外,有一个状态的索引()对应LPS的最小概率值,它对应的更新值是它自身,当MPS连续出现,LPS的概率持续减小,直到保持不变。

概率估计指的是上下文的更新,因此只发生在编码不同块中同一句法元素或者其它上下文发生改变的时候,它是通过在LPS的64个概率状态之间互相转移而实现的。

对于一个给定概率状态,概率的更新取决于状态索引和已经编码的符号值(MPS or LPS)。更新过程导致一个新的概率状态,潜在的LPS概率修正,如果有必要需要修改MPS的值。如果当state=0时,也就是LPS的概率已经达到了最大值0.5,输入的是一个小概率符号LPS,那么MPS和LPS就要互换,因为state=0时,Plps=0.5。

在I片中,有:

           if(decision==MPS)

                            state<-next_state_MPS_intra(state)

           else              state<-next_state_LPS(state)

在其他片中,有:

          if(decision==MPS)

                            state<-next_state_MPS (state)

          else               state<-next_state_LPS(state)

 
2.4.2 算术编码器的总体描述

CABAC编码器由两个子编码器组成,一个用于常规编码模式,另一个称为旁路编码器用于符号的快速编码。下面对常规编码器具体的编码过程进行描述,编码过程必须与后面介绍的译码过程相匹配(H.264标准文件中给出了译码流程,没给出具体的编码流程,下面给出的是可参考的编码流程,必须与译码流程匹配

1、首先是编码器的初始化

该过程是发生在编码片的第一个宏块之前,在编码I_PCM宏块的数据元素pcm_alignment_zero_bit和所有pcm_byte数据之后的。此过程中,输出的是算术编码器中的相关参数,区间下限codILow设置为0,区间长度codIRange设置为0x01FE,另外的firstBitFlag设置为1,计数器(用于防止相关寄存器溢出)bitsOutstangding和symCnt都被设置为0。

2、编码决定

此过程输入的是Binval(语法元素经过二进制化后的值),context_id(上下文模型)和编码器的环境codirange,codilow和symCnt,输出的值是codirange,codilow和symCnt。如图2.2所示。

该过程可以分为4个步骤

(1)通过当前编码器区间范围codiRange计算Qi的索引值i,然后利用状态索引(由上下文模型得到)和i进行查表得出Rlps的概率

(2)根据要编码的符号是否MPS来更新算术编码中的概率区间下限和概率区间范围。

(3)上下文模型概率状态的更新(参考前文)

(4)重整化处理,具体操作在后文给出。 

3、重整化处理

在区间划分结束后,如果新的区间范围R不在合法范围[28   29]之内,那么就需要进行重整化操作,输出1位或多位。其中用到的PutBit程序。

4、旁路编码模式

首先,概率估计和更新过程的旁路被建立;

其次间隔细分被执行 

最后,编码完片内所有宏块的句法元素后,写入end_of_slice_flag的标志,然后进行字节压缩,在编码完一幅图像的所有元素后,所有输出的二进制位都会进行封装,成为适合NAL层的传输单位。