您的位置:首页 > 其它

CAVLC熵编码

2013-04-26 11:43 253 查看
http://bbs.chinavideo.org/viewthread.php?tid=1033&highlight=cavlc

谨以此文献给QQ群“H.264乐园”和群里那些无私奉献的同行朋友!

也希望能对刚进入这个领域的朋友有所帮助,欢迎做过CAVLC的同行能批评指正!

编码过程:

假设有一个4*4数据块

{

0, 3, -1, 0,

0, -1, 1, 0,

1, 0, 0, 0,

0, 0, 0, 0

}

数据重排列:0,3,0,1,-1,-1,0,1,0……

1) 初始值设定:

非零系数的数目(TotalCoeffs) = 5;

拖尾系数的数目(TrailingOnes)= 3;

最后一个非零系数前零的数目(Total_zeros) = 3;

变量NC=1;

(说明:NC值的确定:色度的直流系数NC=-1;其他系数类型NC值是根据当前块左边4*4块的非零系数数目(NA)当前块上面4*4块的非零系数数目(NB)求得的,见毕厚杰书P120表6.10)

suffixLength = 0;

i = TotalCoeffs = 5;

2) 编码coeff_token:

查标准(BS ISO/IEC 14496-10:2003)Table 9-5,可得:

If (TotalCoeffs == 5 && TrailingOnes == 3 && 0 <= NC < 2)

coeff_token = 0000 100;

Code = 0000 100;

3) 编码所有TrailingOnes的符号:

逆序编码,三个拖尾系数的符号依次是+(0),-(1),-(1);

即:

TrailingOne sign[i--] = 0;

TrailingOne sign[i--] = 1;

TrailingOne sign[i--] = 1;

Code = 0000 1000 11;

4) 编码除了拖尾系数以外非零系数幅值Levels:

过程如下:

(1)将有符号的Level[ i ]转换成无符号的levelCode;

如果Level[ i ]是正的,levelCode = (Level[ i ]<<1) – 2;

如果Level[ i ]是负的,levelCode = - (Level[ i ]<<1) – 1;

(2)计算level_prefix:level_prefix = levelCode / (1<<suffixLength);

查表9-6可得所对应的bit string;

(3)计算level_suffix:level_suffix = levelCode % (1<<suffixLength);

(4)根据suffixLength的值来确定后缀的长度;

(5)suffixLength updata:

If ( suffixLength == 0 )

suffixLength++;

else if ( levelCode > (3<<suffixLength-1) && suffixLength <6)

suffixLength++;

回到例子中,依然按照逆序,Level[i--] = 1;(此时i = 1)

levelCode = 0;level_prefix = 0;

查表9-6,可得level_prefix = 0时对应的bit string = 1;

因为suffixLength初始化为0,故该Level没有后缀;

因为suffixLength = 0,故suffixLength++;

Code = 0000 1000 111;

编码下一个Level:Level[0] = 3;

levelCode = 4;level_prefix = 2;查表得bit string = 001;

level_suffix = 0;suffixLength = 1;故码流为0010;

Code = 0000 1000 1110 010;

i = 0,编码Level结束。

5)编码最后一个非零系数前零的数目(TotalZeros):

查表9-7,当TotalCoeffs = 5,total_zero = 3时,bit string = 111;

Code = 0000 1000 1110 0101 11;

6) 对每个非零系数前零的个数(RunBefore)进行编码:

i = TotalCoeffs = 5;ZerosLeft = Total_zeros = 3;查表9-10:

依然按照逆序编码

ZerosLeft =3, run_before = 1 run_before[4]=10;

ZerosLeft =2, run_before = 0 run_before[3]=1;

ZerosLeft =2, run_before = 0 run_before[2]=1;

ZerosLeft =2, run_before = 1 run_before[1]=01;

ZerosLeft =1, run_before = 1 run_before[0]不需要码流来表示

Code = 0000 1000 1110 0101 1110 1101;

编码完毕。

----------------------------------Sunrise------

[ 本帖最后由 firstime 于 2008-9-4 02:49 PM 编辑 ]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: