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…

学习java第一百零六天

Spring的后置处理器 BeanPostProcessor&#xff1a;Bean的后置处理器&#xff0c;主要在bean初始化前后工作。 InstantiationAwareBeanPostProcessor&#xff1a;继承于BeanPostProcessor&#xff0c;主要在实例化bean前后工作&#xff1b; AOP创建代理对象就是通过该接口实现…

用LangChain调用Ollama的时候一个小问题

说来让人无语&#xff0c;简单记录一下。安装好Ollama后&#xff0c;我们通常通过访问http://127.0.0.1:11434来测试其是否正常&#xff0c;通常会出来“Ollama is running”&#xff0c;然后我习惯性地从Chrome把地址拷贝到VS Code&#xff0c; oembed OllamaEmbeddings(bas…

【启明智显产品介绍】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主小巴只爱学习的图神经网络教程 …

【Android面试八股文】你能说一说View绘制流程与自定义View注意点吗?

文章目录 一、自定义View的构造函数以及各参数的用法二、自定义View的几种方式三、自定义View的绘制流程四、自定义View需要注意的一些点五、举个例子一、自定义View的构造函数以及各参数的用法 在Android中,自定义View通常需要提供多个构造函数,以适应不同的使用场景。主要…

创建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;发表了题为《大模型改变世界》的演讲。李彦宏认为&#…

在centos服务器上部署nginx容器

1.下载nginx镜像 2.导入镜像 docker load -i nginx.tar 3. 查看导入的镜像 docker images 4. 运行镜像 docker run -d -p 80:80 --name my-nginx nginx 5. 访问Nginx 其他 1.查看所有正在运行的Docker容器:docker ps 2.查看所有镜像:docker images 3.使用Docker命令…

Html集成 vue3,js文件访问vue内的方法和属性

标题页面代码如下 如下代码,假设index.js文件中有个 getUserInfo函数, 1.我们首先需要把 let vm app.mount(‘#app’);的vm传到js文件中,这样才能访问vue中定义的元素和函数 2.vue中定义的函数需要return出去才能在js文件中调用 3.js文件中,调用vue中的函数作为参数即可传参到…

为什么我在 PostgreSQL 中 Commit 很慢?

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

求职刷题力扣DAY24--回溯算法

1. 77. 组合 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4], ]示例 2&#xff1a; 输入&#xff1…

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…

日语 13 14

13. スピーチの依頼 いらい 自信 自信 自信 自信 自信 じしん 折り入って 折り入って 折り入って おりいって  诚恳 頼み 頼み 頼み 頼み 頼み  たのみ 请求 整備 整備 整備 整備 整備 せいび 维修 肥満 肥満 肥満 肥満 肥満 ひまん 肥胖 権利 …