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帧:
可以看到里面就会出现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)编码过程
以待编码码号code_num = 3为例:
第一步:将code_num +1, 即3+1 = 4
第二步:将4写为二进制的形式:100
第三步:计算100的比特个数为3,在100前面写(3-1)个0,得到编码码字:00100
会发现里面有一些连续的码字是一样长的,可以总结如下:
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这里找到:
当然,观察编码过程其实也能看出这个规律。其中leadingZeroBits为中间1前面,0的个数。所以在解码的时候,如果遇到描述为ue(v),则可以先数0的个数,数到1为止,其中0的个数即为leadingZeroBits。而公式中的read_bits( leadingZeroBits ),则为从中间1开始,往后顺序数leadingZeroBits个比特位。利用这个公式,就可以计算出codeNum的值。
1.3 实例分析
例如下面有一个SPS帧:
具体参数什么含义看前面的SPS帧的相关笔记,这里分析几个ue(v)的数据来深入了解一下这个编解码的过程。
1.3.1 00 00 00 01 67
1 | 00 00 00 01 : start code |
1.3.2 4D 00 29
1 | 4D : profile_idc=0x4D(77=main profile) |
1.3.3 8D
其实到这里就是要解完才知道是到哪个字节了,因为这里开始就有一个ue(v)指数哥伦布编码的成员了:
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不成立,直接跳到:
根据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)类型的:
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有说明:
如上表所示,表中第一列codeNum为输入,第二列为输出。计算公式则为:
1 | 语法元素值 = (−1)k+1 Ceil( k÷2 ) |
其中Ceil为向上取整,k为codeNum的值,代入即可计算出语法元素的值。
参考资料: