【H.264/AVC视频编解码技术详解】十三、熵编码算法(3):CAVLC原理

2023-10-27

《H.264/AVC视频编解码技术详解》视频教程已经在“CSDN学院”上线,视频中详述了H.264的背景、标准协议和实现,并通过一个实战工程的形式对H.264的标准进行解析和实现,欢迎观看!

“纸上得来终觉浅,绝知此事要躬行”,只有自己按照标准文档以代码的形式操作一遍,才能对视频压缩编码标准的思想和方法有足够深刻的理解和体会!

链接地址:H.264/AVC视频编解码技术详解

GitHub代码地址:点击这里


上下文自适应的变长编码(Context-based Adaptive Variable Length Coding, CAVLC)

1. 引言

在前述的几章节的博文/视频中,我们已经了解到熵编码是利用信息的统计冗余进行数据压缩的无损编码方法,并且已经讨论过了熵编码的基本原理、H.264中使用的语法元素解析算法“指数哥伦布编码”的算法与实践:

在我们已经实现的H.264码流结构(如NAL Unit、Slice Header等)的解析中,大多使用定长编码或者指数哥伦布编码实现。而例如预测残差等占据码流大量体积的数据则必须使用压缩率更高的算法,如CAVLC和CABAC等。前者是我们将在本文中讨论的内容,后者将在后续内容中详述。

2. CAVLC的基本原理

我们知道,CAVLC的全称叫做“上下文自适应的变长编码Context-based Adaptive Variable Length Coding”。所谓“上下文自适应”,说明了CAVLC算法不是像指数哥伦布编码那样采用固定的码流-码字映射的编码,而是一种动态编码的算法,因而压缩比远远超过固定变长编码UVLC等算法。

在H.264标准中,CAVLC主要用于预测残差的编码。在本系列第二篇博文中我们给出了H.264的编码流图,其中可知,熵编码的输入为帧内/帧间预测残差经过变换-量化后的系数矩阵。以4×4大小的系数矩阵为例,经过变换-量化后,矩阵通常呈现以下特性:

  1. 经过变换量化后的矩阵通常具有稀疏的特性,即矩阵中大多数的数据已0为主。CAVLC可以通过游程编码高效压缩连续的0系数串;
  2. 经过zig-zag扫描的系数矩阵的最高频非0系数通常是值为±1的数据串。CAVLC可以通过传递连续的+1或-1的长度来高效编码高频分量;
  3. 非零系数的幅值通常在靠近DC(即直流分量)部分较大,而在高频部分较小;
  4. 矩阵内非0系数的个数同相邻块相关;

鉴于上述的特性3和4,针对待编码的系数在系数矩阵中不同的位置,以及相邻块的有关信息,在编码时采用不同的码表进行编码。CAVLC的这种特性,体现了命名中的“上下文自适应”的方法。

3. CAVLC的编码流程

在CAVLC中,熵编码不是像哈夫曼编码等算法一样针对某一个码元进行编码,而是针对一个系数矩阵进行。假设我们希望对一个如下变换系数块进行CAVLC编码:

{
	3,	2, -1,	0,
	1,	0,	1,	0,
	-1,	0,	0,	0,
	0,	0,	0,	0,
}

对于一个4×4大小的变换系数矩阵进行CAVLC编码,首先需要对其进行扫描,将二维矩阵转化为一维数组。如前一节所讲,扫描按照zig-zag顺序进行,即按照如下顺序:
在这里插入图片描述

因此,扫描之后变换系数将进行重新排列,得到的结果为:

[3, 2, 1, -1, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]

在编码过程中需要注意以下重要的语法元素:

  • 非零系数的个数(TotalCoeffs):取值范围为[0, 16],即当前系数矩阵中包括多少个非0值的元素;
  • 拖尾系数的个数(TrailingOnes):取值范围为[0, 3],表示最高频的几个值为±1的系数的个数。拖尾系数最多不超过3个,若超出则只有最后3个被认为是拖尾系数,其他被作为普通的非0系数;
  • 拖尾系数的符号:以1 bit表示,0表示+,1表示-;
  • 当前块值(numberCurrent):用于选择编码码表,由上方和左侧的相邻块的非零系数个数计算得到。设当前块值为nC,上方相邻块非零系数个数为nA,左侧相邻块非零系数个数为nB,计算公式为nC = round((nA + nB)/2);对于色度的直流系数,nC = -1;
  • 普通非0系数的幅值(level):幅值的编码分为prefix和suffix两个部分进行编码。编码过程按照反序编码,即从最高频率非零系数开始。
  • 最后一个非0系数之前的0的个数(TotalZeros);
  • 每个非0系数之前0的个数(RunBefore):按照反序编码,即从最高频非零系数开始;对于最后一个非零系数(即最低频的非零系数)前的0的个数,以及没有剩余的0系数需要编码时,不需要再继续进行编码。

在上述各类型数据中,编码非零系数的level相对最为复杂。其主要过程为:

  1. 确定suffixLength的值:
    • suffixLength初始化:通常情况下初始化为0;当TotalCoeffs大于10且TrailingOnes小于3时,初始化为1;
    • 若已经编码好的非零系数大于阈值,则suffixLength加1;该阈值定义为3 << ( suffixLength − 1 );编码第一个level后,suffixLength应加1;
  2. 将有符号的Level值转换为无符号的levelCode:
    • 若level > 0,levelCode = (level << 1) - 2;
    • 若level < 0,levelCode = -(level << 1) - 1;
  3. 编码level_prefix:level_prefix的计算方法为:level_prefix = levelCode/(1 << suffixLength);level_prefix到码流的对应关系由9-6表示;
  4. 确定后缀的长度:后缀的长度levelSuffixSize通常情况下等于suffixLength,例外情况有:
    • level_prefix = 14时,suffixLength = 0, levelSuffixSize = 4;
    • level_prefix = 15时,levelSuffixSize = 12;
  5. 计算level_suffix的值:level_suffix = levelCode%(1 << suffixLength);
  6. 按照levelSuffixSize的长度编码level_suffix;

在上述的系数矩阵中,非零系数个数TotalCoeffs=6,拖尾系数个数TrailingOnes=3,最后一个非零系数之前0的个数TotalZeros=2;假设nC=0。

  1. 在H.264标准协议文档的表9-5中查得,coeff_token的值为0x00000100;
  2. 编码拖尾系数的符号,从高频到低频,拖尾系数符号为+、-、-,因此符号的码流为011
  3. 编码非零系数的幅值,三个普通非零系数分别为1、2、3;
    1. 编码1:suffixLength初始化为0;levelCode=0;level_prefix=0,查表得对应的码流为1;suffixLength=0,因此不对后缀编码;
    2. 编码2:suffixLength自增1等于1;levelCode=2;level_prefix=1,查表可知对应的码流为01;suffixLength=1,level_suffix=0,因此后缀码流为0
    3. 编码3:suffixLength不满足自增条件,依然为1;levelCode=4;level_prefix=2,查表可知对应的码流为001;suffixLength=1,level_suffix=0,因此后缀码流为0
    4. 综上所述,非零系数的幅值部分的码流为10100010
  4. 编码最后非零系数之前0的个数TotalZeros: TotalCoeffs=6,TotalZeros=2时,在表9-7中可知码流为111
  5. 编码每个非零系数前0的个数:从高频到低频,每个非零系数前0的总个数(zerosLeft)分别为2、1、0、0、0、0,每个非0系数前连续0的个数(run_before)分别为1、1、0、0、0、0。根据标准文档表9-10可得:
    • run_before=1,zerosLeft=2,对应码流为01
    • run_before=1,zerosLeft=1,对应码流为0
    • 所有的0系数都已经编码完成,无需再继续进行编码;

