【H.264/AVC视频编解码技术详解】二十二、熵编码(7):语法元素的CABAC解析

2023-11-03

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

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

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

GitHub代码地址:点击这里

在本系列的博文18中,我们讨论了算术编码的基本原理,以及实现一个简单的算术编码器内核的方法:

而在博文19和21中我们根据H.264对于CABAC的规定,讨论了语法元素二值化以及上下文概率模型的相关算法:

通过前面的研究我们已经了解,由于视频数据特殊的统计特性和对编码性能的高指标要求,CABAC的算法远远比博文18中描述的基本模型更加复杂。尽管如此,CABAC在算术编码的最核心层面依然遵循了博文18中所讲的根本原理,这一点在本文对标准协议文档的解读中也可以获得明确的证实。

一、CABAC解析(解码)的总流程

CABAC的解码过程定义与标准协议文档的9.3.3.2节。CABAC解码过程所需要的输入数据包括前一章所推导出的上下文模型索引ctxIdx、旁路模式标志bypassFlag,以及解码器引擎的状态。下图表示了CABAC解码过程的概念框图:

在上图中可以看出,根据参数的不同,CABAC解码总共可能有三种运行流程:

  • DecodeBypass: 当旁路模式标志bypassFlag为1时执行,表示旁路模式的解析过程;
  • DecodeDecision: 当bypassFlag为0且ctxIdx不为276时执行,表示CABAC解析过程;
  • DecodeTerminate: 当bypassFlag为0且ctxIdx==276时执行,表示解析终结码的过程;

在这三种执行流程中最重要的就是第二种——DecodeDecision。接下来本文将从DecodeDecision开始分析这三种解析过程。

二、CABAC算术编码的解码(解析)过程

本节描述的即是DecodeDecision部分的方法。这一部分也是CABAC算法中最为重要的部分,H.264的main、high profile中的多数语法元素都是通过该过程进行解析的。该部分在标准协议文档的9.3.3.2.1中定义。

从标准协议中的该节内容中可知,该过程所需要的数据有ctxIdx, codIRange 和 codIOffset,其中ctxIdx由前一章《CABAC的上下文概率模型》中的方法推导,codIRange 和 codIOffset的初始值由CABAC解码器引擎的初始化确定。输出的数据包括解析出来的语法元素比特位值binVal,以及更新过的codIRange 和 codIOffset。

该过程的整体流程如下图所示:

2.1 计算 codIRangeLPS

计算 codIRangeLPS 的过程遵循以下流程:

  1. 根据当前的codIRange值,计算qCodIRangeIdx的值:
    • qCodIRangeIdx =( codIRange >> 6 ) & 3
  2. 通过 qCodIRangeIdx 和 pStateIdx,计算 codIRangeLPS 的值:
    • 通过查表获取:codIRangeLPS = rangeTabLPS[ pStateIdx ][ qCodIRangeIdx ]
    • rangeTabLPS为预定义的表,在表9-44中指定;

2.2 更新 codIRange

更新 codIRange 的方法为:

codIRange = codIRange - codIRangeLPS;

更新完成后,判断 codIOffset,如果 codIOffset >= codIRange,输出比特位值binVal赋值为1 - valMPS,并且codIOffset自减去codIRange的值,然后codIRange的值赋值为codIRangeLPS;否则,输出比特位值binVal赋值为valMPS。

2.3 状态转移过程

在CABAC编码或解码语法元素的某一个bit,编码/解码器将随之更新编解码器的状态。状态转移过程定义于标准的9.3.3.2.1.1节。该过程根据当前的上下文模型索引和解码的比特值,来更新上下文模型索引以及LPS/MPS的定义。

状态转移过程可以下式表示:

if( binVal = = valMPS )
    pStateIdx = transIdxMPS( pStateIdx )
else {
    if( pStateIdx = = 0 ) {
        valMPS = 1 − valMPS   
    }
    pStateIdx = transIdxLPS( pStateIdx )
}

在编码过程中上下文模型索引的更新同样以查表的形式实现,该表格在9-45中规定。

2.4 归一化过程

在第18篇博文“算术编码的基本原理中”已经讨论过算术编码器的归一化。在H.264实际定义的CABAC算法中,归一化同样也是必备过程。CABAC的归一化过程定义于9.3.3.2.2节,流程图以下图表示:

进行归一化的本质含义是更新codIRange和codIOffset的值,所需要的数据包括当前CABAC的codIRange和codIOffset以及当前的二进制比特流数据。主要步骤为:

  • 判断如果codIRange不小于256,那么不需要进行归一化;
  • 如果codIRange小于256,则进行归一化过程,方法为:
    1. codIRange和codIOffset分别自乘以2;
    2. 在码流中读取 1 bit,并与codIOffset按位取或运算并更新到codIOffset;

