当前位置: 首页 > news >正文

基于上下文自适应可变长熵编码 CAVLC 原理详细分析

CAVLC

CAVLC,即Context-Adaptive Variable-Length Coding,是一种用于视频压缩的编码技术,特别是在MPEG-4视频编码标准中使用。CAVLC是一种熵编码方法,它根据视频数据的上下文信息来调整编码长度,以实现更有效的数据压缩。

CAVLC的主要特点包括:

  1. 上下文适应性:编码器会根据视频帧中的特定上下文来选择最合适的编码长度,例如在图像的平坦区域使用较短的编码,而在边缘区域使用较长的编码。
  2. 可变长度编码:编码的长度不是固定的,而是根据数据的统计特性来确定,这有助于进一步压缩数据。
  3. 效率:CAVLC提供了比固定长度编码更高的压缩效率。

CAVLC通常用于视频编码的残差数据部分,即在变换编码(如DCT)之后,用于编码变换系数。这种编码方式可以显著减少编码后数据的比特率,从而提高视频传输和存储的效率。

CAVLC原理

相关名词解释

  • TotalCoeffs :非零系数,代表ZigZag扫描后序列中非0值的个数;取值 0~16。
  • TrailingOnes :拖尾系数,代表ZigZag扫描后序列中+1,和-1的总个数,取值0~3,如果超过3,则为3,在ZigZag扫描序列中从右到左选取三个,作为拖尾系数,其余的系数就当普通的非零系数;TotalCoeffs和TrailingOnes是通过查表方式,共有4 个变长表格和 1 个定长表格;其中定长表格是6 个比特长,高 4 位表示TotalCoeffs,低 2 位表示TrailingOnes。
  • TotalZeros: 编码最后一个非零系数前零的数目。
  • NC:当前块值,用来决策coeff如何编码的变量; 上述的 5 个表格的选择就是根据 NC 值来决定的。
  • ZerosLeft: 当前系数之前所有的0的个数,其初始值等于TotalZeros。
  • RunBefore: 编码每个非零系数前0的个数。
  • Levels:编码除了拖尾系数之外的非零系数的幅值。

NC 计算

  • 该值的求解过程中,体现了基于上下文的思想。除了色度的直流系数外,其它系数类型的 NC 值是根据当前块左边 4x4 块的非零系数数目(NA)和当前块上面 4x4 块的非零系数数目(NB)求得的。当输入的系数是色度的直流系数时,NC = -1。求 NC 的过程见表 6.10,X 表示与当前块同属于一个片并可用。 选择非零系数数目和拖尾系数数目的编码表格的过程见表 6.11 。
    在这里插入图片描述

Levels 计算

  • 非零系数的幅值(Levels)的组成分为两个部分,前缀(level_prefix)和后缀(level_suffix)。levelSuffixsSize 和 suffixLength 是编码过程中需要使用的两个变量。后缀是长度为 LevelSuffixsSize 位的无符号整数。通常情况下变量 levelSuffixsSize 的值等于变量 suffixLength 的值,有两种情况例外:
    • 当前缀等于 14 时,suffixLength 等于 0,levelSuffixsSize 等于 4。
    • 当前缀等于 15 时,levelSuffixsSize 等于 12。
  • 变量 suffixLength 是基于上下文模式自适应更新的,suffixLength 的更新与当前的 suffixLength 的值以及已经解码好的非零系数的值(Level)有关。suffixLength 数值的初始化以及更新过程如下所示:
    • 普通情况下 suffixLength 初始化为 0,但是当块中有多于 10 个非零系数并且其中拖尾系数的 数目少于 3 个,suffixLength 初始化为 1。
    • 编码在最高频率位置上的非零系数。
    • 如果当前已经解码好的非零系数值大于预先定义好的阈值,变量 suffixLength 加 1。 决定是否要将变量 suffixLength 的值加一的阈值如表 3 所示。第一个阈值是 0,表示在第一个非零系数被编码后,suffixLength 的值总是增加 1。
      在这里插入图片描述
  • Levels 的算法过程
  • 将有符号变成无符号:如果level > 0: levelcode = level << 1 - 2 如果level < 0: levelcode = -(level << 1) - 1 ;(上面的公式对应句法也就是把正数转换为偶数,负数转换为奇数。比如level=1时,levelcode=0,level=-1,levelcode=1)。
  • 根据level_prefix 码表进行查表: level_prefix = levelcode / (1 << suffix_length) 得到level_prefix之后通过查表即可以获得对应该如何编码。(在句法中,有 levelCode = level_prefix << suffix_length,进行转换,就可以得到上面的公式)。
  • Suffix_length表示的是level编码后缀的长度,后缀用0填充,长度为多少就填充多少个0。初始值为0,如果非零系数 > 10且 拖尾数目 < 1的时候,suffix_length初始值为1,if(suffix_length == 0) suffix_length++; else if(level > 3 << (suffix_length - 1) && suffix_length < 6) suffix_length++
    在这里插入图片描述
    在这里插入图片描述

