更多文章请访问 自己动手写 H.264 解码器
在上一章节,我们介绍了 NALU 层的相关细节,并且简单介绍了 SPS 和 PPS 的概念。我们知道,解码器在解码一路码流的时候,总是要首先读入 SPS 和 PPS。那么我们本章就来详细介绍 SPS 和 PPS。
SPS 和 PPS 里面存放了解码需要的参数,我们首先要做的就是把码流里的这些参数给读出来。在读取之前,我们先得知道几件事。
在 H.264 中,指数哥伦布编码又分成了 4 种:
我们先来介绍前两种:
我们先来看看如何使用无符号指数哥伦布进行编码:
最后,4 进行无符号指数哥伦布编码之后得到的二进制码流就是 0 0 1 0 1。
其实前两步还是比较好理解的,但是第三步,为什么要补这个 0 呢?明明 1 0 1 就可以表示这个数字了,为什么还要多牺牲两个 bit 的空间来补 0 呢?我们来看一个例子:
假设我们有两个数字,4 和 5,我们想要将这两个数字编码成一路二进制数据。我们利用上面提到的步骤来进行一下编码。
首先是 4,编码后的码流是 1 0 1(未经过补零)。
然后是 5,编码后的码流是 1 1 0(未经过补零)。
然后我们把这两组二进制数据收尾相连,得到以下码流:
1 0 1 1 1 0
大家立刻就会发现,这个样子的码流,因为压根就没办法知道里面到底编码了几个数字,也没法知道每个数字编码之后的数据长度,所以也根本没有办法进行解码,那么一个不能解码的码流,是没有任何意义的。
那么这时候我们再来看补零的操作,其实就是指明了码流的长度,在解码的时候,先读零,读到的几个连续的 0,就可以推断出码流的长度,由此就可以成功解码。
我们再来看看上面的例子:
首先是 4,编码后的码流是 0 0 1 0 1(经过补零)。
然后是 5,编码后的码流是 0 0 1 1 0(经过补零)。
然后我们把这两组二进制数据收尾相连,得到以下码流:
0 0 1 0 1 0 0 1 1 0
接下来我们尝试解码:
我们再来看看如何使用无符号指数哥伦布进行编码:
同样的,有符号指数哥伦布熵编码的解码方式和无符号指数哥伦布熵编码是非常像的,我们以 0 0 0 1 0 1 1 为例来看看如何解码
在说明映射指数哥伦布熵编码 me(v) 之前,我们先来尝试用无符号指数哥伦布熵编码两个数字。
我们先来编码数字 5。得到的码流是 0 0 1 1 0,占用 5 个 bit 的空间。
我们再来编码数字 47。得到的码流是 0 0 0 0 0 1 1 0 0 0 0,占用了 11 个 bit 的空间。
我们发现,指数哥伦布熵编码有个特性,那就是数字越大,占用的空间将会越大。那么如果我们要编码的数字集中在某一个区间比较小的范围,而这个范围内的数字又比较大,有没有什么办法能够节省一些空间呢?
为了解决这个问题,就出现了映射指数哥伦布熵编码。其实映射指数哥伦布熵编码的原理特别简单。映射指数哥伦布熵编码提供了一个码表,当你遇到一段码流的时候,你要先用无符号指数哥伦布熵编码进行解码,然后得到的结果其实是一个码表的索引,例如,你解码出的数字是 2,那么你到码表中,找到角标是 2 的元素出来就是最后的结果。
对于不同的情况,映射指数哥伦布熵编码可能会选择不同的码表,我们后面遇到具体情况的时候,再介绍码表应该如何选择。
截断指数哥伦布熵编码要解决的问题其实和映射指数哥伦布熵编码要解决的问题差不多。
当语法元素以截断指数哥伦布解码时,首先需要判断的是语法元素的取值范围,假定为0, x, x≥1。根据x的取值情况,语法元素根据不同情况进行解析。若 x>1,解析方法同无符号指数哥伦布熵编码相同。若 x=1 ,语法元素值等同于下一位bit值的取反。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。