【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解析 的相关文章

  • H.264 RTSP 绝对时间戳

    是否可以从安讯士摄像机通过 RTSP 发送的 H 264 流中读取绝对时间戳 有必要知道相机何时拍摄该帧 谢谢 安德里亚 正如拉尔夫已经说过的 RTP 时间戳与随机时钟相关 它们仅用于计算两个帧 或一般的 RTP 数据包 之间的差异 为了将
  • AVI、MP4 和“原始”h264 流中的 h264。 NAL 单元格式不同(或 ffmpeg bug)

    TL DR 我想从 AVI MP4 文件读取原始 h264 流 甚至是损坏 不完整的 几乎所有有关 h264 的文档都告诉我它由 NAL 数据包组成 好的 几乎所有地方都告诉我 数据包应该以这样的签名开头00 00 01 or 00 00
  • 除 ffmpeg x264 之外的 H264 编码器

    我正在开发的 iPhone 应用程序会在特定的用户定义的时间间隔内连续捕获图像 我正在寻找一种将这些图像组合成 H264 编码视频的方法 我在 Google 上做了一些研究 看起来我必须在 iPhone 上使用 ffmpeg mencode
  • 使用 Android MediaCodec 以不同的比特率重新编码 h.264 内容

    我正在尝试使用 4 2 中引入的 Android MediaCodec API 以不同的比特率重新编码 h 264 mp4 文件 我可以使用 MediaCodec API 解码和播放内容 在更改比特率之前 但是如果我在解码之前尝试使用不同的
  • FFmpeg 从 UYVY422 转换为 YUV420P

    我有 UYVY422 格式的原始视频 我想将其转换为 YUV420p 我正在执行该命令 ffmpeg y r 25 0 f rawvideo s 1920x1080 pix fmt uyvy422 i input avi pix fmt y
  • ffmpeg API h264编码的视频不能在所有平台上播放

    Edit 在之前的版本中 我使用了非常旧的 ffmpeg API 我现在使用最新的库 问题仅略有变化 从 主要 变为 高 我正在使用 ffmpeg C API 在 C 中创建 mp4 视频 我希望生成的视频具有 约束基线 配置文件 以便生成
  • 使用 Android 低级 api 解码 H264 流

    我在 android 中使用 MediaCodec 低级 Api 来解码从 IP 摄像机接收到的 h264 原始流 来自 IP 摄像机的原始流 通过 TCP IP 连接接收 要解码流 我的代码是 Override protected voi
  • Android MediaCodec 似乎可以缓冲 H264 帧

    我正在手动读取 RTP H264 流并将 H264 帧传递给 Android MediaCodec 我使用 markerBit 作为框架的边框 MediaCodec 与 OpenGL 纹理 SurfaceTexture 绑定 一般来说 一切
  • 从 H.264 中删除 EIA-608 隐藏式字幕而不重新编码

    我希望从 H 264 视频 包含为 mkv 中删除隐藏字幕 EIA 608 而不需要重新编码 我最接近的是使用 ffmpeg ffmpeg f lavfi i movie input mkv out subcc map 0 0 output
  • H.264 over RTP - 识别 SPS 和 PPS 帧

    我有来自 IP 摄像机的原始 H 264 流 封装在 RTP 帧中 我想将原始 H 264 数据放入文件中 以便我可以将其转换为ffmpeg 因此 当我想将数据写入原始 H 264 文件时 我发现它必须如下所示 00 00 01 SPS 0
  • 使用libavcodec解码H264视频,C

    我正在尝试使用 ffmpeg libavcodec 解码原始 h264 文件 但无法使其正常工作 目前输出应该是原始 YUV 文件 可以用GCC编译代码 gcc o decoder decoder c L lib llibavcodec l
  • ffmpeg 复制以保留时间戳

    我正在尝试修改 HLS 段传输流 并使用 ffmpeg 保留其开始时间 但是 即使提到了 copyts 输出也不会保留输入文件的 start time 值 这是我的命令行 ffmpeg i fileSequence1 ts i x png
  • 如何在没有 MediaExtractor 的情况下使用 MediaCodec 进行 H264

    我需要在没有 MediaExtractor 的情况下使用 MediaCodec 并且我正在使用 FileInputStream 读取文件 目前它不起作用 它在屏幕上显示绿色的乱码图像 这是整个源代码 FileInputStream in n
  • 为什么 AVSampleBufferDisplayLayer 会失败并出现操作中断 (-11847)?

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

    研究 HTML5 视频标签 并研究哪些浏览器支持哪些视频文件类型 我最初的想法是事情变得比仅仅使用 Flash 更困难 我想知道是否有人已经找到一些骨架代码 与视频的开发方法相结合 来执行以下操作 如果闪光灯可用 请使用它 如果没有 请尝试
  • 有没有简单的方法来提取附件 b 格式的 h264 原始流?

    当我使用命令行使用 ffmpeg 提取视频流时 ffmpeg i 一些文件 vcodec copy an f rawvideo h264 什么 out h264 对于 Adob e Media Encoder 生成的某些媒体文件 只有 m4
  • 将 H264 视频转换为原始 YUV 格式

    是否可以使用 ffmpeg 从 H264 编码视频创建原始 YUV 视频 我想用 matlab 打开视频并逐帧访问 Luma Cb 和 Cr 分量 是的 您可以 您只需指定像素格式即可 要获取格式的完整列表 ffmpeg pix fmts
  • h264 参考帧

    我正在寻找一种在 h264 流中查找参考帧的算法 我在不同的解决方案中看到的最常见的方法是查找访问单元分隔符和 IDR 类型的 NAL 不幸的是 我检查的大多数流没有 IDR 类型的 NAL 我将不胜感激的帮助 问候 雅采克 H264 帧由
  • RTSP H.264 IP 摄像机作为 Windows 中的视频源/输入

    我目前被这个问题困扰 我希望有人可以帮助我 我正在尝试创建某种解码器来转换视频流 该视频流将充当视频输入设备 以便我可以在 Wirecast 视频流程序 中使用它 在这个阶段 我使用 mjpeg IP 摄像机作为视频源 使用这个简洁的小程序
  • 为 Windows Phone 8 构建 ffmpeg

    我如何为 Windows Phone 8 arm 构建 ffmpeg 我找不到任何有关它的信息 我可以在 Windows Phone 8 中从 C 调用 h 264 硬件编码器 解码器吗 看来媒体基金会太有限了 谢谢 据我所知 由于缺少工具

随机推荐

  • 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的标准进行解析和实现 欢迎观看 纸上得来终觉浅 绝知此事要躬行 只有自己按照标准文档