LV05-02-H264-12-02-指数哥伦布编码

本文主要是指数哥伦布编解码的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
PC端开发环境 Windows Windows11
Ubuntu Ubuntu20.04.6的64位版本
VMware® Workstation 17 Pro 17.0.0 build-20800274
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
Win32DiskImager Win32DiskImager v1.0
点击查看本文参考资料
点击查看相关文件下载
------

前面已经从哥伦布编码引出了指数哥伦布编码,对哥伦布编码有了一定的了解,在H264的SPS帧中就使用到了指数哥伦布编码,这里来详细的学习一下。

一、指数哥伦布编码简介

1. 指数哥伦布编码

指数哥伦布(Exp-Golomb)编码是一种在音视频编码标准中经常采用的可变长编码方法,它是使用一定规则构造码字的变长编码模式。它将所有数字分为等大小不同的组,符号值较小的组分配的码长较短,同一组内符号长基本相等,并且组的大小呈指数增长。

指数哥伦布码的比特串分为“前缀”(prefix)和“后缀”(suffix)两个部分。它的逻辑结构为:

1
[N个0][1][INFO] 或者 [Prefix 前缀][1][Suffix 后缀]
  • prefix:对应连续的N个0;

  • surfix:为表示实际数值的信息位,其长度与 prefix 一样。

编码后码长为2N + 1 + k,N为前缀长度,1为中间的1长度,N+k为后缀长度。

2. H264中的指数哥伦布编码

在H264码流中就会有指数哥伦布编码的存在,例如SPS帧:

image-20241213164505373

可以看到里面就会出现ue(v)、se(v)等,其实还会有te(v)、me(v),他们都是指数哥伦布编码:

类型 说明
ue(v) 无符号指数哥伦布编码
se(v) 有符号指数哥伦布编码
te(v) 截断指数哥伦布编码
me(v) 映射指数哥伦布编码

其中ue(v)是其他变型算法的基础,其他算法的结果由ue(v)的结果进一步处理得到。关于指数哥伦布编码的相关内容,在H264的相关文档中也有说明:ITU-T Rec. H.264 (08/2024) Advanced video coding for generic audiovisual services中的9.1 Parsing process for Exp-Golomb codes。

二、0阶指数哥伦布编码

指数哥伦布编码是一种较简单的编码方法,正常来说,它可以拓展至K阶,也即K阶指数哥伦布编码。而在H.264中使用的,是0阶指数哥伦布编码,也即K等于0。下面我们来学习一下0阶指数哥伦布编码。

1. ue(v)

1.1 ue(v)编码过程

image-20241216110711312

以待编码码号code_num = 3为例:

  • 第一步:将code_num +1, 即3+1 = 4

  • 第二步:将4写为二进制的形式:100

  • 第三步:计算100的比特个数为3,在100前面写(3-1)个0,得到编码码字:00100

会发现里面有一些连续的码字是一样长的,可以总结如下:

image-20241216111148209

1.2 ue(v)解码过程

那怎么解码?其实可以直接在ITU-T Rec. H.264 (08/2024) Advanced video coding for generic audiovisual services文档的9.1 Parsing process for Exp-Golomb codes这里找到:

image-20241216111959120

当然,观察编码过程其实也能看出这个规律。其中leadingZeroBits为中间1前面,0的个数。所以在解码的时候,如果遇到描述为ue(v),则可以先数0的个数,数到1为止,其中0的个数即为leadingZeroBits。而公式中的read_bits( leadingZeroBits ),则为从中间1开始,往后顺序数leadingZeroBits个比特位。利用这个公式,就可以计算出codeNum的值。

image-20241216114101208

1.3 实例分析

例如下面有一个SPS帧:

img

具体参数什么含义看前面的SPS帧的相关笔记,这里分析几个ue(v)的数据来深入了解一下这个编解码的过程。

1.3.1 00 00 00 01 67

1
2
00 00 00 01 : start code
67 : nalutype=7 sps

1.3.2 4D 00 29

image-20241216130808284
1
2
4D          : profile_idc=0x4D(77=main profile)
00 29 : level_idc=0x29(41就是4.1)

1.3.3 8D

其实到这里就是要解完才知道是到哪个字节了,因为这里开始就有一个ue(v)指数哥伦布编码的成员了:

image-20241216131110023
1
8D = 1000 1101

根据指数哥伦布编码的原理,首个1bit是seq_parameter_set_id编码后的数据,前面0个0,所以这里不需要向后读取,这里就是2^0-1+0=0,所以seq_parameter_set_id=0。

继续解下一个成员的值,看这里其实seq_parameter_set_id后面的成员受到profile_idc的影响,上面profile_idc = 77,不在这里所以这里的if不成立,直接跳到:

image-20241216134611596

根据SPS成员的定义,后面还是一个ue(v)的数据,这个时候就是解析000 1101,发现1前面有3个0,所以从第一个1后面读3位,就是101,也就是5,所以code_num就是2^3-1+5=12。所以log2_max_frame_num_minus4 = 12。

这样8D这个数据就解析完了。

1.3.4 8D

接下来的数据还是8D,上面解析完后,接下来还是个ue(v)类型的:

image-20241216134819478
1
8D = 1000 1101

所以第一个bit就是pic_order_cnt_type的值,这里pic_order_cnt_type=0,后面继续解log2_max_pic_order_cnt_lsb_minus4的值,它也是一个ue(v)类型的,所以这里就是继续解析000 1101,前面计算过了,就是12,所以这里的值也是12,即log2_max_pic_order_cnt_lsb_minus4=12.

2. se(v)

se(v)也称有符号指数哥伦布编码,所以当描述字为se(v)时,它的输出有可能为负。而且当描述字为se(v)时,它的输入为ue(v)解码过程解析出来的codeNum。意思是什么呢?如果遇到se(v),需要先调用ue(v),得出codeNum的值。然后调用se(v)的解析过程,se(v)的输出即为语法元素的值。

2.1 se(v)编码

这个se(v)编码相关的东西就没去研究了,根据解码的过程,应该是先把符号取消,然后按照u(ve)编码的方式进行编码。

2.1 se(v)解码说明

主要还是关注解码的过程,在ITU-T Rec. H.264 (08/2024) Advanced video coding for generic audiovisual services的9.1.1 Mapping process for signed Exp-Golomb codes有说明:

image-20241216140628231

如上表所示,表中第一列codeNum为输入,第二列为输出。计算公式则为:

1
语法元素值 = (−1)k+1 Ceil( k÷2 )

其中Ceil为向上取整,k为codeNum的值,代入即可计算出语法元素的值。

参考资料:

h264编码概述八(哥伦布编码ue(v))-CSDN博客

Exp-Golomb 指数哥伦布编码-CSDN博客

指数哥伦布编码 - TaigaComplex - 博客园

H.264学习笔记6——指数哥伦布编码 - DwyaneTalk - 博客园

Golomb及指数哥伦布编码原理介绍及实现 - Brook_icv - 博客园