三、CABAC的bypass解析方法

本节描述的是CABAC的DecodeBypass方法,即旁路解析模式,在bypass值设为1时执行。DecodeBypass相比DecodeDecision方法的特点是编码效率较低但运算远比DecodeDecision简单。与DecodeDecision过程相比,DecodeBypass不需要ctxIdx,只需要codIRange和codIOffset两个值。

DecodeBypass过程的流程图如下:

解析过程为:

  1. 首先codIOffset自增一倍,并且从码流中读取1 bit与之求按位或操作;
  2. codIOffset与codIRange对比:
    • 若codIOffset小于codIRange,输出二进制位0;
    • 否则,输出二进制位1,且codIOffset自减去codIRange的值;

四、CABAC的终止符解析

CABAC的终止符解析即DecodeTerminate过程,主要用于解析end_of_slice和ctxIdx值为276的元素。解析的方法类似于DecodeBypass过程,流程如下:

  1. 首先codIOffset自减2;
  2. codIOffset与codIRange对比:
    • 若codIOffset小于codIRange,输出二进制位0,并执行解码器的归一化过程;
    • 否则,输出二进制位1;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【H.264/AVC视频编解码技术详解】二十二、熵编码(7):语法元素的CABAC解析 的相关文章

  • linux安装ffmpeg

    1 下载解压 wget http www ffmpeg org releases ffmpeg 3 1 tar gz tar zxvf ffmpeg 3 1 tar gz 2 进入解压后目录 输入如下命令 usr local ffmpeg为
  • 【视频编码学习】VTM15.0编译运行

    VTM版本 15 0 操作系统 Win10 x64位 IDE Visual Studio 2019 编译器 cmake 利用VS2019运行VTM15 0 前言 一 下载VTM15 0 二 下载安装cmake 1 下载cmake并安装 2
  • H264 视频使用 src 属性工作。使用 MediaSource API (Chromium) 相同视频失败

    http www youtube com html5表示 Google Chrome 兼容 MediaSource Extensions 和 H 264 我做了一个简单的测试 检查我的视频是否受 Chromium 支持 使用 视频 gt 视
  • h264 idea 比特流是如何组织的? / 标头起始码

    我试图通过使用十六进制编辑器查看视频文件的比特流来了解一些有关 h264 的知识 我发现here视频对象平面 0x000001b6 和 i 帧 0x000001b600 的起始码 但我在视频文件中找不到很多这样的字节 大多数情况下 这些起始
  • 了解 libx264 输出 [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 我在 ffmpeg 中使用 libx264 进行编码 最后我得到了以下输出 谁能指导我理解和解释这一点 有任何参考 文档吗 01 01 06 34 43 650 I stderr 6
  • H.264 中的 VBV(视频缓冲验证器)是什么?

    我不明白什么是 VBV 视频缓冲验证器 以及它与 maxrate 有什么关系 当我使用这个命令时 ffmpeg i input mp4 crf 21 maxrate 750k bufsize 750k codec v 0 libx264 s
  • 取自 .mp4 的 H.264 解码器配置记录的格式

    我正在检查从 Android 设备录制的 mp4 视频文件中包含的解码器配置记录 有些设备的解码器配置记录中写入了奇怪或不正确的参数 以下是来自 Galaxy Player 4 0 的示例 该示例是不正确的 DecoderConfigura
  • 将 FFMPEG 编码为 MPEG-DASH – 或使用关键帧簇的 WebM – 用于 MediaSource API

    我目前正在将视频流发送到 Chrome 以通过 MediaSource API 进行播放 据我了解 MediaSource 仅支持使用 MPEG DASH 编码的 MP4 文件 或具有以关键帧开头的簇的 WebM 文件 否则会引发错误 媒体
  • H.264 over RTP - 识别 SPS 和 PPS 帧

    我有来自 IP 摄像机的原始 H 264 流 封装在 RTP 帧中 我想将原始 H 264 数据放入文件中 以便我可以将其转换为ffmpeg 因此 当我想将数据写入原始 H 264 文件时 我发现它必须如下所示 00 00 01 SPS 0
  • 如何定量测量源和显示器之间的 gstreamer H264 延迟?

    我有一个项目 我们使用 gstreamer x264 等将视频流通过本地网络多播到多个接收器 连接到显示器的专用计算机 我们在视频源 摄像机 系统和显示监视器上使用 gstreamer 我们使用 RTP 有效负载 96 和 libx264
  • 解析 mdat MP4 中的 H264

    我有一个仅包含 MP4 容器中的 mdat 原子的文件 mdat中的数据包含AVC数据 我知道数据的编码参数 该格式似乎不是附件 B 字节流格式 我想知道我将如何解析这个 我尝试过搜索切片标题 但运气不佳 是否可以在没有 NAL 的情况下解
  • 将 AVAssetWriter 与原始 NAL 单元结合使用

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

    我正在使用一个AVSampleBufferDisplayLayer解码并显示从服务器流式传输的 H 264 视频 当我的应用程序进入后台然后返回前台时 解码过程就会搞砸 并且AVSampleBufferDisplayLayer失败 我看到的
  • ffmpeg 用于将视频编码为 H264 编解码器格式

    我有一个 mp4 视频文件 MPEG4 视频编解码器 我试图在 Linux 上使用 ffmpeg 将其转换为 H264 视频编解码器格式 原始 h 264 格式 版本 FFmpeg 版本 SVN r0 5 1 4 0 5 1 1ubuntu
  • 时间戳和合成时间偏移

    H 264 缓冲区是否包含时间戳和解码时间戳信息 当我们获得 H 264 nalu 数据时 其中是否包含计时信息 如果您指的是原始 H 264 NAL 单元 那么它们不包含计时信息 如果指的是 PTS DTS 之类的内容 MKV MP4 T
  • 使用 libavcodec 的 mpegts 容器中的原始 H264 帧

    我非常感谢对以下问题的帮助 我有一个带摄像头的小工具 可以生成 H264 压缩视频帧 这些帧将发送到我的应用程序 这些帧不在容器中 只是原始数据 我想用ffmpeg和libav函数创建一个视频文件 方便以后使用 如果我解码帧 然后对其进行编
  • 使用 libavformat API 读取 H264 SPS 和 PPS NAL 字节

    如何使用 libavformat API 读取 H264 SPS 和 PPS NAL 字节 我尝试使用 av read frame input avFormatContext avPkt API 从 mp4 视频 编解码器为 h264 文件
  • 将 H.264 I 帧放入 AVSampleBufferDisplayLayer 但不显示视频图像

    在详细回顾了 WWDC2014 Session513 后 我尝试在 IOS8 0 上编写我的应用程序来解码和显示一个实时 H 264 流 首先 我成功构建了H264参数集 当我得到一个带有 4 位起始代码的帧时 就像 0x00 0x00 0
  • H264 字节流到图像文件

    第一次来这里所以要温柔 我已经在给定的 H 264 字节流上工作了几个星期 一般注意事项 字节流不是来自文件 它是从外部源实时提供给我的 字节流使用 Android 的媒体编解码器进行编码 当将流写入扩展名为 H264的文件时 VLC能够正
  • MediaCodec 创建输入表面

    我想使用 MediaCodec 将 Surface 编码为 H 264 使用 API 18 有一种方法可以通过调用 createInputSurface 然后在该表面上绘图来对表面中的内容进行编码 我在 createInputSurface

随机推荐

  • nvidia-smi 无进程占用GPU,但GPU显存却被占用了很多

    下图是我当时遇到的问题 如上图 GPU1 显示占用了10G多的显存 但是却没有相应的进程 此时可使用如下命令查看进程 fuser v dev nvidia 显示如下图 此时把这些进程全部 kill 掉 kill 9 5142 5143 51
  • win10误删的注册表能还原吗_win10注册表删错了怎么办_win10注册表删错东西如何恢复-win7之家...

    我们要知道 注册表是Microsoft Windows中的一个重要的数据库 用于存储系统和应用程序的设置信息 在win10系统中 用户可以通过修改注册表来保证电脑的安全 可是近日有的用户在修改注册表时不小心删错了 那么win10注册表删错了
  • 分页居中显示

    div class page number div div div page number width 100 height 80px padding top 10px text align center page number1 disp
  • 如何阅读芯片手册

    原视频链接 如何快速阅读芯片数据手册 初学者和外行进 1 芯片手册的结构 1 Features 特性 对芯片的特点进行了总结 2 General Description 概述 把芯片的功能进行了一个大概的总结 这部分对新手来说很重要 每一个
  • SDIO接口(4)——SDIO通信

    SDIO通信 SD总线上的通信基于命令和数据位流 这些命令和数据位流由起始位启动 并由停止位终止 SDIO总线上的设置和控制都是通过命令来实现 SDIO总线上都是HOST端发起请求 然后DEVICE端回应请求 其中请求和应答中会包含数据信息
  • 香橙派4和树莓派4B构建K8S集群实践之八: TiDB

    目录 1 说明 2 准备工作 3 安装 3 1 参考Tidb官方 v1 5安装说明 3 2 准备存储类 3 3 创建crd 3 4 执行operator 3 5 创建cluster dashboard monitor容器组 3 6 设置访问
  • Android BottomNavigationView的使用

    BottomNavigationView大于3个menu文字和icon都显示 代码中设置 public static void disableShiftMode BottomNavigationView view int count vie
  • 使用Java对轨迹进行抽稀,并生成mvt(Map Vector Tile)瓦片

    Java对轨迹进行抽稀 并生成mvt线瓦片 1 原理 2 pom依赖 3 Java对轨迹道格拉斯普克抽稀源码 4 Java生成线瓦片源码 参考 1 原理 Java对轨迹抽稀 道格拉斯普克算法 生成mvt瓦片 VectorTileEncode
  • mysql tinyint和char(1)性能对比

    在数据库设计的时候会遇到很多只需要0 1 2这种固定几个值的状态字段 基本上都建议设置为只占一字节的tinyint类型 有些觉得char 1 是一样 毕竟char 1 存储数字和字母时一个字符也只是占一个字节 mysql是用c 写的 而在c
  • 蓝桥杯-小数第n位-2017-国赛

    小数第n位 文章目录 小数第n位 分析 代码 参考材料 题目描述 我们知道 整数做除法时 有时得到有限小数 有时得到无限循环小数 如果我们把有限小数的末尾加上无限多个 0 它们就有了统一的形式 本题的任务是 在上面的约定下 求整数除法小数点
  • VSCode配置之Opencv4x终极奥义

    苦于windows下编译opencv的效率和对于大型软件如Visual Studio 2017 Visual Studio S2019等的不习惯 希望VScode也能够快速 高效编译第三方库 如opencv等 花了大概两天的时间 分析了主流
  • 【Where和having的区别】条件语句where和having有什么不同?

    Where 总之 WHERE 关键字的特点是 直接用表的字段对数据集进行筛选 如果需要通过关联查询从其他的表获取需要的信息 那么执行的时候 也是先通过 WHERE 条件进行筛选 用筛选后的比较小的数据集进行连接 这样一来 连接过程中占用的资
  • iostat 命令

    NAME iostat Report Central Processing Unit CPU statistics and input output statistics for devices partitions and network
  • 计算机组成原理与系统结构期末复习题(2)

    计算机组成原理与系统结构 选择题 1 冯 诺依曼机工作的基本方式的特点是 B A 多指令流单数据流 B 按地址访问并顺序执行指令 C 堆栈操作 D 存贮器按内容选择地址 2 完整的计算机应包括 D A 运算器 存储器 控制器 B 外部设备和
  • VS环境下Qt工程.UI文件不生成头文件的问题

    在VS环境下创建的Qt工程会出现 UI文件不生成头文件的问题 可以通过右击 ui文件 点击编译生成头文件 但是 我创建的工程的 ui文件不能编译 右键编译选项是灰的 这种情况下 我想到的办法是 重新添加一个带UI文件的GUI类 与工程同名
  • openmvg2.0编译与使用

    目录 写在前面 获取代码 github 网盘 编译 使用 稠密重建 参考 完 写在前面 1 openmvg是一个用于实现structure from motion的开源库 实现了完整的sfm pipeline 并有说明文档 https op
  • css文本换行加省略号

    overflow hidden text overflow ellipsis white space nowrap 可以显示的行数 超出部分用 表示 webkit box orient vertical 控制显示行数 webkit line
  • 某企业每月给其A、B、C 和D 四个门店一共发送6 个集装箱的某种货物,如果各门店出售该种货物的利润(万元)如下表:

    某企业每月给其A B C 和D 四个门店一共发送6 个集装箱的某种货物 如果各门店出售该种货物的利润 万元 如下表 试求这6 箱货物如何分配给各门店 才能获得最大总利润 解题思路 将问题按卖场分为四个阶段 将A B C D四个卖场分别编号为
  • Angular学习---filter过滤器(管道pipe)

    angular核心概念 过滤器 Filter 应用 如当后台传入数据用1 2 代表性别 可以用过滤器进行更改 如上 练习 创建员工信息列表 中 的员工性别 过滤器在angular2以后改名为 管道 pipe 详见新建的sex pipe ts
  • 【H.264/AVC视频编解码技术详解】二十二、熵编码(7):语法元素的CABAC解析

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