在之前的一篇文章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总结与补充讨论的更多相关文章

  1. CABAC

    CABAC(Context-based Adaptive Binary Arithmetic Coding),基于上下文的自适应二进制算术编码.CABAC是H.264/AVC标准中两种熵编码中的一种, ...

  2. 任意多边形切割/裁剪(附C#代码实现)

    本实现主要参考了发表于2003年<软件学报>的<一个有效的多边形裁剪算法>(刘勇奎,高云,黄有群)这篇论文,所使用的理论与算法大都基于本文,对论文中部分阐述进行了详细解释,并提 ...

  3. 1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例)

    前言 在上一篇0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架中,我已经介绍了这个轻型框架的层次结构,在下面的这篇文章中,我将以教师登陆功能为例,具体来扩充下我的core层的代 ...

  4. 四极耳机接线标准,N版耳机改造为i版耳机

    (本文提到的都是3.5mm的耳机,2.5mm的没做验证) 现在的手机,以及大多数笔记本都开始使用“四极耳机”,也就是耳机上插头上有四个极.为了叙述方便,将耳机插头上的四个极从插头顶端到靠近电线的塑胶部 ...

  5. 对象布局已知时 C++ 对象指针的转换时地址调整

    在我调试和研究 netscape 系浏览器插件开发时,注意到了这个问题.即,在对象布局已知(即对象之间具有继承关系)时,不同类型对象的指针进行转换(不管是隐式的从下向上转换,还是强制的从上到下转换)时 ...

  6. memset 的实现分析

    memset 是 msvcrt 中的一个函数,其作用和用途是显而易见的,通常是对一段内存进行填充,就其作用本身不具有任何歧义性.但就有人一定要纠结对数组的初始化一定要写成如下形式: int a[... ...

  7. SSO之CAS单点登录详细搭建教程

    本教程是我个人编写,花费几个小时的时间,给需要学习的人员学习使用,希望能帮助到你们. [环境说明]:本文演示过程在同一个机器上的(也可以在三台实体机器或者三个的虚拟机上),环境如下: windows7 ...

  8. 使用JAVASCRIPT实现静态物体、静态方法和静态属性

    Javascript语言的面向对象特征非常弱.其它面向对象语言在创建类时仅仅要使用keywordstatic就可以指定类为静态类,Javascript没有提供static这种keyword.要让Jav ...

  9. PowerShell管道入门,看看你都会不(管道例子大全)

    PowerShell的一个重中之重的功能就是管道(pipeline),本文从浅入深,一步一步详解管道的使用方法和例子,来看看有没有你所不知道的吧,如果全知道,恭喜你已经很厉害啦--适用于所有Power ...

随机推荐

  1. Maven学习第2期---Maven安装配置

    一.Maven介绍 1.1 何为Maven Maven这个词可以翻译为"知识的积累",也可以翻译为"专家"或"内行".Maven是一个跨平台 ...

  2. python实战案例--银行系统

    stay hungry, stay foolish.求知若饥,虚心若愚. 今天和大家分享一个python的实战案例,很多人在学习过程中都希望通过一些案例来试一下,也给自己一点动力.那么下面介绍一下这次 ...

  3. configure: error: cannot guess build type; you must specify one解决方法

    原文地址:https://blog.csdn.net/hebbely/article/details/53993141 1.configure: error: cannot guess build t ...

  4. Filebeat简介

    原文地址:http://blog.51cto.com/seekerwolf/2110174 收集日志的目的是有效的利用日志,有效利用日志的前提是日志经过格式化符合我们的要求,这样才能真正的高效利用收集 ...

  5. BeautifulSoup库

    '''灵活又方便的网页解析库,处理高效,支持多种解析器.利用它不用编写正则表达式即可方便的实现网页信息的提取.''' BeautifulSoup库包含的一些解析库: 解析库 使用方法 优势 劣势 py ...

  6. 03-Linux的shell命令 .doc

    快捷键 基本操作和命令 Cd转换文件夹 以/开头的是绝对路径 没有/相对路径 ../代表上一级目录 Tab补充 Ctrl+R 查找历史输入过的命令 箭头上也代表能够查询以往输入的命令 Ctrl+C 终 ...

  7. HashSet中存放不重复元素

    一.自定义对象存放在hashSet中,保证元素不重复.重写hashCode()和equals()方法 public class Student{ private String name; privat ...

  8. Notepad++快捷使用

    用Notepad++写代码,要是有一些重复的代码想copy一下有木有简单的方法呢,确实还是有的不过也不算太好用.主要是应用键盘上的 Home 键 和 End 键.鼠标光标停留在一行的某处,按 Home ...

  9. PHPUnit实践一(初识)

    PHPUnit实践一(初识)     本系列教程所有的PHPUnit测试基于PHPUnit6.5.9版本,Lumen 5.5框架 前置 日常我们的普通用到的测试: 代码直接echo,debug等方法测 ...

  10. [转帖]web安全:QQ号快速登录漏洞及被盗原理

    web安全:QQ号快速登录漏洞及被盗原理 https://www.cnblogs.com/1996V/p/7481823.html 看了下 QQ的确监听 端口 大神牛B 自己这一块一直没深入学习过.. ...