CABAC总结与补充讨论
在之前的一篇文章CABAC中我们已经对算法中的大部分细节部分做了详细分析,这里做一个总结与拾遗。
总结
CABAC的编码可以分为以下四个部分:
- 上下文变量的初始化
- 待编码语法元素二值化
- 上下文建模(确定上下文索引)
- 算术编码
本文的主要目的就是阐明CABAC是如何把这四个部分串联起来的。
在编码一个slice的slice data之前,需要根据该slice的sliceQP对上下文变量进行初始化。
CABAC编码的是语法元素中slice data部分,也就是一个码流中的主体部分。在h.264语法结构当中,我们已得知一个slice是由slice头部、数据、尾部组成的。那么在进行CABAC编码时,slice data中的所有语法元素全部都会被进行二值化处理,得到二进制串,这些二进制串就是进行二进制算术编码的原料。

二进制算术编码会对该slice data中的所有语法元素的二进制串的每一个bit进行编码,按照算术编码的原理,编码得到的结果是一个小数,而该小数就代表了码流中的slice data的数据。

由于CABAC是自适应编码,也就是概率会随着0、1的出现而调整。具体来说,语法元素在二值化转换成二进制串后,一个位置的bit为0或者1将会影响之后该位置出现的0、1的概率。

如上图,第一个prev_intra4x4_pred_mode_flag的bit为1,这将影响ctxIdx=68的上下文(概率),在编码下一个prev_intra4x4_pred_mode_flag时的将会采用已被改变的ctxIdx=68的上下文;rem_intra4x4_pred_mode的三个bit共用一个ctxIdx=69的上下文,这表明在该语法元素的第一个bit将会影响其后面的bit的概率。
CABAC的算术编码补充讨论
重归一化
我们在之前的文章中讨论过CABAC在算术编码一个符号之后是如何输出其编码结果的,如下图。

这张图能很好地概括重归一化流程,不过仅仅执行重归一化流程并不能得到算术编码的结果。以上述的0.0x为例,算术编码的结果应该是得到一个位于区间R内的小数,而上述流程仅会输出”.0”,这显然还不是最终结果。
如果把最终结果的小数分为已确定部分与未确定部分,那么重归一化之后输出的就是已确定部分。举个例子来说就是:如果确定了R处于区间[0.010,0.011),那么0.01就是已确定部分,后来输入的符号无法修改到这部分。随着编码更多的符号,输出的bit会增多,也就是已确定部分会越来越多,越来越接近算术编码的最终结果。那么在编码完最后一个符号之后,执行重归一化,剩下的未确定部分该怎么确定?

EncodeFlush
剩下的未确定部分由EncodeFlush来确定。EncodeFlush有如下流程:

当编码mb_type的binIdx=1的bin或者end_of_slice_flag时ctxIdx = 276,此时会调用EncodeTerminate。如果mb_type的binIdx=1的bin为1,表明此时mb_type=I_PCM;如果end_of_slice_flag=1,表明此时处于slice的末尾。这两种情况下会进入Yes分支,并且进入EncodeFlush。
首先更新L:
$L = L + R$
此时$R=2$,只有$L$或者$L+1$是在区间$R$之内,也就是说只要把这两个值的其中一个写入码流内即可得到最终结果。最终的这次编码需要输出十个bit。

不过我们按照标准中的流程来分析,在选取$R=2$以及更新$L$后,执行了重归一化。重归一化使得$R = R<<7 = 2^8$。按照重归一化的流程,每次对$R$进行左移都会确定一个bit的输出,$R$左移了7次,因此输出了7个bit,剩下3个bit。

随着$R$的左移,$L$也左移了7次:$L << 7 $,只是$L$在重归一化过程中可能会进行$-2^8$或$-2^9$的操作。这意味着在重归一化之后,$L$肯定落在$2^7$的倍数点上。

