openh264 宏块级码率控制源码分析

openh264 宏块级码率控制函数关系

在这里插入图片描述

宏块级核心函数分析

WelsRcMbInitGom函数

  1. 功能:openh264 码率控制框架中宏块级码率控制函数,根据是否启用GOM QP来决定如何设置宏块的QP值,以控制编码的质量和比特率。
  2. 原理过程
  • 函数参数:
    • pEncCtx: 指向编码上下文的指针,包含编码过程中所需的全局信息。
    • pCurMb: 指向当前宏块的指针,宏块是视频编码的基本单位。
    • pSlice: 指向当前切片的指针,切片是一系列连续宏块的集合。
  • 局部变量:
    • pWelsSvcRc: 指向服务层码率控制结构的指针。
    • pSOverRc: 指向切片覆盖码率控制结构的指针。
    • pCurLayer: 指向当前解码质量层的指针。
    • kuiChromaQpIndexOffset: 色度QP索引偏移量,用于调整色度通道的量化参数。
  • 主要逻辑:
    • 首先,获取当前宏块的比特流位置,并更新到切片覆盖码率控制结构中。
    • 如果全局优化码率控制(GOM QP)被启用:
      • 如果当前宏块是GOM的起始宏块(即其索引能被GOM的数量整除),并且不是切片的起始宏块,则增加复杂度指数。
      • 调用RcCalculateGomQp函数计算GOM的QP值。
      • 调用RcGomTargetBits函数计算GOM的目标比特数。
      • 调用RcCalculateMbQp函数计算当前宏块的QP值。
    • 如果GOM QP未启用:
      • 将当前宏块的亮度QP值设置为全局QP值。
      • 根据亮度QP值和色度QP索引偏移量,计算并设置色度QP值。
  • 关键功能:
    • 函数通过判断是否启用GOM QP来决定如何设置宏块的量化参数(QP),这影响编码后视频的质量和比特率。
    • 使用CLIP3_QP_0_51宏来确保QP值在有效范围内(0到51)。
  1. 源码
