H.264的CAVLC(编码.解码)过程详解

    技术2022-05-20  39

    编码 过程: 假设有一个 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 output = 0000 100; 3 ) 编码所有 TrailingOnes 的符号: 逆序编码,三个拖尾系数的符号依次是+( 0 ),-( 1 ),-( 1 ); : TrailingOne sign[i--] = 0; TrailingOne sign[i--] = 1; TrailingOne sign[i--] = 1; Code output = 0000 100    0 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++;      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 output = 0000 100 011 1; 编码下一个Level:Level[0] = 3; levelCode = 4;level_prefix = 2;查表得bit string = 001; level_suffix = 0;suffixLength = 1;故码流为0010; Code output = 0000 100 011 1 0010 ; i = 0,编码Level结束。

    5)编码最后一个非零系数前零的数目(TotalZeros): 查表9-7,当TotalCoeffs = 5,total_zero = 3时,bit string = 111; Code output = 0000 100 011 1 0010 111;

    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 output = 0000 100 011 1 0010 111 10 1 1 01 ; 编码完毕。(CAVLC主要是查表,标准中的表是通过大量实验的出来的!)

     

     

    解码过程:

    接收码流为:0000 1000 1110 0101 1110 1101

    计算NC = 1 解码详细过程如下: 1.       根据Coeff_token和NC查表(见标准表9-5),得到非零系数数目TotalCoeffs和拖尾系数数目TrailingOnes NC = 1选择对应的表,Coeff_token为0000100,查表得到TotalCoeffs=5 TrailingOnes=3 输出序列:无 2. 解析拖尾系数 由第一步得到拖尾系数有3个,输入拖尾系数符号编码码流011,得到两个拖尾系数由先到后是 -1,-1,1 output :-1,-1,1(反序输出) 3.       解析除拖尾系数外的非零系数的幅值(level) (1)       确定后缀长度SuffixLength (2)       根据码流查表9-6得到前缀LevelPrefix (3)       根据前缀和后缀,得到

                  LevelCode=(levelprefix<<suffixlength)+levelsuffix (4)       Levelcode为偶数 level=(level+2)/2                 Levelcode为奇数 level=(-level-1)/2 (5)       根据设定的阈值确定是否update Suffixlegth 回到例子中,按照逆序 i=0, Sufixlegth=0,查表9-6,1对应的前缀levelprefix=0,levelcode=0,

         计算得到level=1 , i++ , sufixlegth++(第一次都要加) i=1,sufixlegth=1,查表0010(3为前缀,1位后缀 )对应的前缀      levelprefix=2,计算levelcode=4,level=3,i++ i=2 >= TotalCoeffs-TrailingOnes,除拖尾系数外的非零系数解析完毕 output:3,1,-1,-1,1 4.       解析每个非零系数前零的个数 根据TotalCoeffs=5和输入码流111查表9-7得到TotalZeros=3 初始i=TotalCoeffs-1=4 ,zeroleft=TotalZeros=3 , 5个非零系数前零的数目解析如下: i=4,zeroleft=3,根据码流10,查表9-10,runbefor=1,

       输出序列:3,1,-1,-1,0,1 i=3,zeroleft=3-1=2,根据码流1,查表runbefore=0,

    输出序列:3,1,-1,-1,0,1 i=2,zeroleft=2-0=2,根据码流1,查表runbefore=0,

    输出序列:3,1,-1,-1,0,1 i=1,zeroleft=2-0=2,根据码流01,查表runbefore=1,

    输出序列:3,0,1,-1,-1,0,1 i=0,zeroleft=2-1=1,输出序列:0,3,0,1,-1,-1,0,1 5. 解码完毕,将剩下的元素用0补齐,反序排列就可以得到4*4矩阵。 6. 最后还原为一个4*4数据块 {    0 , 3 , -1 , 0,    0,   -1 , 1,   0,    1 ,   0 , 0 , 0,    0 ,   0 , 0 , 0 }


    最新回复(0)