二进制化——截断莱斯码与截断一元码
将待编码信息二进制化成异字头码是视频编解码中基本操作,其中对于候选列表索引(如merge候选列表索引)的编解码,一般采用了一种特殊的截断莱斯码——截断一元码进行二进制化。
截断莱斯码
生成截断莱斯码需要指定两个参数:最大门限值MAX和莱斯参数R。截断莱斯码由两部分组成:前缀和后缀。假设待二进制化数值为x,则其截断莱斯码生成过程如下:
- 前缀码:先计算P=x>>R。若P < (MAX>>R),则前缀码长度为P+1,由P个1和1个0组成;若P ≥ (MAX>>R),则前缀码长度为MAX>>R,全部由1组成。
- 后缀码:当x < MAX时,才会生成后缀码。需要计算S=x-(P<<R),后缀码为S的二进制码串。
特别的,当莱斯参数R为0时,截断莱斯码就退化成了截断一元码,常用于编码列表长度固定的索引信息。
截断一元码
生成截断一元码需要指定一个参数:最大门限值MAX。其二进制化规则十分简单,当待二进制化数值x≥MAX时,其对应码字为MAX个1;当x<MAX时,其二进制码字为x个1和一个0。下表展示了MAX=3的截断一元码。
Index | 码字 |
---|---|
0 | 0 |
1 | 10 |
2 | 110 |
3 | 111 |
截断一元码编解码实现
编解码端实现对截断一元码的编解码方式如下:
- 编码端
if (Index == 0) {
arithmeticEncoder.encode(0, ctx.ctxIndex);//ctx.Index是编解码该信息的上下文模型
}
else {
arithmeticEncoder.encode(1, ctx.ctxIndex);
for (int i = 1; i < MAXNUM - 1; i++) {//MAXNUM就是最大门限值
arithmeticEncoder.encode(Index == i ? 0 : 1, ctx.ctxIndex);
if (Index == i)
{
break;
}
}
}
- 解码端
auto Index = 0;//默认解码出Index是0
if (arithmeticDecoder.decode(ctx.ctxIndex)) {//解码出Index大于0
Index++;
for (; Index < MAXNUM - 1; Index++) {
if (arithmeticDecoder.decode(ctx.ctxIndex) == 0 ) {
break;
}
}
}