void WelsRcMbInitGom (sWelsEncCtx* pEncCtx, SMB* pCurMb, SSlice* pSlice) {SWelsSvcRc* pWelsSvcRc        = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];SRCSlicing* pSOverRc          = &pSlice->sSlicingOverRc;SDqLayer* pCurLayer           = pEncCtx->pCurDqLayer;const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;pSOverRc->iBsPosSlice = pEncCtx->pFuncList->pfGetBsPosition (pSlice);if (pWelsSvcRc->bEnableGomQp) {//calculate gom qp and target bits at the beginning of gomif (0 == (pCurMb->iMbXY % pWelsSvcRc->iNumberMbGom)) {if (pCurMb->iMbXY != pSOverRc->iStartMbSlice) {pSOverRc->iComplexityIndexSlice++;RcCalculateGomQp (pEncCtx, pSlice, pCurMb);}RcGomTargetBits (pEncCtx, pSlice);}RcCalculateMbQp (pEncCtx, pSlice, pCurMb);} else {pCurMb->uiLumaQp   = pEncCtx->iGlobalQp;pCurMb->uiChromaQp = g_kuiChromaQpTable[CLIP3_QP_0_51 (pCurMb->uiLumaQp + kuiChromaQpIndexOffset)];}}

RcCalculateGomQp函数

  1. 功能:计算宏块组的量化参数 qp 的具体实现
  2. 原理过程
  • 函数参数:
    • pEncCtx: 指向编码上下文的指针,包含编码过程中所需的全局信息。
    • pSlice: 指向当前切片的指针。
    • pCurMb: 指向当前宏块的指针,虽然在这段代码中没有直接使用。
  • 局部变量:
    • pWelsSvcRc: 指向服务层码率控制结构的指针。
    • pSOverRc: 指向切片覆盖码率控制结构的指针。
    • iBitsRatio: 用于计算比特率比例的变量。
  • 主要逻辑:
    • 计算剩余的比特数 iLeftBits,即目标比特数减去已使用的比特数。
    • 计算目标剩余比特数 iTargetLeftBits,考虑了当前GOM的已用比特数。
  • QP调整逻辑:
    • 如果剩余比特数小于或等于0,增加QP以降低质量,减少比特率的使用。
    • 否则,根据比特率比例 iBitsRatio 来调整QP:
      • 如果 iBitsRatio 小于 8409,增加QP 2。
      • 如果 iBitsRatio 在 8409 和 9439 之间,增加QP 1。
      • 如果 iBitsRatio 大于 10600,减少QP 1。
      • 如果 iBitsRatio 大于 11900,减少QP 2。
  • QP值的边界限制:
    • 使用 WELS_CLIP3 宏来确保计算出的QP值在允许的最小值和最大值之间。
  • 重置GOM比特计数器:
    • 将 iGomBitsSlice 重置为0,为下一个GOM的比特计数做准备。
  • 注释:
    • 注释中提到了一个可能的日志记录语句,但在这段代码中被注释掉了。
  • 设计目的:
    • 函数的目的是根据当前的编码比特率情况动态调整量化参数,以控制视频的质量和编码效率。
  • 关键功能:
    • 函数通过计算剩余比特数与目标比特数的比例,动态调整QP值,实现码率控制。
  1. 源码
void RcCalculateGomQp (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb) {SWelsSvcRc* pWelsSvcRc    = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];SRCSlicing* pSOverRc      = &pSlice->sSlicingOverRc;int64_t iBitsRatio        = 1;int64_t iLeftBits         = pSOverRc->iTargetBitsSlice - pSOverRc->iFrameBitsSlice;int64_t iTargetLeftBits   = iLeftBits + pSOverRc->iGomBitsSlice - pSOverRc->iGomTargetBits;if ((iLeftBits <= 0) || (iTargetLeftBits <= 0)) {pSOverRc->iCalculatedQpSlice += 2;} else {
//globe decisioniBitsRatio = 10000 * iLeftBits / (iTargetLeftBits + 1);if (iBitsRatio < 8409)              //2^(-1.5/6)*10000pSOverRc->iCalculatedQpSlice += 2;else if (iBitsRatio < 9439)         //2^(-0.5/6)*10000pSOverRc->iCalculatedQpSlice += 1;else if (iBitsRatio > 10600)        //2^(0.5/6)*10000pSOverRc->iCalculatedQpSlice -= 1;else if (iBitsRatio > 11900)        //2^(1.5/6)*10000pSOverRc->iCalculatedQpSlice -= 2;}pSOverRc->iCalculatedQpSlice = WELS_CLIP3 (pSOverRc->iCalculatedQpSlice, pWelsSvcRc->iMinFrameQp,pWelsSvcRc->iMaxFrameQp);
// WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,"iCalculatedQpSlice =%d,iBitsRatio = %d\n",pSOverRc->iCalculatedQpSlice,iBitsRatio);pSOverRc->iGomBitsSlice = 0;}

RcGomTargetBits函数

  1. 功能:在视频编码过程中为一个组(Group of Macroblocks,GOM)分配目标比特数。
  2. 原理过程
  • 函数参数:
    • pEncCtx: 指向编码上下文的指针,包含编码过程中所需的全局信息。
    • pSlice: 指向当前切片的指针。
  • 局部变量:
    • pWelsSvcRc: 指向当前依赖层的码率控制服务结构体的指针。
    • pWelsSvcRc_Base: 指向基础码率控制服务结构体的指针,可能用于比较或计算。
    • pSOverRc: 指向切片覆盖码率控制结构的指针。
    • iAllocateBits: 用于存储分配给当前GOM的比特数。
    • iSumSad: 用于累加GOM的总SAD(Sum of Absolute Differences)值。
    • iLastGomIndex: 表示最后一个GOM的索引。
    • iLeftBits: 表示剩余的比特数。
    • kiComplexityIndex: 表示当前GOM的复杂度指数。
  • 主要逻辑:
    • 计算最后一个GOM的索引 iLastGomIndex。
    • 计算剩余的比特数 iLeftBits。
    • 如果剩余比特数小于或等于0,将GOM的目标比特数设置为0并返回。
    • 如果当前复杂度指数等于最后一个GOM的索引,将所有剩余比特数分配给当前GOM。
    • 否则,计算从当前复杂度指数到最后一个GOM的SAD总和 iSumSad。
    • 根据SAD值按比例分配剩余比特数。
  • 比特分配策略:
    • 如果 iSumSad 为0,等比例分配剩余比特数。
    • 如果 iSumSad 不为0,根据当前GOM的SAD值占总SAD的比例来分配比特数。
  • 辅助函数:
    • RcJudgeBaseUsability: 用于判断基础码率控制服务结构体的可用性,其返回值可能用于计算。
  • 设计目的:
    • 函数的目的是根据宏块的复杂度和剩余的比特资源,动态地为每个GOM分配目标比特数,以优化视频质量和编码效率。
  • 关键功能:
    • 函数通过计算SAD值来评估宏块的复杂度,并据此分配比特数,实现码率控制。
  1. 源码
void RcGomTargetBits (sWelsEncCtx* pEncCtx, SSlice* pSlice) {SWelsSvcRc* pWelsSvcRc        = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];SWelsSvcRc* pWelsSvcRc_Base   = NULL;SRCSlicing* pSOverRc          = &pSlice->sSlicingOverRc;int32_t iAllocateBits = 0;int32_t iSumSad = 0;int32_t iLastGomIndex = 0;int32_t iLeftBits = 0;const int32_t kiComplexityIndex = pSOverRc->iComplexityIndexSlice;int32_t i;iLastGomIndex  = pSOverRc->iEndMbSlice / pWelsSvcRc->iNumberMbGom;iLeftBits = pSOverRc->iTargetBitsSlice - pSOverRc->iFrameBitsSlice;if (iLeftBits <= 0) {pSOverRc->iGomTargetBits = 0;return;} else if (kiComplexityIndex >= iLastGomIndex) {iAllocateBits = iLeftBits;} else {pWelsSvcRc_Base = RcJudgeBaseUsability (pEncCtx);pWelsSvcRc_Base = (pWelsSvcRc_Base) ? pWelsSvcRc_Base : pWelsSvcRc;for (i = kiComplexityIndex + 1; i <= iLastGomIndex; i++) {iSumSad += pWelsSvcRc_Base->pCurrentFrameGomSad[i];}if (0 == iSumSad)iAllocateBits = WELS_DIV_ROUND (iLeftBits, (iLastGomIndex - kiComplexityIndex));elseiAllocateBits = WELS_DIV_ROUND ((int64_t)iLeftBits * pWelsSvcRc_Base->pCurrentFrameGomSad[kiComplexityIndex + 1],iSumSad);}pSOverRc->iGomTargetBits = iAllocateBits;
}

RcCalculateMbQp函数

  1. 功能:作用是在视频编码过程中为当前宏块(Macroblock, MB)计算量化参数(Quantization Parameter, QP)
  2. 原理过程
  • 函数参数:
    • pEncCtx: 指向编码上下文的指针,包含编码过程中所需的全局信息。
    • pSlice: 指向当前切片的指针。
    • pCurMb: 指向当前宏块的指针。
  • 局部变量:
    • pWelsSvcRc: 指向服务层码率控制结构的指针。
    • pSOverRc: 指向切片覆盖码率控制结构的指针。
    • iLumaQp: 存储计算得到的亮度QP值。
    • pCurLayer: 指向当前解码质量层的指针。
    • kuiChromaQpIndexOffset: 色度QP索引偏移量。
  • 主要逻辑:
    • 从切片覆盖码率控制结构中获取iCalculatedQpSlice计算得到的亮度QP值 iLumaQp。
    • 如果启用了自适应量化(bEnableAdaptiveQuant),则根据宏块的运动和纹理信息调整QP值。
  • 自适应量化:
    • 如果启用自适应量化,使用 pMotionTextureIndexToDeltaQp 数组,根据宏块的位置 MbXY 来获取QP调整值,并将其加到基础QP值iLumaQp上。
    • 调整后的QP值通过 WELS_CLIP3 宏确保在允许的范围内。
  • 色度QP计算:
    • 使用色度QP表 g_kuiChromaQpTable 和色度QP索引偏移量 kuiChromaQpIndexOffset 来计算色度QP值。
    • 色度QP值通过 CLIP3_QP_0_51 宏确保在0到51的范围内。
  • 宏块QP赋值:
    • 将计算得到的亮度QP和色度QP值赋给当前宏块 pCurMb。
  1. 源码
void RcCalculateMbQp (sWelsEncCtx* pEncCtx, SSlice* pSlice, SMB* pCurMb) {SWelsSvcRc* pWelsSvcRc        = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];SRCSlicing* pSOverRc          = &pSlice->sSlicingOverRc;int32_t iLumaQp               = pSOverRc->iCalculatedQpSlice;SDqLayer* pCurLayer           = pEncCtx->pCurDqLayer;const uint8_t kuiChromaQpIndexOffset = pCurLayer->sLayerInfo.pPpsP->uiChromaQpIndexOffset;if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) {iLumaQp   = (int8_t)WELS_CLIP3 (iLumaQp +pEncCtx->pVaa->sAdaptiveQuantParam.pMotionTextureIndexToDeltaQp[pCurMb->iMbXY], pWelsSvcRc->iMinFrameQp,pWelsSvcRc->iMaxFrameQp);}pCurMb->uiChromaQp    = g_kuiChromaQpTable[CLIP3_QP_0_51 (iLumaQp + kuiChromaQpIndexOffset)];pCurMb->uiLumaQp      = iLumaQp;
}