CAVLC示例

  1. 编码残差数据经过变换量化后的4x4 块矩阵举例如下:
    在这里插入图片描述
  2. 量化后矩阵系数有负数的原因:因为在变换前,一般字节的值在 0~255,为了减少像素绝对值的波动,先把数值移位一下,变成-128~127;这样就出现了负数,移位之后再进行变换和量化操作。
  3. 对 4x4 矩阵进行 zigzag 扫描:0、0、5、3、2、-1、0、0、0、1、0、0、0、0、0、0
  4. TotalCoeffs = 5
  5. TrailingOnes = 2
  6. TotalZeros = 5
  7. NC = 3 (假定)
  8. 编码coeff_token:根据TotalCoffes,TrailiingOnes以及NC而确定;确定coeff_token编码为 0000101
    在这里插入图片描述
  9. 编码TrailingOnes:标志位符号Trailing_ones_sign_flag 中 0 表示 +1,1 表示 -1,从右到左依次编码为 01
  10. 编码除拖尾以外的非零系数的Levels:按照 zigzag 的逆序,从右向左。
  • 编码“2”:levelcode = 2 << 1 - 2 = 2; level_prefix = 2 / (1 << 0) = 2; 此时suffix_length == 0,没有后缀,同时suffix_length++,suffix_length = 1. 查表,level_prefix = 2时,编码为“001”,且suffix_length = 0,无后缀,此时编码为:001
  • 编码“3”: levelcode = 3 << 1 - 2 = 4; level_prefix = levelcode / (1 << suffix_length) = 4 / (1 << 1) = 2 ; level_prefix = 2, 编码为“001”,且suffix_length = 1, 填充 1 位“0”,根据公式:if(suffix_length == 0) suffix_length++; else if(level > 3 << (suffix_length - 1) && suffix_length < 6) suffix_length++ ;条件不成立,则此时suffix_length不需要累加 1,suffix_length依旧等于 1,此时编码为:0010
  • 编码"5": levelcode = 5 << 1 - 2 = 8; level_prefix = levelcode / (1 << suffix_length) = 8 / (1 << 1) = 4 ; level_prefix = 4,suffix_length = 1,此时, 编码为“00001”,且此时suffix_length == 1, 填充1位“0”, 根据公式,条件成立,suffix_length需要累加1;suffix_length = 2,最终编码为:000010
  1. 编码最后一个非零系数前的0的个数TotalZeros: 此时TotalZeros = 5, TotalCoeffs = 5, 查第一张表,因为TotalZeros=5,所以此时的编码为 101
    在这里插入图片描述
  2. 对每个非零系数前零的个数RunBefore进行编码,依旧采用ZigZag反序:
  • RunBefore 在以下两种情况下是不需要编码的:
    • 最后一个非零系数(在低频位置上)前零的个数;
    • 如果没有剩余的零需要编码(Σ[RunBefore]=TotalZeros)时,没有必要再进行 RunBefore 的编码;
  • 按照ZigZag逆序分别为 1, -1, 2, 3, 5,查表;
    • 对1编码: zerosLeft = 5, run_before = 3, 编码为010
    • 对-1编码: zerosLeft = 2, run_before = 0, 编码为1
    • 对2编码: zerosLeft = 2, run_before = 0, 编码为1
    • 对3编码: zerosLeft = 2, run_before = 0, 编码为1
    • 对5编码: zerosLeft = 2, run_before = 0, 最后一个系数不需要编码。
      在这里插入图片描述
  1. 最终的CAVLC熵编码之后码流为:0000101010010010000010101010111

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 03Spring底层架构核心概念解析
  • 亲测--linux下安装ffmpeg最新版本---详细教程
  • 自适应键盘,自带隐藏键盘的输入框(UITextField)
  • 异常:android.os.NetworkOnMainThreadException 原因分析
  • 【Elasticsearch】Elasticsearch 中的节点角色
  • 前端面试题日常练-day95 【Less】
  • JVM:GraalVM
  • 如何在 Linux 中解压 ZIP 文件
  • 多口适配器,给您的生活增添便利
  • Rust编程-类面向对象编程
  • “轻、灵、画、韵”,TCL第三代艺术电视引领艺术生活
  • 面向对象练习题
  • 玄机-第二章日志分析-mysql应急响应
  • LeetCode题(66,69,35,88)--《c++》
  • Ubuntu编译ffmpeg并添加cmake工程
  • CSS居中完全指南——构建CSS居中决策树
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • hadoop集群管理系统搭建规划说明
  • mysql 5.6 原生Online DDL解析
  • open-falcon 开发笔记(一):从零开始搭建虚拟服务器和监测环境
  • php中curl和soap方式请求服务超时问题
  • Sass 快速入门教程
  • vue-cli在webpack的配置文件探究
  • vue-router 实现分析
  • 从输入URL到页面加载发生了什么
  • 高程读书笔记 第六章 面向对象程序设计
  • -- 数据结构 顺序表 --Java
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • 从如何停掉 Promise 链说起
  • ​【数据结构与算法】冒泡排序:简单易懂的排序算法解析
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • #etcd#安装时出错
  • #if 1...#endif
  • $(this) 和 this 关键字在 jQuery 中有何不同?
  • (C语言)编写程序将一个4×4的数组进行顺时针旋转90度后输出。
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (附源码)php新闻发布平台 毕业设计 141646
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (论文阅读40-45)图像描述1
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (四) Graphivz 颜色选择
  • (转)一些感悟
  • .htaccess配置重写url引擎
  • .net core docker部署教程和细节问题
  • .NET/C# 使窗口永不获得焦点
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .net连接oracle数据库
  • :“Failed to access IIS metabase”解决方法
  • @ 代码随想录算法训练营第8周(C语言)|Day57(动态规划)
  • @AutoConfigurationPackage的使用
  • @JsonSerialize注解的使用
  • @SuppressLint(NewApi)和@TargetApi()的区别
  • @TableId注解详细介绍 mybaits 实体类主键注解