HM编码器代码阅读(21)——熵编码的概念以及在HEVC中应用

熵编码把一系列用于表示视频序列的元素符号转变为一个用来传输或存储的压缩码流。

信息的多少用信息量来度量,显然,信息量与不确定性的消除程度有关,消除的不确定性越大,信息量就越大。不确定性的大小与事件发生的概率相关,因此不确定性可以度量,更进一步信息量也可以度量。

假设某一个信源(就是产生信息的地方)的概率空间是:

X(表示信源产生的符号的集合),P(x)表示符号产生的概率的集合。

那么,某一个信源符号Xi的信息量就定义为:I(Xi)=log(1/P(Xi))。

那么这个信源的信息熵(即这个信源的包含的信息量)是各个信源符号的信息量的数学期望:E[I(Xi)]。

即熵可以表示信息量的大小。

对信源输出的信息采用某一种方法进行编码就是熵编码。通常的,有下面两种编码方法:

(1)变长编码(哈夫曼编码就是一种变长编码)是一种前缀编码(即任意一个码字都不是另一个码字的前缀)。其中应用比较广泛的是指数哥伦布编码。变长编码为信源的每一个信息都指定一个不同长度的码字。

(2)算术编码。算术编码的本质是为整个输入序列分配一个码字。因此平均意义上可以为单个字符分配长度小于1的码字。

指数哥伦布编码由前缀和后缀两部分构成,前缀和后缀都依赖于指数哥伦布码的阶数k。假设指数哥伦布码是N,阶数为k,下面是它的编码步骤:

(1)把N转换为二进制数,去掉最低的k个比特位,然后加上1

(2)计算留下的比特数,把这个数减去1,这就是需要增加的前缀0的个数

(3)把步骤(1)中去掉的k个比特位补回比特串的尾部。

假如N=4,k=1,那么:

(1)把N转成二进制即100,去掉后面的1个比特位后变成10,加上1就变成11

(2)11的比特位数是2,因此需要在前面加上(2-1)个0。变成011

(3)把去掉的比特位补上,即0110.

算数编码的步骤:

(1)起始的时候把当前区间[L,H)设置为[0,1)

(2)对每一个事件,编码器按照步骤a和b进行处理:

a)编码器把当前区间分成子区间,每个事件一个

b)一个子区间的大小与下一个将要出现的事件的概率成正比,编码器选择的子区间与下一个将要发生的事件相对应,并把它当作新的区间

(3)最后输出的当前区间的下边界就是该给定序列的的算数编码。

下面是一个例子:

假设信源符号是{A,B,C,D},这些符号发生的概率是{0.1,0.4,0.2,0.3},因此把区间[0,1)分成4个子区间:[0,0.1),[0.1,0.5),[0.5,0.7),[0.7,1)

在HEVC中,零阶指数哥伦布编码用于视频参数集(VPS)、序列参数集(SPS)、图像参数集(PPS)和片头信息的参数的编码。而CABAC(上下文自适应的二进制算术编码)则用于其他参数以及残差系数的编码。

零阶指数哥伦布编码:

(1)由前缀和后缀组成,前缀的长度和后缀的长度满足:Lprefix - Lsuffix = 1.

(2)前缀具有一元码的形式,即:000...001,其中零的个数M等于:

M=log2(CodeNum + 1);

CodeNum由待编码的符号V算出:如果V大于0,那么CodeNum = 2V-1,否则CodeNum=-2V。

(3)后缀部分就是下面数值的二进制:CodeNum+1-2^M

CABAC的三个基本的步骤是:

(1)二进制化。一般采用截断莱斯二进制化(TR)、定长码(FL)、指数哥伦布码(EGK)(注意它也可以用来进行二进制化)等方法;下面介绍两个方法。

①截断莱斯二进制化。已知门限值cMax,莱斯参数R,语法元素的值V。截断莱斯码由前缀和后缀拼接而成。

前缀值P=V>>R。如果P小于cMax>>R,那么前缀由P个1和一个0组成。如果P大于等于cMax>>R,则前缀由cMax>>R个1组成。

当语法元素V大于等于cMax的时候没有后缀,当V小于cMax的时候,后缀值S=V-(P<<R),后缀码是S的二元化串,长度是R。

②定长二进制化。直接转换成定长的二进制符号串。

(2)上下文建模。一般情况下,不同的语法元素之间并不是完全独立的,因此可以根据已经编码的语法元素进行条件编码,这就是所谓的上下文。这些上下文信息通常做成表格。

①在编码过程中,语法元素使用的上下文概率模型都被唯一的上下文索引号r标识,每一个r涉及两个概率模型变量:最大概率符号MPS和概率状态索引。MPS表示待编码的Bin很有可能出现的符号(0或1);与之对应的,待编码的Bin不可能出现的符号即为最小概率符号LPS。

②在CABAC中,为LPS的概率设置了64个代表值,每一个都与LPS一一对应。

③编码器会初始化上下文模型的除号变量MPS和

④在获取初始的概率模型变量后,即可对当前符号(或语法元素)进行二元算数编码和概率模型参数更新,实现上下文自适应的编码。

