Chinaunix首页 | 论坛 | 博客
  • 博客访问: 75574
  • 博文数量: 10
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 321
  • 用 户 组: 普通用户
  • 注册时间: 2014-05-24 18:56
文章分类
文章存档

2019年(2)

2014年(8)

我的朋友

分类: C/C++

2019-05-15 09:23:46

CAVLC 编码过程


0.  CAVLC是h264的熵编码(entropy coding)一种,是一种无损编码.h264编码算法对任何()宏块无论采取帧内预测或是帧间运动估计,最终都会归结到对()宏块预测或估计的残差值矩阵进行DCT变换、量化、和熵编码.熵编码的结果才是最终的码流.


1.  现有经过DCT变换以及量化之后的4x4block,如下所示.

0

3

-1

0

0

-1

1

0

1

0

0

0

0

0

0

0

上述4x4block经过zig-zag顺序扫描之后,生成重排序列reorder-sequence: 0,3,0,1,-1,-1,0,1,0,0,0,0,0,0,0,0


2.  编码非零系数的数目(TotalCoeffs)以及拖尾系数的数目(TrailingOnes)

非零系数的数目(TotalCoeffs):就是reorder-sequence中非零系数的个数,这里TotalCoeffs=5.

拖尾系数的数目(TrailingOnes):逆向扫描reorder-sequence的非零系数,排在最前面的连续+1/-1串就是拖尾系数.拖尾系数数目TrailingOnes的范围是[0,3],也就是即便这个+1/-1串的个数大于3,也只有前3个被算入拖尾系数数目TrailingOnes.这里TrailingOnes=3, 因为+1/-1串的个数等于4,但是最大只能是3.

TotalCoeffs和TrailingOnes是作为一个整体一起编码的,码字是根据h264-2003.5.pdf

Table 9-5 coeff_token mapping to TotalCoeff( coeff_token ) and TrailingOnes( coeff_token )表格得出的,此表格部分内容如下,

TrailingOnes

TotalCoeff

0 <= NC < 2

2 <= NC < 4

4 <= NC < 8

4 <= NC < 8

4 <= NC < 8

0

0

1

11

1111

0000 11

01

0

1

0001 01

0010 11

0011 11

0000 00

0001 11

……

……

……

……

……

……

……

3

5

0000 100

0011 0

1010

0100 11

-

……

……

……

……

……

……

……

上表可以看出, TotalCoeffsTrailingOnes的编码还得依据另一个变量NC的值来决定.

若当前块(4x4block)的左侧块(4x4block)的非零系数的数目TotalCoeffsNA, 当前块(4x4block)的上侧块(4x4block)的非零系数的数目TotalCoeffsNB,那么NC的值计算方法如下表.按照编码规范,上侧块、左侧块和当前块要属于同一个slice.

上侧块(NB)

左侧块(NA)

NC

存在

存在

(NA+NB)/2

存在

不存在

NB

不存在

存在

NA

不存在

不存在

0

那么,假如当前块的上侧块和左侧块都不存在, reorder-sequenceTotalCoeffsTrailingOnes的编码结果就是 0000 100

 

3.  编码拖尾系数的符号

按逆序编码, 正号用 0,负号用 1

那么, reorder-sequence的编码拖尾系数符号的编码结果就是0000 1000 11

 

4.  编码除了拖尾系数之外的每个非零系数

按逆序编码, 编码结果由两部分组成, 前缀 + 后缀, 前缀就是level_prefix的码字,后缀是suffixLength 个level_suffix(01)组成. 基本过程:

(1) 把非零系数记为level[i],这里level[i]是带符号的.

(2) 把level[i]转换为无符号的levelcode,

如果level[i] > 0, levelcode = (level[i] << 1) - 2;

如果level[i] < 0, levelcode = -(level[i] << 1) - 1;

(3) 计算level_prefix,

level_prefix = levelcode / ( 1 << suffixLength)

注意, suffixLength 初始化为0,但是当块中有多于10 个非零系数并且其中拖尾系数的数目少于3 个,suffixLength 初始化为1

level_prefix的码字由h264-2003.5.pdf 的Table 9-6 – Codeword table for level_prefix得出

Table 9-6 – Codeword table for level_prefix

level_prefix

bit string

0

1

1

01

2

001

3

0001

4

0000 1

5

0000 01

6

0000 001

7

0000 0001

8

0000 0000 1

9

0000 0000 01

10

0000 0000 001

11

0000 0000 0001

12

0000 0000 0000 1

13

0000 0000 0000 01

14

0000 0000 0000 001

15

0000 0000 0000 0001

(4) 计算level_suffix,

level_suffix = levelcode % ( 1 << suffixLength)

(5) 此时的suffixLength决定后缀长度, level_suffix的奇偶性决定后缀是0还是1,奇数->1,偶数->0.

(6) 更新suffixLength,以便编码下一个系数

if (suffixLength == 0)

suffixLength++;

else if (levelcode > (3<

suffixLength++;

当前suffixLength

Levelcode阈值

0

0

1

3

2

6

3

12

4

24

5

48

6

N/A

那么, reorder-sequence需要编码的就是1,3两个非零系数.首先编码非零系数1, levelcode = (1<<1)-2=0,level_prefix=0/(1<<0)=0,level_suffix=0%(1<<0)=0,suffixLength=0(初始值).所以非零系数1的编码结果就是1(前缀)(没有后缀,因为suffixLength=0).之后suffixLength++,然后编码非零系数3, levelcode = (3<<1)-2=4,level_prefix=4/(1<<1)=2,level_suffix=4%(1<<1)=0,suffixLength=1, 所以非零系数3的编码结果就是001(前缀)0(后缀).

那么, reorder-sequence的非零系数的编码结果就是0000 1000 1110 010

 

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

根据h264-2003.5.pdf 的Table 9-7, Table 9-8,最后一个非零系数前零的数目(TotalZeros)的码字由TotalCoeff决定. reorder-sequence的TotalCoeff=5, 最后一个非零系数前零的数目(TotalZeros)=3,查表可知,对应的码字是111.

那么, reorder-sequence最后一个非零系数前零的数目(TotalZeros)的编码结果就是0000 1000 1110 0101 11

 

6.  编码每个非零系数前零的个数(RunBefore)

逆序对每一个非零系数编码. ZerosLeft为系数前面0的个数, run_before为系数前面紧邻的连续0的个数.那么,对于reorder-sequence来说,通过查h264-2003.5.pdf 的Table 9-10 – Tables for run_before就有

系数1: ZerosLeft=3; run_before=1  码字10

系数-1: ZerosLeft=2;run_before=0  码字1

系数-1: ZerosLeft=2;run_before=0  码字1

系数1: ZerosLeft=2;run_before=1  码字01

系数3: ZerosLeft=1; run_before=1  最前面的系数不需要编码

那么, reorder-sequence每个非零系数前零的个数(RunBefore)的编码结果就是

0000 1000 1110 0101 1110 1101,这也就是这个4x4block最终的编码结果,直接输出为码流.


阅读(2373) | 评论(0) | 转发(0) |
0

上一篇:LCD时序解释

下一篇:位域BitField的解释

给主人留下些什么吧!~~