h264CAVLC自适应上下文变长编码原理

时间:2022-06-11 15:54:06

熵编码是无损压缩编码方法,它生成的码流可以经解码无失真地恢复出原数据。熵编码是建立在随机过程的统计特性基础上的。

称H(X )为信息源 X的熵(entropy),单位为 bit/符号, 通常也称为 X的一阶熵,它可以理解为信息源X 发任意一个符号的平均信息量。由信息论的基本概念可以知道,一阶熵是无记忆信息源(在无失真编码时)所需数码率的下界。

熵的大小与信源的概率模型有着密切的关系,各个符号出现的概率不同,信源的熵也不同。当信源中各事件是等概率分布时,熵具有极大值。信源的熵与其可能达到的最大值之间的差值反映了该信源所含有的冗余度。信源的冗余度越小,即每个符号所独立携带的信息量越大,那么传送相同的信息量所需要的序列长度越短,符号位越少。因此,数据压缩的一个基本的途径是去除信源的符号之间的相关性,尽可能地使序列成为无记忆的,即前一符号的出现不影响以后任何一个符号出现的概率。

CAVLC

在 H.264 的CAVLC(基于上下文自适应的可变长编码)中,通过根据已编码句法元素的情况动态调整编码中使用的码表,取得了极高的压缩比。CAVLC 用于亮度和色度残差数据的编码。残差经过变换量化后的数据表现出如下特性:4*4 块

数据经过预测、变换、量化后,非零系数主要集中在低频部分,而高频系数大部分是零;量化后的数据经过zig-zag 扫描,DC 系数附近的非零系数值较大,而高频位置上的非零系数值大部分是+1 -1;相邻的4*4 块的非零系数的数目是相关的。CAVLC 充分利用残差经过整数变换、量化后数据的特性进行压缩,进一步减少数据中的冗余信息

 

CAVLC 的上下文模型

利用相邻已编码符号所提供的相关性,为所要编码的符号选择合适的上下文模型。利用合适的上下文模型,就可以大大降低符号间的冗余度。在CAVLC 中上下文模型的选择主要体现在两个方面

非零系数编码所需表格的选择

拖尾系数后缀长度的更新

非零系数数目的范围是从0 到16,拖尾系数数目的范围是从0 到3。

如果±1 的个数大于3 个,只有最后3 个被视为拖尾系数,其余的被视为普通的非零系数。

 

对非零系数数目和拖尾系数数目的编码是通过查表的方式,共有4 个变长表格和1 个定长表格可供选择。

其中的定长表格的码字是6个比特长,高4 位表示非零系数的个数(TotalCoeffs),最低两位表示拖尾系数的个数(TrailingOnes)。

 h264CAVLC自适应上下文变长编码原理

对于每个拖尾系数(±1)只需要指明其符号,其符号用一个比特表示(0 表示+,1 表示-)。编码的顺序是按照反向扫描的顺序,从高频数据开始。

非零系数的幅值(Levels)的组成分为两个部分

前缀(level_prefix)

后缀(level_suffix)。  后缀是长度为LevelSuffixsSize位的无符号整数

levelSuffixsSize 和suffixLength 是编码过程中需要使用的两个变量,。通常情况下变量levelSuffixsSize = suffixLength 有两种情况例外:

1. 当前缀等于 14 时,suffixLength 等于0,levelSuffixsSize 等于4。

2. 当前缀等于 15 时,levelSuffixsSize 等于12。

 

变量suffixLength 是基于上下文模式自适应更新的,suffixLength 的更新与当前的suffixLength的值以及已经解码好的非零系数的值(Level)有关。suffixLength 数值的初始化以及更新过程如下所示:

1. 普通情况下 suffixLength 初始化为0,但是当块中有多于10 个非零系数并且其中拖尾系数的

数目少于3 个,suffixLength 初始化为1。

2. 编码在最高频率位置上的非零系数。

3. 如果当前已经解码好的非零系数值大于预先定义好的阈值,变量 suffixLength 加1。

决定是否要将变量suffixLength 的值加一的阈值如表3 所示。第一个阈值是0,表示在第一个非零系数被编码后,suffixLength 的值总是增加1。

h264CAVLC自适应上下文变长编码原理

TotalZeros 指的是在最后一个非零系数前零的数目,此非零系数指的是按照正向扫描的最后一个非零系数。例如:已知一串系数0 0 5 0 3 0 0 0 1 0 0 -1 0 0 0 0,最后一个非零系数是-1,TotalZeros的值等于2+3+1+2=8。因为非零系数数目(TotalCoeffs)是已知,这就决定了TotalZeros 可能的最大值。

每个非零系数前零的个数(RunBefore)是按照反序来进行编码的,从最高频的非零系数开始。RunBefore 在以下两种情况下是不需要编码的:

1. 最后一个非零系数(在低频位置上)前零的个数。

2. 如果没有剩余的零需要编码(Σ[RunBefore]=TotalZeros)时,没有必要再进行RunBefore 的编码。在CAVLC 中,对每个非零系数前零的个数的编码是依赖于ZerosLeft 的值,ZerosLeft 表示当前

非零系数左边的所有零的个数,ZerosLeft 的初始值等于TotalZeros,在每个非零系数的RunBefore值编码后进行更新。用这种编码方法,有助于进一步压缩编码的比特数目。例如:如果当前ZerosLeft等于1,就是只剩下一个零没有编码,下一个非零系数前零的数目只可能是0 或1, 编码只需要一个比特。

 

根据数值得到的编码过程都是通过查表获得的:

比较难的是拖尾系数和NC的数值的确定。

目前认为拖尾系数应该是最后的+1.-1的个数

如果±1 的个数大于3 个,只有最后3 个被视为拖尾系数