熵编码系列目录
熵编码(一)-熵编码概述
熵编码(二)-指数哥伦布熵编码
1. 前言
通过熵编码系列第一篇文章熵编码(一)-熵编码概述,我们了解了熵编码的概念和分类。熵编码包含了香农-范诺编码、霍夫曼编码、指数哥伦布熵编码,CAVLC、CABAC等。 本篇文章中主要介绍指数哥伦布熵编码,主要应用于SPS&PPS的句法元素解析。
2. 指数哥伦布熵编码
指数哥伦布熵编码是变长编码, 一个数值可以随着数值的不同而有不同的比特数,包含:无符号指数哥伦布熵编码,有符号指数哥伦布熵编码,映射指数哥伦布熵编码,截断指数哥伦布熵编码。 指数哥伦布熵编码是一种比较简单的编码方法,可以拓展至K阶,即K阶指数哥伦布熵编码。在H264白皮书中使用的是0阶指数哥伦布熵编码,即K=0。因此下述文章中除非特殊标明是K阶,描述的都是0阶指数哥伦布熵编码。理解了0阶指数哥伦布熵编码,自然也就理解了K阶指数哥伦布熵编码
3. 无符号指数哥伦布熵编码
无符号指数哥伦布熵编码和熵解码流程如下图
3.1. 无符号指数哥伦布熵编码
无符号指数哥伦布熵编码步骤:
- 将code_num+1,转化为二进制序列
- 计算二进制序列比特位数M, 令前置补0的比特数leading_zero_bits=M-1,
- 在二进制序列前面增加leading_zero_bits个0, 得到encode_num
3.2. 无符号指数哥伦布熵解码 ue(v)
无符号指数哥伦布熵解码步骤:
- 按位读取encode_num,直到非0的比特位为止,得到前置补0的数量leading_zero_bits
- 读取leading_zero_bits+1的二进制序列,获取无符号二进制数值D
- 解码得到code_num=D-1
uint32_t md_bits_rue(BitContext *bc) {
int leading_zero_bits = 0;
/* md_bits_r1: read one bit */
while(!md_bits_r1(1)) {
leading_zero_bits++;
}
return (1 << leading_zero_bits) + md_bits_r1(leading_zero_bits) - 1;
}
上述代码写法是因为md_bits_r1(1)不为0时,此时指针已经指向非0比特位的下一个比特位.
3.3. K阶无符号指数哥伦布熵编码
由上述的0阶流程,可以拓展至k阶,只需要把第一步稍微变动一点 K阶无符号指数哥伦布熵解码步骤:
- 将
code_num+2^k转化为二进制序列(0阶) - 计算二进制序列比特位数M, 令前置补0的比特数leading_zero_bits=M-1,
- 在二进制序列前面增加leading_zero_bits个0, 得到encode_num
可以发现0阶指数哥伦布熵编码就是K阶指数哥伦布熵编码K=0的特殊形式
3.4. K阶无符号指数哥伦布熵解码 ue_k(v)
K阶无符号指数哥伦布熵解码步骤:
- 按位读取encode_num,直到非0的比特位为止,得到前置补0的数量leading_zero_bits
- 读取leading_zero_bits+1的二进制序列,获取无符号二进制数值D
- 解码得到
code_num=D-2^k
uint32_t md_bits_rue_k(BitContext *bc, k) {
int leading_zero_bits = 0;
/* md_bits_r1: read one bit */
while(!md_bits_r1(1)) {
leading_zero_bits++;
}
return (1 << leading_zero_bits) + md_bits_r1(leading_zero_bits) - (1 << k);
}
4. 有符号指数哥伦布熵编码
4.1. 有符号指数哥伦布熵编码
有符号指数哥伦布熵编码步骤:
- 将code_num取绝对值并转化为二进制序列
- 在二进制序列后增加一位符号位:0表示整数,1表示负数
- 计算二进制序列比特M, 令前置补0的比特数leading_zero_bits=M-1
- 在二进制序列前面增加leading_zero_bits个0,得到encode_num
4.2. 有符号指数哥伦布熵解码 se(v)
有符号指数哥伦布熵解码步骤:
- 先进行无符号指数哥伦布解码ue(v),得到code_num=k
- 有符号指数哥伦布语法元素值se(v)=(-1)^(code_num) * ((codec_num+1) >> 1)
int md_bits_rse(BitContext *bc) {
uint32_t code_num = md_bits_rue(bc);
return pow(-1, code_num + 1) * ((code_num + 1) >> 1);
}
5. 参考文档
本篇文章参考T-REC-H.264官方协议文档实现指数哥伦布熵编码&熵解码