综上所述,整个4×4系数矩阵经过CAVLC编码之后,输出码流为:0000010001110100010111010。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【H.264/AVC视频编解码技术详解】十三、熵编码算法(3):CAVLC原理 的相关文章

  • h.264 视频无法在 iOS 上播放

    我有一个用 h 264 编码的视频文件无法在 iOS 上播放 我想知道原因 这是 HTML
  • AVI、MP4 和“原始”h264 流中的 h264。 NAL 单元格式不同(或 ffmpeg bug)

    TL DR 我想从 AVI MP4 文件读取原始 h264 流 甚至是损坏 不完整的 几乎所有有关 h264 的文档都告诉我它由 NAL 数据包组成 好的 几乎所有地方都告诉我 数据包应该以这样的签名开头00 00 01 or 00 00
  • 通过 rtp 流发送 Android h264 捕获

    我正在为 android 编写一个 rtp 视频流媒体 它从 Android 本地套接字读取 h264 编码数据并将其打包 问题是我做到了 但我在客户端 Voip 不断收到黑框 通信过程如下 Android gt Asterisk gt J
  • 了解 libx264 输出 [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 我在 ffmpeg 中使用 libx264 进行编码 最后我得到了以下输出 谁能指导我理解和解释这一点 有任何参考 文档吗 01 01 06 34 43 650 I stderr 6
  • 通过 ICodecAPI 为 H.264 IMFSinkWriter 编码器设置属性

    我试图通过检索 ICodecAPI 接口来调整通过 ActivateObject 创建的 H 264 编码器的属性 虽然我没有收到错误 但我的设置没有被考虑在内 代码在 Windows 10 下运行 我复制用于创建 IMFSinkWrite
  • 使用 Android MediaCodec 以不同的比特率重新编码 h.264 内容

    我正在尝试使用 4 2 中引入的 Android MediaCodec API 以不同的比特率重新编码 h 264 mp4 文件 我可以使用 MediaCodec API 解码和播放内容 在更改比特率之前 但是如果我在解码之前尝试使用不同的
  • 如何在iOS上通过硬件解码来解码H.264帧?

    我已经使用 ffmpeg 来解码从 ip cam 收到的每一帧 简短的代码如下所示 void decodeFrame unsigned char frameData frameSize int frameSize AVFrame frame
  • Android MediaCodec 似乎可以缓冲 H264 帧

    我正在手动读取 RTP H264 流并将 H264 帧传递给 Android MediaCodec 我使用 markerBit 作为框架的边框 MediaCodec 与 OpenGL 纹理 SurfaceTexture 绑定 一般来说 一切
  • 有没有实用的视频、图片素材网站推荐?

    在作品创作中 素材网站扮演着至关重要的角色 它们提供了海量的设计资源 为设计师 艺术家和创意工作者提供了无限的可能性 本文将为您介绍几款备受推崇的素材网站 帮助您开启创意之旅 一 制片帮素材 制片帮素材是一个提供海量精品视频素材的网站 站内
  • 实用软件分享,打工人必备~

    在这个数字化时代 各种实用软件已经成为我们生活中不可或缺的工具 它们可以帮助我们更高效地完成工作 提高生活质量 节省时间和精力 本文将为您介绍几款实用的软件 让您的工作和生活更加便捷 一 视频下载工具 犀牛下载器 一款免安装的在线视频下载工
  • 如何使用Android MediaCodec编码相机数据(YUV420sp)

    感谢您的关注 我想使用Android MediaCodec API对从Camera获取的视频帧进行编码 不幸的是 我没有成功做到这一点 我对 MediaCodec API 还不太熟悉 以下是我的代码 我需要你的帮助来弄清楚我应该做什么 1
  • 检测到损坏的 ffmpeg 默认设置

    我在使用 X264 Fourcc 编解码器的 VideoWrite 时遇到 ffmpeg 错误 我已经安装了所有依赖项 如何纠正此问题 我一直在使用的示例代码如下 VideoWriter oVideoWriter path mp4 CV F
  • 将 AVAssetWriter 与原始 NAL 单元结合使用

    我在 iOS 文档中注意到AVAssetWriterInput你可以通过nil为了outputSettings字典来指定输入数据不应重新编码 用于对附加到输出的媒体进行编码的设置 传递 nil 来指定不应重新编码附加的样本 我想利用此功能来
  • 为什么 AVSampleBufferDisplayLayer 会失败并出现操作中断 (-11847)?

    我正在使用一个AVSampleBufferDisplayLayer解码并显示从服务器流式传输的 H 264 视频 当我的应用程序进入后台然后返回前台时 解码过程就会搞砸 并且AVSampleBufferDisplayLayer失败 我看到的
  • Gstreamer - Android 上的硬件加速视频解码

    我在 Android 手机上通过 RTP UDP 接收视频 但我发现 CPU 使用率非常高 几乎 100 的一个核心都用于解码视频 在高端设备上 视频播放几乎流畅 但在中低端设备上 我几乎每秒无法获得 1 帧 这是一个 H 264 视频流
  • 时间戳和合成时间偏移

    H 264 缓冲区是否包含时间戳和解码时间戳信息 当我们获得 H 264 nalu 数据时 其中是否包含计时信息 如果您指的是原始 H 264 NAL 单元 那么它们不包含计时信息 如果指的是 PTS DTS 之类的内容 MKV MP4 T
  • 我的视频没有关键帧,怎么可能?

    当我在视频上运行以下行时 它仅输出 P 帧和 B 帧 没有 I 帧 ffprobe select streams v show frames show entries frame pict type of csv 00000 MTS 视频怎
  • 使用 VLC imem 从内存播放 h264 视频文件但收到错误“主流错误:无法预填充缓冲区”

    我有一个加载到内存中的 h264 视频文件 我尝试使用参数 imem cat 4 使用 imem 播放它 以便 vlc 将使用访问模块来解复用视频 并且 vlc 启动并接收我的 imem参数成功 0x7f38a0000e28 access
  • 如何减少 MediaCodec H264 编码器延迟

    我正在尝试使用 Android6 0 的 MediaCodec 将 h264 实时低延迟编码为流 编码器大约有 6 帧延迟 我想知道如何减少 代码来自屏幕记录 cpp https android googlesource com platf
  • 来自相机的 MediaCodec 视频流方向和颜色错误

    我正在尝试流式传输视频捕获直接从相机适用于 Android 设备 到目前为止 我已经能够从 Android 相机捕获每一帧预览帧 byte data Camera camera 函数 对数据进行编码 然后成功解码数据并显示到表面 我用的是安

随机推荐

  • 深入理解Java比较器(Comparable和Comparator)

    深入理解Java比较器 Comparable和Comparator 文章目录 深入理解Java比较器 Comparable和Comparator 一 Comparable 1 Comparable 接口定义 二 Comparator 比较器
  • 6.11行为型---解释器模式

    在软件开发中 会遇到有些问题多次重复出现 而且有一定的相似性和规律性 如果将它们归纳成一种简单的语言 那么这些问题实例将是该语言的一些句子 这样就可以用 编译原理 中的解释器模式来实现了 虽然使用解释器模式的实例不是很多 但对于满足以上特点
  • vue实现导出excel,pdf功能

    实现导出excel pdf功能 注 代码中res就是后端返回的是文件流 前端使用a标签实现导出excel pdf 导出pdf跟excel的区别在于new blob对象时的type类型不同 下面代码是固定写法 可以直接使用 亲测有用哦 导出p
  • 【面试题】: bs架构与cs架构的区别以及各自优缺点

    一 前言 bs架构 Browser Server Architecture 和cs架构 Client Server Architecture 是常见的软件系统架构 bs架构是一种基于Web浏览器和Web服务器互联的架构 而cs架构则是一种由
  • 【VUE】npm install报错“found * vulnerabilities( * high), run npm audit fix, or npm audit”相关问题的解决

    前言 一个vue2的项目 从mac上传到gitee 然后windows clone之后npm install报错 原因 核心问题是node版本问题 windows11下载了node v16 然后版本过高导致各种无法resolve 需要降级为
  • 牛客模拟面试7月19

    说一说常用的 Linux 命令 常用的 Linux 命令有 命令 说明 cd 切换当前目录 ls 查看当前文件与目录 grep 通常与管道命令一起使用 用于对一些命令的输出进行筛选加工 cp 复制文件或文件夹 mv 移动文件或文件夹 rm
  • AI实战:深度学习必须使用大量数据?数据量对深度学习的重要性可能超乎你的想象!

    前言 最近 几个CV相关的项目陆续暴露出识别准确率不高的问题 导致客户反应强烈 其实在项目初期时我就指出过 只有千级的训练数据是无法训练出一个准确率高的模型的 在此写一篇博文记录一下 正文 数据量不够大 别玩深度学习 2017年 Jeff
  • Python之环境搭建

    1 安装 python 安装Python的流程图 如下 点击install 正在安装中 2 手动将python配置到系统环境 下面进行环境变量的配置 测试python环境是否搭建成功 1 WIN R 打开cmd 2 输入python 3 显
  • 再见乱码:5分钟读懂MySQL字符集设置

    摘要 在MySQL的使用过程中 了解字符集 字符序的概念 以及不同设置对数据存储 比较的影响非常重要 不少同学在日常工作中遇到的 乱码 问题 很有可能就是因为对字符集与字符序的理解不到位 设置错误造成的 本文由浅入深 分别介绍了如下内容 1
  • python爬虫入门教程!华为手机秒杀抢购助手

    前言 我们学习了网络爬虫的基本概念 通过网络爬虫我们可以批量下载文字 图片 视频等任意数据资源 在今天的课程中 我们将会给大家介绍关于网络爬虫更加深入的内容 一款能够进行华为手机商品秒杀的工具 只要你安装了Python环境就可以进行使用 零
  • JSX 标签自定义属性报错解决方法

    1 问题 不能将类型 class any xxx string yyy string zzz string 分配给类型 ElementAttrs
  • 车载以太网和工业以太网区别

    车载以太网使用单对非屏蔽电缆以及更小型紧凑的连接器 使用非屏蔽双绞线时可支持15m的传输距离 对于屏蔽双绞线可支持40m 这种优化处理使车载以太网可满足车载EMC要求 可减少高达80 的车内连接成本和高达30 的车内布线重量 100M车载以
  • 【满分】【华为OD机试真题2023 JAVA&JS】分奖金

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 分奖金 知识点栈 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 公司老板做了一笔大生意 想要给每位员工分配一些奖金 想通过游戏的方式来决定每个人分多少钱 按照员
  • SpringBoot-Kafka使用(一)

    一 简介 Kafka认识一下 Kafka异军突起 是近来非常火热的一款消息中间件 消息中间件的作用非常多 常用作系统业务的解耦 例如最常听到的秒杀业务 我们也能使用消息中间件对业务进行解耦 用户发起秒杀请求后 系统首先会将该请求转发到中间件
  • networkmanger开机自启动

    可以在系统设置中启用 NetworkManager 服务的开机自启动 如果使用的是 Ubuntu 系统 可以使用下面的命令开启 sudo systemctlenable NetworkManager service 然后重启系统 Netwo
  • 矩阵分析——LU分解

    LU分解初步 矩阵的LU分解主要用来求解线性方程组或者计算行列式 在使用初等行变换法求解线性方程组的过程中 系数矩阵的变化情况如下 由上可知 其中U就是上面矩阵A经过行变换后的上三角矩阵 Eij表示将i行元素与j行元素互换的初等矩阵 Eij
  • 谈民营企业股份制改制面临问题

    改革开放以来 民营企业是拉动中国经济增长的重要力量 是中国经济的重要组成部分 是国民经济发展的一支生力军 为国家经济发展做出了巨大的贡献 股份制改制对促进民营企业健康稳定发展起着至关重要的作用 然而 当前民营企业在股份制改制中存在产权不清晰
  • 【python数据挖掘课程】十.Pandas、Matplotlib、PCA绘图实用代码补充

    这篇文章主要是最近整理 数据挖掘与分析 课程中的作品及课件过程中 收集了几段比较好的代码供大家学习 同时 做数据分析到后面 除非是研究算法创新的 否则越来越觉得数据非常重要 才是有价值的东西 后面的课程会慢慢讲解Python应用在Hadoo
  • 【Shell牛客刷题系列】SHELL23 nginx日志分析1-IP统计

    该系列是基于牛客Shell题库 针对具体题目进行查漏补缺 学习相应的命令 刷题链接 牛客题霸 Shell篇 该系列文章都放到专栏下 专栏链接为 专栏 Shell 欢迎关注专栏 本文知识预告 本文首先复习了substr 截取字符串函数和sor
  • 【H.264/AVC视频编解码技术详解】十三、熵编码算法(3):CAVLC原理

    H 264 AVC视频编解码技术详解 视频教程已经在 CSDN学院 上线 视频中详述了H 264的背景 标准协议和实现 并通过一个实战工程的形式对H 264的标准进行解析和实现 欢迎观看 纸上得来终觉浅 绝知此事要躬行 只有自己按照标准文档