转:H.264熵编码分析

利用信源的随机过程统计特性进行码率压缩的编码方式称为熵编码。它是把所有的语法(句法)元素(包括控制流数据,变换量化残差系数和运动矢量数据)以一定的编码形式映射成二进制比特流。熵编码是无损压缩编码方法,它生成的码流可以经解码无失真地恢复出数据。在信息论中表示一个数据符号的理论上最佳的比特数通常是一个分数而不是整数,这个比特数用log2(1/P)表示,其中P是每个数据符号的出现概率。这里Log2(1/P)指的就是熵的概念。熵的大小与信源的概率模型有着密切的关系,各个符号出现的概率不同,信源的熵也不同。当信源中各事件是等概率分布时,熵具有极大值。信源的熵与其可能达到的最大值之间的差值反映了该信源所含有的冗余度。信源的冗余度越小,即每个符号所独立携带的信息量越大,那么传送相同的信息量所需要的序列长度就越短,符号位也越少。因此,数据压缩的一个基本的途径是去除信源的符号之间的相关性,尽可能地使序列成为无记忆的,即前一符号的出现不影响以后任何一个符号出现的概率。

熵编码可以是定长编码,变长编码或算术编码;变长编码对出现频率高的符号用短码字表示,对出现频率低的符号用长码字表示。算术编码是一种递推形式的连续编码,其思想是用01的区间上的一个数来表示一个字符输入流,它的本质是为整个输入流分配一个码字,而不是给输入流中的每个字符分别指定码字。算术编码是用区间递进的方法来为输入流寻找这个码字的,它从于第一个符号确定的初始区间(01)开始,逐个字符地读入输入流,在每一个新的字符出现后递归地划分当前区间,划分的根据是各个字符的概率,将当前区间按照各个字符的概率划分成若干子区间,将当前字符对应的子2区间取出,作为处理下一个字符时的当前区间。到处理完最后 一个字符后,得到了最终区间,在最终区间中任意挑选一个数作为输出。算术编码是一种高效的熵编码方案,其每个符号所对应的码长被认为是分数。由于对每一个符号的编码都与以前编码的结果有关,所以它考虑的是信源符号序列整体的概率特性,而不是单个符号的概率特性, 因而它能够更大程度地逼近信源的极限熵,降低码率。

H.264标准中有3种熵编码方案: 一个是指数哥伦布编码(Exponential Golomb Codes);一个是从可变长编码发展而来的上下文自适应可变长编码(CAVLC);另一个是从算术编码发展而来的基于上下文的自适应二进制算术编码(CABAC)。前两种属于变长编码,而第三种属于算术编码。研究表明CABAC的压缩效率比CAVLC提高了9%14%在标准中通过描述子(Descriptor)的形式来说明熵编码的方法。

 

Exp‐Golomb Codes

Exp‐Golomb的描述子有无符号指数哥伦布编码ue(v),有符号指数哥伦布编码se(v),截断指数哥伦布编码te(v)和映射指数哥伦布编码me(v)

0阶指数哥伦布编码是一种有规则结构的变长编码,它的结构可以表示为

[M zeros][1][INFO]

其中M zeros称为前缀,由M个零组成,而MINFO称为信息后缀。码字总长为2M+1MINFO的值由要编码的值索引code_num得到。(可参考标准表9‐1

ue(v)vcode_num的转换公式为code_num = v。(可参考标准表9‐2

se(v)vcode_num的转换公式为:

te(v)vcode_num的转换,首先根据语法元素v值位数范围,如果v的位数大于1vcode_num的转换过程和ue(v)相同;如果v的位数等于1,即v等于01,则code_numv的值相同,但最终的编码值与code_num这个值相反。

me(v)vcode_num的转换参考标准表9‐4

CAVLC

CAVLC的描述子是ce(v)

基于上下文自适应编码的CAVLC利用相邻已编码符号所提供的相关性为所要编码的符号选择合适的上下文模型,大大降低了符号间的冗余度。上下文模型的选择主要体现在非零系数和拖尾系数的个数编码所需表格(nC)的选择以及非零系数的幅值编码后缀长度(suffixLength)的更新。CAVLC编码的具体过程由以下五部分组成,编码顺序和Zig‐zag扫描顺序相反:

(1) 对非零系数的数目(TotalCoeffs)以及拖尾系数(TrailingOnes)的数目进行编码。根据这两个值一共有3个变长表格和1个定长表格(这4个表格只针对于亮度系数,色度系数使用其它表格)可供选择(选择的表格由相邻块非零系数的个数nC值确定,具体参见标准表9‐5)。其中的定长表格的码字是六个比特长,高四位表示TotalCoeffs,低两位表示TrailingOnes

(2) 对每个拖尾系数的符号进行编码。(+10表示,‐11表示)

(3) 对除了拖尾系数之外的非零系数的幅值(Levels)进行编码。这一步比较复杂,这里详细介绍对单个幅值的编码方法:

a) 将有符号的level转换成无符号的levelCode

如果level是正的,levelCode = (level<<1)‐2;

如果level是负的,levelCode = ‐(level<<1)‐1;

特别地,当TrailingOnes<3时,第一个非拖尾系数的幅值level要加1(当幅值为负)或减1(当幅值为正)后再计算levelCode

b) 计算level_prefix