WelsRcMbInfoUpdateGom函数

  1. 功能:通过收集和更新宏块的编码信息来帮助编码器动态调整编码参数,以优化视频质量和编码效率。
  2. 原理过程
  • 函数参数:
    • pEncCtx: 指向编码上下文的指针,包含编码过程中所需的全局信息。
    • pCurMb: 指向当前宏块的指针。
    • iCostLuma: 当前宏块的亮度成本,用于码率控制。
    • pSlice: 指向当前切片的指针。
  • 局部变量:
    • pWelsSvcRc: 指向服务层码率控制结构的指针。
    • pSOverRc: 指向切片覆盖码率控制结构的指针。
    • kiComplexityIndex: 复杂度指数,用于码率控制策略。
  • 主要逻辑:
    • 计算当前宏块的比特数iCurMbBits,即从切片开始到当前宏块的比特流位置差。
    • 更新切片的总比特数iFrameBitsSlice和GOM(Group of Macroblocks)的总比特数iGomBitsSlice。
  • 码率控制相关操作:
    • 累加当前宏块的亮度成本iCostLuma到对应复杂度指数的成本数组pGomCost中。
    • 如果当前宏块的比特数大于0,更新切片的总QP(量化参数)和宏块计数器。
  • 设计目的:
    • 该函数的目的是在编码过程中收集和更新宏块的相关信息,以便进行有效的码率控制。
  • 关键功能:
    • 函数通过更新宏块的比特数和亮度成本,为后续的码率控制决策提供数据支持。
  1. 源码