按照EncodeFlush的流程,剩下的三个bit输出如上图。EncodeFlush首先调用PutBit输出第一个bit,PutBit可以把之前的累积的bitsOutStanding进行输出。然后调用WriteBits输出第二、三个bit。WriteBits会把第三个bit固定写1,在编码end_of_slice_flag时,该bit会被当作rbsp_stop_one_bit,关于rbsp_stop_one_bit请查看h.264语法结构分析。
CABAC总结与补充讨论的更多相关文章
- CABAC
CABAC(Context-based Adaptive Binary Arithmetic Coding),基于上下文的自适应二进制算术编码.CABAC是H.264/AVC标准中两种熵编码中的一种, ...
- 任意多边形切割/裁剪(附C#代码实现)
本实现主要参考了发表于2003年<软件学报>的<一个有效的多边形裁剪算法>(刘勇奎,高云,黄有群)这篇论文,所使用的理论与算法大都基于本文,对论文中部分阐述进行了详细解释,并提 ...
- 1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例)
前言 在上一篇0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架中,我已经介绍了这个轻型框架的层次结构,在下面的这篇文章中,我将以教师登陆功能为例,具体来扩充下我的core层的代 ...
- 四极耳机接线标准,N版耳机改造为i版耳机
(本文提到的都是3.5mm的耳机,2.5mm的没做验证) 现在的手机,以及大多数笔记本都开始使用“四极耳机”,也就是耳机上插头上有四个极.为了叙述方便,将耳机插头上的四个极从插头顶端到靠近电线的塑胶部 ...
- 对象布局已知时 C++ 对象指针的转换时地址调整
在我调试和研究 netscape 系浏览器插件开发时,注意到了这个问题.即,在对象布局已知(即对象之间具有继承关系)时,不同类型对象的指针进行转换(不管是隐式的从下向上转换,还是强制的从上到下转换)时 ...
- memset 的实现分析
memset 是 msvcrt 中的一个函数,其作用和用途是显而易见的,通常是对一段内存进行填充,就其作用本身不具有任何歧义性.但就有人一定要纠结对数组的初始化一定要写成如下形式: int a[... ...
- SSO之CAS单点登录详细搭建教程
本教程是我个人编写,花费几个小时的时间,给需要学习的人员学习使用,希望能帮助到你们. [环境说明]:本文演示过程在同一个机器上的(也可以在三台实体机器或者三个的虚拟机上),环境如下: windows7 ...
- 使用JAVASCRIPT实现静态物体、静态方法和静态属性
Javascript语言的面向对象特征非常弱.其它面向对象语言在创建类时仅仅要使用keywordstatic就可以指定类为静态类,Javascript没有提供static这种keyword.要让Jav ...
- PowerShell管道入门,看看你都会不(管道例子大全)
PowerShell的一个重中之重的功能就是管道(pipeline),本文从浅入深,一步一步详解管道的使用方法和例子,来看看有没有你所不知道的吧,如果全知道,恭喜你已经很厉害啦--适用于所有Power ...
随机推荐
- 2-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案数据篇(数据库简单说明)
1-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案数据篇(视频总揽) 这里有个教程 http://www.cnblogs.com/best/p/6517755.h ...
- 【原创】从策略模式闲扯到lambda表达式
引言 策略模式,讲这个模式的文章很多,但都缺乏一个循序渐进的过程.讲lambda表达式的文章也很多,但基本都是堆砌一堆的概念,很少带有自己的见解.博主一时兴起,想写一篇这二者的文章.需要说明的是,在看 ...
- Spring+Struts2+Hibernate框架整合流程
一:基本步骤 新建Maven项目,导入相关依赖(推荐) 在WEB-INF的web.xml中进行配置 ————–Hibernate配置 —————- 创建entity包,创建数据库相关实体类 根据实体类 ...
- 使用redis实现生产者消费者模式
本次主要分享一下使用redis做缓存队列,实现生产者消费者模式. 首先先来看一下redis提供的列表操作接口.像ListRightPush就和符合队列先进先出的原则. 然后围绕这个列表已下单为例简要实 ...
- Unix / Linux 线程的实质
线程与进程的比较 概述: 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小 ...
- ES6 Promise 详解
一.概念 Promise,从语法上来讲,它是一个对象,是一个构造函数,可以获取 异步操作 的信息. 简单来讲,就是用同步的方式写异步代码,用来解决回调问题. 二.特点 Promise 对象有两个特点: ...
- js中的join(),reverse()与 split()函数用法解析
<script> /* * 1:arrayObject.reverse() * 注意: 该方法会改变原来的数组,而不会创建新的数组.此函数可以将数组倒序排列 * 2:arrayObject ...
- 未能加载文件或程序集"Newtonsoft.Json, Version=4.5.0.0
这问题遇到好几次了,重新更改了引用都不好使,有的时候版本改成一致就好了,但是有的地方你不知道在哪里用了就不好排查,所性在config里面加个配置让程序运行的时候去处理得了~ 很实用,放在configu ...
- Jmeter之上传数据流(图片、文本等)请求
MIME类型~Content-Type: 参数名称~name
- Linux watchdog
使用 watchdog 构建高可用性的 Linux 系统及应用https://www.ibm.com/developerworks/cn/linux/l-cn-watchdog/index.html ...