CABAC
CABAC(Context-based Adaptive Binary Arithmetic Coding),基于上下文的自适应二进制算术编码。CABAC是H.264/AVC标准中两种熵编码中的一种,它的编码核心算法就是算术编码(Arithmetic Coding)。
# 算术编码
# 传统编码算法
算术编码与传统的编码方法有很大的区别,传统编码是通过符号映射实现的。映射包含符号(symbol)与码字(codeword)两个要素,如下面的例子
symbol | e | h | l | o |
---|---|---|---|---|
codeword | 00 | 01 | 10 | 11 |
通过上述的映射表,我们可以把“hello”编码成码流 01 00 10 10 11。而诸如Haffuman,Shannon这些编码方法也没脱离这种编码模式,他们只是通过符号出现的概率对码字进行调优。
# 算术编码
算术编码采用的并非上述这种传统的单符号映射模式进行编码,它不是将单个符号映射成一个码字,而是从全序列出发,将输入的符号依据它的概率映射到[0,1)内的一个小区间上,如此递归地进行区间映射,最后得到一个小区间,从该区间内选取一个代表性的小数作为实际的编码输出。
如下面为算术编码的例子
symbol | e | h | l | o |
---|---|---|---|---|
probability | 0.1 | 0.2 | 0.3 | 0.4 |
假设需要编码的符号只有“e”,“h”,“l”,“o”四个,他们出现的总概率为1,各个符号出现的概率如上述表格所示。现要求“hello”经过算术编码后的码字。
算术编码有如下编码步骤:
首先我们需要根据概率设定各符号在[0,1)上的初始区间,其中区间的起点为表中前面的符号的累计概率
symbol e h l o sum of probability 0 0.1 0.1+0.2 0.1+0.2+0.3 interval [0,0.1) [0.1,0.3) [0.3,0.6) [0.6,1) “hello”的第一个符号为“h”,那么映射的区间为[0.1,0.3)。
接下来我们需要根据符号的概率分割[0.1,0.3)上的区间,得到的结果如下
symbol e h l o interval [0.1,0.12) [0.12,0.16) [0.16,0.22) [0.22,0.3) “hello”的第二个符号为“e”,那么映射的区间为[0.1,0.12)。
按照这种方式继续进行区间映射,最终“hello”映射到的区间是[0.10888,0.1096)
映射区间 区间大小 初始值 [0,1) 1 编码完h后 [0.1,0.3) 0.2 编码完e后 [0.1,0.12) 0.02 编码完l后 [0.106,0.112) 0.006 编码完l后 [0.1078,0.1096) 0.0018 编码完o后 [0.10888,0.1096) 0.00072 从区间[0.10888,0.1096)中任取一个代表性的小数,如“0.109”就是编码“hello”后的输出值
算术编码的总体的编码流程可以参考下图
算术解码就只是需要判断代表性的小数在哪个区间,相应地就知道输入的符号了。
# 二进制算术编码
二进制算术编码的编码方法跟算术编码是一样的,但是输入只有两个符号:“0”,“1”,也就是说输入的是二进制串。除了是对二进制串进行编码这个特征外,二进制算术编码跟普通的算术编码还有一些区别,总体上可以按照如下进行描述: s
x264→