⑤更新的方法:如果编码的符号等于MPS,那么通过查表更新 =
transIdxMps();否则,如果为0,那么互换LPS和MPS然后更新,否则只更新=transIdxLps(

(3)二进制算术编码。有两种模式:常规模式,旁路模式。

1、常规模式。假设当前编码器的区间长度是R,区间下限是L。

①计算索引值=(R>>6)&3

②查表得到LPS对应的子区间=rangeTabLps[][],那么=-

③如果当前的二进制符号Bin等于MPS,则作为下一个符号的编码区间R,下限L不变;如果Bin等于LPS,那么作为下一个符号的编码区间R,区间下限L要加上的长度。然后更加当前符号值更新上下文。

2、旁路模式。这种模式无需对概率进行自适应更新,而是采用0和1概率各占0.5的固定概率进行编码。为了是区间划分更加简单,才用了保存编码区间长度不变,使下限L值加倍的方法来实现区间划分。

时间: 2024-10-11 17:12:10

HM编码器代码阅读(21)——熵编码的概念以及在HEVC中应用的相关文章

HM编码器代码阅读(22)——熵编码的初始化

入口函数:TEncSbac::resetEntropy: 这个函数的实质就是初始化各种上下文 // 重置熵编码器 Void TEncSbac::resetEntropy () { Int iQp = m_pcSlice->getSliceQp(); SliceType eSliceType = m_pcSlice->getSliceType(); Int encCABACTableIdx = m_pcSlice->getPPS()->getEncCABACTableIdx(); i

HM编码器代码阅读(18)——变换以及量化(一)

入口函数:encodeResAndCalcRdInterCU. 这个函数的作用是根据预测值,求出残差,然后进行TU的划分,然后进行变换.量化等操作以及RD代价的计算. 流程: (1)如果是帧内预测,那么直接返回 (2)判断是否使用skip模式,如果使用了: 1)对所有的子分割设置skip标志 2)清理残差 3)把预测的CU直接设置为重建的CU 4)计算率失真 5)加载SBAC熵编码器,并重置比特数 6)如果使用了跳过变换量化的标志(TransquantBypassEnableFlag),那么就对

HM编码器代码阅读(14)——帧间预测之二predInterSearch(inter模式)

predInterSearch主要的工作是ME(运动估计)和MC(运动补偿). 函数中有一个bTestNormalMC变量,它表示是否进行正常的MC过程,正常的MC过程就是进行ME再进行MC. 正常的MC流程是,遍历所有的参考帧,进行ME(运动估计:xEstimateMvPredAMVP和xMotionEstimation),然后记录AVP或者MV的信息,进行MC(运动补偿,目的是选出最优的参数),然后更新最优的参数,遍历完所有的参考帧之后,就选出了最优的参数了:然后循环结束,接着进行正式的MC

代码阅读问题

---恢复内容开始--- 下面列举阅读代码过程中遇到的问题和相应的资料查询: 1.namespace的用途:http://www.kuqin.com/language/20080107/3532.html 2.enum 的用途:http://pcedu.pconline.com.cn/empolder/gj/c/0502/562347.html 3.SFML:http://www.sfml-dev.org/ 4.双冒号的用法:http://blog.csdn.net/zimingjushi/ar

NRE代码阅读记录

本来是为了论证自己的观点,把安全标签打在RunningConfig里,就写了个代码分析,结果写着写着发现的确不应该是在RunningVM里.意外的发现看代码的时候这么写写还是挺不错的,也避免了看了后面的忘记前面的.这种底层的代码实在是很难理解,对我来说就像是小学生去算高数一样,也只能硬着头皮去看了. vmmng.cc对应的就是如下界面(回头放图上来,ubuntu下没有什么截图工具,总不能把整个屏幕放上来)然后"3"键可以新建tiny-core虚拟机,对应到代码里,也就是input_th

代码阅读分析工具Understand 2.0试用

Understand 2.0是一款源码阅读分析软件,功能强大.试用过一段时间后,感觉相当不错,确实能够大大提高代码阅读效率.因为Understand功能十分强大,本文不可能详尽地介绍它的全部功能,所以仅仅列举本人觉得比較重要或有特色的功能,以做抛砖引玉之举. Understand 2.0能够从http://www.scitools.com/下载到,安装后能够试用15天. 使用Understand阅读代码前,要先创建一个Project,然后把全部的源码文件增加到这个Project里.这里我创建了一

MediaInfo代码阅读

? MediaInfo是一个用来分析媒体文件的开源工具. 支持的文件非常全面,基本上支持所有的媒体文件. 最近是在做HEVC开发,所以比较关注MediaInfo中关于HEVC的分析与处理. 从MeidaInfo的官网上下载下来的代码比较庞大,工程比较多,但是代码阅读的一个关键在于,先要抓住主干,然后再不断的深入.先找到自己关注的地方,然后分析,之后再进行分析一些相关的代码. 此处下载的是mediainfo 0.7.72版本. 从下图可以看出,mediaInfo中包括了诸多的工程. ? 其中,Me

代码阅读之术一:结构与源流

代码阅读的目的是搞清代码的结构和功能: 组织结构是与耦合.功能相对应的概念: 困惑:软件的物理组织无法反映软件的逻辑结构: 大部分代码阅读是按照组件化编程的思想阅读的: 软件的阅读要按照:业务-〉功能--〉技术的路径考虑: 功能和业务是箭之的: 技术是木之根: 原文地址:https://www.cnblogs.com/feng9exe/p/10028437.html

《代码阅读方法与实践》阅读笔记之二

时间过得真快,一转眼,10天就过去了,感觉上次写阅读笔记的场景仿佛还历历在目.<代码阅读方法与实践>这本书真的很难写笔记,本来我看这本书的名字还以为书里大概写的都是些代码阅读的简易方法,心想着这就好写笔记了,没想到竟然好多都是我们之前学过的东西,这倒让我有点无从下手了.大概像我们这些还没有太多经历的大学生,总是习惯于尽量避免自己的工作量,总是试图找到一些完成事情的捷径吧.总之,尽管我不想承认,但我自己心里很清楚,我就是这种人.下面开始言归正传,说说接下来的几章内容归纳. 这本书在前面已经分析了