level_prefix = levelCode / (1<<suffixLength)

根据level_prefix的值查标准表9‐6即可得到对应的字符串前缀。当TotalCoeffs>10TrailingOnes<1suffixLength初始为1,其它情况下suffixLength初始为0

c) 计算level_suffix

level_suffix = levelCode % (1<<suffixLength)

字符串后缀是level_suffix值的二进制无符号数形式。

d) suffixLength值更新为下一个编码作准备,如果当前已编码的非零系数值大于预先定义好的阈值,suffixLength1。伪代码如下(注意这里隐含了上下文自适应过程):

If ( suffixLength == 0 )

suffixLength++

else if ( Abs(level) > (3<<(suffixLength‐1)) && suffixLength <6)

suffixLength++;

e) 编码值为前缀和后缀的拼接。

(4) 对最后一个非零系数前零的数目(TotalZeros)进行编码(参见标准表9‐7,9‐8,9‐9)。

(5) 对每个非零系数前零的个数(RunBefore)进行编码(参见标准表9‐10)。还有一个变量ZerosLeft表示当前非零系数左边的所有零的个数,ZerosLeft的初始值等于TotalZeros,在每个非零系数的RunBefore值编码后进行更新。注意在以下两种情况下是不需要编码的:

a) 最后一个非零系数(run_before[0])前零的个数。

b) 没有剩余的零需要编码(ZerosLeft=0)

 

 

CABAC

CABAC的描述子是ae(v)

CABAC充分考虑和利用了视频流统计特性,克服了VLC编码中的缺点,充分利用了视频流的上下文信息,并且能够自适应视频流的统计信息,提高了编码效率。CABAC的编码流程如图1所示,主要分为3部分:语法元素二进制化、上下文建模和自适应二进制算术编码器。

大致编码过程如下:如果输入的语法元素是非二进制的语法元素则进行二进制化, 二进制的语法元素跳过这一过程。 二进制字符串进入编码器, 可以进行快速编码, 直接进入旁路编码器, 以固定的概率模型进行编码; 通常是根据语法元素的类型选择上下文, 然后二进制值和选择的上下文模型一起进入编码器, 输出编码码流, 并且根据编码符号更新上下文模型。CABAC要编码的语法元素包括两类:第一类包含关于宏块类型、子块类型以及时间和空间预测模式信息的元素;第二类包括所有残差元素,也就是所有变换系数相关的语法元素。

下面将详细介绍流程中的三个部分。

A. 语法元素二进制化

H.264通过二进制化把多维算术编码转化为二进制算术编码,提高了运算速度。语法元素二进制化就是把非二进制的符号映射成若干位的二进制串。CABAC引入了二进制化预处理过程来减小要编码的语法元素符号集的大小, 对于给定的语法元素用一个惟一的二进制串代替。CABAC二进制化方案由基本方案,串接方案(参考标准子条款9.3.2.39.3.2.6)以及特别的手工选择方案(参考标准子条款9.3.2.5)组成。基本方案有一元码、截断一元码、K阶指数哥伦布码和定长码4种;串接方案由基本方案串接而成;手工选择方案有5种,专门针对mb_typesub_mb_type这两种语法元素。对语法元素的二进制化方案参考标准表9‐25。经二进制化编码输出的是MPS概率极高的比特流,这样可以达到极高的压缩效果。

B. 上下文建模

利用相邻的编码符号的相关性,用已编码符号为待编码符号选择合适的上下文模型,上下文模型提供了对当前待编码符号的概率估计,上下文信息可以降低符号间的冗余度。在H.264中通过索引选择的方法利用上下文信息。首先建立上下文集合,上下文变量按线性排列,每一个变量用索引值来表示,然后为每一个语法元素分配上下文变量,最后通过编码符号的上下文信息选择上下文变量。

H.264中用64个有代表性的概率值来表示LPS(Least Probability Symbol)的概率。这64个概率值通过下式产生:

其中表示概率的索引值(),在H.264中概率模型用上下文变量表示,而上下文变量由2个变量组成, 分别为6位概率状态索引值pStateIdx)和1位最大可能符号值valMPS),所以概率状态空间总共有7128个状态。最大可能符号值MPS(Most Probability Symbol)"0""1",(ctxIdx)为上下文变量的索引值,各语法元素的取值范围可参考标准表9‐11,其准确值是这样计算的:

如果索引偏移值(标准表9‐11中范围的左值,即ctxIdxOffset)在标准表9‐30中,则ctxIdxctxIdxOffset与索引增加量(ctxIdxInc)之和,而ctxIdxInc取决于位索引(binIdx)和ctxIdxOffset;否则,ctxIdxctxIdxOffsetctxIdxInc与上下文种类偏移(ctxIdxBlockCatOffset)之和。此时ctxIdxIncctxIdxBlockCatOffset的值和上下文种类(ctxBlockCat)相关。ctxBlockCat的取值可参考标准表9‐33

上下文变量初始值由训练序列得到(参考标准子条款9.3.1.1),注意上下文变量初始值对于所有上下文变量的索引值ctxIdx都要计算,其计算表达式如下:

preCtxState = Clip3( 1, 126, ( ( m 􀗛 Clip3( 0, 51, SliceQPY ) ) >> 4 ) + n )

if( preCtxState <= 63 ) {

pStateIdx = 63 − preCtxState

valMPS = 0

} else {

pStateIdx = preCtxState − 64

valMPS = 1

}

其中mn的值是根据ctxIdx查找标准表9‐129‐23得到的。Clip3(x,y,z)的含义是如果z(x,y)的范围则直接取z,如果不在(x,y)范围则取边界值。初始值为不同的编码条件提供了最初的概率状态预自适应方法。

每一个语法元素可能会有几个上下文变量。在一个语法元素中,有些二进制位分配固定的上下文变量,其他的二进制位根据上下文信息选择上下文变量。上下文信息有4种类型:

a. 当前编码块相邻的已编码块的信息, 一般利用当前块的左边和上边相邻块。(标准子条款9.3.3.1.1

b. 利用同一语法元素中已经编码的二进制值为当前编码的二进制值选择上下文模型。(标准子条款9.3.3.1.2,用于语法元素mb_typesub_mb_type

c. 根据当前编码语法元素在编码块的之字行扫描位置(标准子条款9.3.3.1.3,用于残差语法元素significant_coeff_flaglast_significant_coeff_flag)。

d. 根据当前块已经编码的残差数据个数(标准子条款9.3.3.1.3,用于残差语法元素coeff_abs_level_minus1)。

C. 自适应二进制算术编码器

自适应特性保证上下文模型能够自适应视频流。对于不同的视频流,其编码符号的概率不同。在CABAC 中有2个编码器: 旁路编码器和规则编码器。旁路编码器以固定的概率进行编码, 概率状态不需要更新,编码效率低,主要用于编码符号概率为0.5的元素。下面以规则编码器为例说明编码器的原理。

 

编码器的输入值是上下文变量(由γ索引)和待编码的二进制值binVal,算术编码器的状态变量是编码区间R(codIRange9位精度)和最低限度L(codIOffset9位精度)。编码器完成区间细分功能。在该编码器中, 通过查表的方法进行快速计算。首先把编码区间量化, 因为, 可以通过对R(b8b7b6b5b4b3b2b1b0)b7b6进行4等分。4个量化区间值分别为Q0Q1Q2Q3LPS的相关子间隔范围RLPS得到,在具体实现时不用做乘法,而是用一个64x4的表格TabRangeLPS来查找得到(参考标准表9‐35),状态转换表TransIdxLPS是根据标准表9‐36

CABAC将片作为算术编码的生命期,在每个片开始时,CABAC进行初始化,按照一定的法则为编码器指定初始,并初始化[0,1)为当前区间(L初始化为0R初始化为0x01FE)。建立了概率模型和乘法模型后,在递进计算过程中CABAC必须保存以下变量记录状态:当前区间的下限L,当前区间的大小R,当前LPS的概率编号MPS字符。编码器流程如图2所示。流程图的第一步完成区间细分功能,然后根据binVal选择更新后的编码区间,流程图的灰色部分完成上下文变量的概率更新,概率更新就是一个状态转移的过程,实现了对模型初始表的修改。

 

编码器的最后是编码区间归一化,防止编码区间溢出,即保证,当然L也要通过移位与R保持一致的精度。在二进制编码中,区间的上下限以二进制形式表示,每当下限的最高有效位与上限的最高有效位一样时,就可以移出这个比特。这样的方法可以保证编码器在递进计算的同时不断地输出码流。

从中可以看出CABAC的算术编码有以下3个特点:

a. 每编码完一个符号都要更新概率状态, 使上下文变量中的概率估计和视频流实际的概率统计相适应。概率更新通过有限状态机来决定。一共有128个状态, 每一个状态代表一个概率估计, 状态转化就是根据已编码符号的不同取值。

b. 编码器的区间细分通过查表进行, 不需要进行复杂的计算, 易于实现并且提高了计算速度。

c. 对于概率近似0.5的符号(标准表9‐25标为na的符号), 通过旁路编码器进行编码, 不需要概率更新提高计算速度。

 

By kdjwang

2008‐8‐9

posted @ 2012-07-30 12:55  Mr.Rico  阅读(6144)  评论(0编辑  收藏  举报