void WelsRcMbInfoUpdateGom (sWelsEncCtx* pEncCtx, SMB* pCurMb, int32_t iCostLuma, SSlice* pSlice) {SWelsSvcRc* pWelsSvcRc            = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];SRCSlicing* pSOverRc              = &pSlice->sSlicingOverRc;const int32_t kiComplexityIndex   = pSOverRc->iComplexityIndexSlice;int32_t iCurMbBits = pEncCtx->pFuncList->pfGetBsPosition (pSlice) - pSOverRc->iBsPosSlice;pSOverRc->iFrameBitsSlice += iCurMbBits;pSOverRc->iGomBitsSlice += iCurMbBits;pWelsSvcRc->pGomCost[kiComplexityIndex] += iCostLuma;if (iCurMbBits > 0) {pSOverRc->iTotalQpSlice += pCurMb->uiLumaQp;pSOverRc->iTotalMbSlice++;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/31678.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“打造智能售货机系统,基于ruoyi微服务版本开源项目“

目录 # 开篇 售货机术语 1. 表设计说明 2. 页面展示 2.1 区域管理页面 2.2 合作商管理页面 2.3 点位管理页面 3. 建表资源 3.1 创建表的 SQL 语句&#xff08;包含字段备注&#xff09; 1. Region 表 2. Node 表 3. Partner 表 4. 创建 tb_vending_machine 表的 S…

【启明智显产品介绍】Model3C工业级HMI芯片详解专题(一)芯片性能

【启明智显产品介绍】工业级HMI芯片Model3C详解&#xff08;一&#xff09;芯片性能 Model3C 是一款基于 RISC-V 的高性能、国产自主、工业级高清显示与智能控制 MCU&#xff0c;配置平头哥E907&#xff0c;主频400MHz&#xff0c;强大的 2D 图形加速处理器、PNG/JPEG 解码引擎…

【Conda】修改 Conda 默认的虚拟环境位置

文章目录 问题描述分析与解决查看默认安装位置修改 .condarc 文件修改权限 参考资料 问题描述 Conda 的虚拟环境默认安装在 C 盘。时间久了&#xff0c;C 盘上的内存会被大量占用&#xff0c;影响电脑性能。于是想到修改虚拟环境的默认存放位置&#xff0c;改到自定义的位置。…

找不到d3dx9_43.dll无法继续执行代码的几种解决方法

在工作或生活使用电脑都会遇到丢失dll文件应用无法启动的情况&#xff0c;比如你安装完一款你最喜欢的游戏在启动的时候提示系统缺少d3dx9_39.dll、d3dx9_40.dll、d3dx9_41.dll、d3dx9_42.dll、d3dx9_43.dll、xinput1_3.dll 文件而无法正常游戏&#xff0c;或你在工作的时候安装…

分享HTML显示2D/3D时间

效果截图 实现代码 <!DOCTYPE html> <head> <title>three.jscannon.js Web 3D</title><meta charset"utf-8"><meta name"viewport" content"widthdevice-width,initial-scale1,maximum-scale1"><meta n…

图神经网络学习笔记

文章目录 一、图神经网络应用领域分析二、图基本模块定义三、邻接矩阵的定义四、GNN中常见任务五、消息传递计算方法六、多层GCN的作用七、GCN基本模型概述八、图卷积的基本计算方法九、邻接的矩阵的变换十、GCN变换原理解读 本笔记参考自b站up主小巴只爱学习的图神经网络教程 …

创建OpenWRT虚拟机

环境&#xff1a;Ubuntu 2204&#xff0c;VM VirtualBox 7.0.18 安装必备软件包&#xff1a; sudo apt update sudo apt install subversion automake make cmake uuid-dev gcc vim build-essential clang flex bison g gawk gcc-multilib g-multilib gettext git libncurses…

C语言中操作符详解(一)

众所周知&#xff0c;在我们的C语言中有着各式各样的操作符&#xff0c;并且在此之前呢&#xff0c;我们已经认识并运用了许许多多的操作符&#xff0c;都是诸君的老朋友了昂 操作符作为我们使用C语言的一个非常非常非常重要的工具&#xff0c;诸君一定要加以重视&#xff0c;…

大模型如何改变世界?李彦宏:未来至少一半人要学会“提问题“

2023年爆火的大模型&#xff0c;对我们来说意味着什么&#xff1f; 百度创始人、董事长兼CEO李彦宏认为&#xff0c;“大模型即将改变世界。” 5月26日&#xff0c;李彦宏参加了在北京举办的2023中关村论坛&#xff0c;发表了题为《大模型改变世界》的演讲。李彦宏认为&#…

为什么我在 PostgreSQL 中 Commit 很慢?

有时&#xff0c;我们的一位客户会查看数据库中最耗时的语句&#xff08;使用pg_stat_statements或pgBadger&#xff09;&#xff0c;并发现COMMIT排名靠前。通常&#xff0c;COMMIT这是 PostgreSQL 中非常快的语句&#xff0c;因此值得研究。在本文中&#xff0c;我将探讨速度…

Go微服务: redis分布式锁在集群中可能遇到的问题及其解决方案

概述 我们的 redis 一般都是集群来给我们程序提供服务的&#xff0c;单体的redis现在也不多见 看到上面是主节点redis和下面是6个重节点redis&#xff0c;主节点和重节点的通讯都是畅通没问题的这个时候&#xff0c;我们有 gorouting 写我们的数据&#xff0c;那它就会用到我们…

(Python)可变类型不可变类型;引用传递值传递;浅拷贝深拷贝

从一段代码开始说事&#xff0c;先上代码&#xff1a; a [[1],[2],[3]] b [[4,5],[6,7],[7,8]] for i,j in zip(a,b):print(i,j)i [9]#i[0] 8j[:2][1,2]print(i, j) print(a) print(b) 运行的结果&#xff1a; [1] [4, 5] [9] [1, 2] [2] [6, 7] [9] [1, 2] [3] [7, 8] …

Homebrew使用

官网&#xff1a;https://brew.sh/ 安装&#xff1a; 简介&#xff1a;https://www.jianshu.com/p/f4c9cf0733ea 比如&#xff0c;安装maven: 1、brew install maven 2、查看安装路径&#xff1a;brew list maven 具体参考&#xff1a;https://blog.csdn.net/m0_67402970/arti…

MPLS-LDP(个人学习笔记)

定义 标签分发协议LDP&#xff08;Label Distribution Protocol&#xff09;是多协议标签交换MPLS的一种控制协议&#xff0c;负责转发等价类FEC的分类、标签的分配以及标签交换路径LSP的建立和维护等操作。LDP规定了标签分发过程中的各种消息以及相关处理过程 术语 LDP会话&a…

【尚庭公寓SpringBoot + Vue 项目实战】移动端找房功能(二十一)

【尚庭公寓SpringBoot Vue 项目实战】移动端找房功能&#xff08;二十一&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】移动端找房功能&#xff08;二十一&#xff09;1、业务介绍2、接口开发2.1、地区信息2.2、获取全部支付方式列表2.3、房间信息2.2.1. 根据条…

python基础1.1-格式化输出(%用法和format用法)

目录 %用法 format用法 %用法 1、整数的输出 %o —— oct 八进制 %d —— dec 十进制 %x —— hex 十六进制 1 >>> print(%o % 20) 2 24 3 >>> print(%d % 20) 4 20 5 >>> print(%x % 20) 6 142、浮点数输出 &#xff08;1&#xff09;格式化…

鸿蒙开发系统基础能力:【@ohos.accessibility (辅助功能)】

辅助功能 说明&#xff1a; 本模块首批接口从 API version 7 开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import accessibility from ohos.accessibility;AbilityState 辅助应用状态类型。 系统能力&#xff1a;以下各项对应的…

智能体合集

海外版coze: 前端代码助手 后端代码助手&#xff1a; 前端代码助手&#xff1a;

添加右键菜单(以git为例)

1、打开注册表编辑器 打开系统注册表&#xff0c;使用组合键“Win R”输入“regedit”。 依次展开”HKEY_CLASSES_ROOT\Directory\Background\shell”。 2、新建右键菜单项 在[Background]下找到“shell”如果没有则新建项shell&#xff0c;接着在“shell”下右键-新建项名…

基于DPU的云原生裸金属网络解决方案

1. 方案背景和挑战 裸金属服务器是云上资源的重要部分&#xff0c;其网络需要与云上的虚拟机和容器互在同一个VPC下&#xff0c;并且能够像容器和虚拟机一样使用云的网络功能和能力。 传统的裸金属服务器使用开源的 OpenStack Ironic 组件&#xff0c;配合 OpenStack Neutron…