openh264 帧级码率控制原理:RcCalculateIdrQp 函数

RcCalculateIdrQp函数

功能

在码控中,当eSliceType为I_SLICE时 计算 IDR 帧的帧级量化参数QP 值。

原理过程

  • 初始化变量:
    • dBpp:初始化为0,用来存储比特率每像素(bits per pixel)的值。
    • i:一个整型循环变量。
  • 注释说明:
    • 提供了不同分辨率和帧率下的目标比特率每像素值(bpp)和对应的量化参数(QP)示例。
  • 定义数组:
    • dBppArray:一个二维数组,存储不同分辨率下的比特率每像素值的阈值。
    • dInitialQPArray:一个二维数组,存储不同分辨率下对应的初始量化参数。
    • iQpRangeArray:一个二维数组,存储量化参数的范围。
  • 计算帧复杂度:
    • 根据编码参数的用途类型(iUsageType),可能使用不同的方法来计算帧复杂度(iFrameComplexity)。
  • 获取编码器的比特率控制和空间层配置:
    • pWelsSvcRc:指向比特率控制结构体的指针。
    • pDLayerParam:指向空间层配置的指针。
    • pDLayerParamInternal:指向空间层内部配置的指针。
  • 计算比特率每像素值(dBpp):
    • 如果输出帧率、视频宽度和高度都大于0,则根据空间层的比特率、输出帧率、视频宽度和高度计算dBpp。
    • 如果上述条件不满足,则将dBpp设置为0.1,这可能是一个默认值或者最小值。
  • 分辨率与索引关联:
    • 根据视频的分辨率(宽度乘以高度)来设置iBppIndex。这个索引将用于选择适当的比特率每像素(bpp)阈值和初始量化参数。
    • iBppIndex为0时,对应90p视频(160x90像素)。
    • iBppIndex为1时,对应180p视频(320x180像素)。
    • iBppIndex为2时,对应360p视频(640x360像素)。
    • 如果分辨率大于360p,则iBppIndex默认为3。
  • 搜索合适的bpp阈值:
    • 使用一个循环来搜索dBppArray中不超过当前dBpp值的最大阈值。循环中的i变量从0开始,直到找到合适的阈值或达到数组的最后一个元素。
  • 确定量化参数范围:
    • 根据找到的阈值索引i和iBppIndex,从iQpRangeArray中获取量化参数的最大值iMaxQp和最小值iMinQp。
  • 量化参数范围的调整:
    • 使用WELS_CLIP3函数来确保iMinQp和iMaxQp在编码器设定的最小量化参数pWelsSvcRc->iMinQp和最大量化参数pWelsSvcRc->iMaxQp之间。
  • 检查是否为第一个IDR帧:
    • 如果pWelsSvcRc->iIdrNum等于0,表示当前正在处理的是序列的第一个IDR帧。
  • 设置第一个IDR帧的初始量化参数:
    • 对于第一个IDR帧,使用dInitialQPArray数组中对应iBppIndex和索引i的值作为初始量化参数iInitialQp。
  • 处理非第一个IDR帧:
    • 如果当前IDR帧不是序列中的第一个IDR帧,则根据前一个IDR帧的复杂度来计算量化参数。
  • 调整内部分块复杂度:
    • 如果iNumberMbFrame(帧的宏块数)不等于iIntraMbCount(帧内的内部分块数),则重新计算iIntraComplexity,即内部分块的复杂度。
  • 计算复杂度比率:
    • 使用WELS_DIV_ROUND64函数计算iFrameComplexity(当前帧的复杂度)与iIntraComplxMean(平均内部分块复杂度)的比率iCmplxRatio,并且乘以一个常数INT_MULTIPLY。
  • 限制复杂度比率的范围:
    • 使用WELS_CLIP3函数将iCmplxRatio限制在INT_MULTIPLY - FRAME_CMPLX_RATIO_RANGE和INT_MULTIPLY + FRAME_CMPLX_RATIO_RANGE之间。
  • 计算量化步长:
    • 根据iIntraComplexity、iCmplxRatio和目标比特数iTargetBits计算量化步长iQStep,使用WELS_DIV_ROUND函数。
  • 将量化步长转换为量化参数:
    • 使用RcConvertQStep2Qp函数将量化步长iQStep转换为量化参数iInitialQp。
  • 限制初始量化参数:
    • pWelsSvcRc->iInitialQp = WELS_CLIP3 (pWelsSvcRc->iInitialQp, iMinQp, iMaxQp);
    • 使用WELS_CLIP3函数确保iInitialQp(初始量化参数)在预定义的最小量化参数iMinQp和最大量化参数iMaxQp之间。这是为了确保量化参数不会超出设定的范围。
  • 设置全局量化参数:
    • pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp;
    • 将初始量化参数赋值给编码上下文pEncCtx中的全局量化参数iGlobalQp。这个全局参数会被编码过程中的其他部分使用。
  • 转换量化参数为量化步长:
    • pWelsSvcRc->iQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp);
    • 将量化参数转换为量化步长iQStep。量化步长是比特率控制算法中的一个中间参数,用于进一步的计算。
  • 记录最后计算的量化参数:
    • pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp;
    • 将当前的全局量化参数保存为最后计算的量化参数iLastCalculatedQScale。用于跟踪和调整编码过程中的量化参数。
  • 设置帧的最小和最大量化参数:
    • pWelsSvcRc->iMinFrameQp = WELS_CLIP3 (pEncCtx->iGlobalQp - DELTA_QP_BGD_THD, iMinQp, iMaxQp);
    • pWelsSvcRc->iMaxFrameQp = WELS_CLIP3 (pEncCtx->iGlobalQp + DELTA_QP_BGD_THD, iMinQp, iMaxQp);
    • 分别计算帧的最小量化参数iMinFrameQp和最大量化参数iMaxFrameQp。它们是基于全局量化参数iGlobalQp减去或加上一个阈值DELTA_QP_BGD_THD来计算的,然后使用WELS_CLIP3函数确保结果在iMinQp和iMaxQp的范围内。

原理流程图

在这里插入图片描述

源码

void RcCalculateIdrQp (sWelsEncCtx* pEncCtx) {double dBpp = 0;int32_t i;//64k@6fps for 90p:     bpp 0.74    QP:24
//192k@12fps for 180p:  bpp 0.28    QP:26
//512k@24fps for 360p:  bpp 0.09    QP:30
//1500k@30fps for 720p: bpp 0.05    QP:32double dBppArray[4][3] = {{0.5, 0.75, 1.0}, {0.2, 0.3, 0.4}, {0.05, 0.09, 0.13}, {0.03, 0.06, 0.1}};int32_t dInitialQPArray[4][4] = {{28, 26, 24, 22}, {30, 28, 26, 24}, {32, 30, 28, 26}, {34, 32, 30, 28}};int32_t iBppIndex = 0;int32_t iQpRangeArray[4][2] = {{37, 25}, {36, 24}, {35, 23}, {34, 22}};int64_t iFrameComplexity = pEncCtx->pVaa->sComplexityAnalysisParam.iFrameComplexity;if (pEncCtx->pSvcParam->iUsageType == SCREEN_CONTENT_REAL_TIME) {SVAAFrameInfoExt* pVaa = static_cast<SVAAFrameInfoExt*> (pEncCtx->pVaa);iFrameComplexity = pVaa->sComplexityScreenParam.iFrameComplexity;}SWelsSvcRc* pWelsSvcRc                = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];SSpatialLayerConfig* pDLayerParam     = &pEncCtx->pSvcParam->sSpatialLayers[pEncCtx->uiDependencyId];SSpatialLayerInternal* pDLayerParamInternal       = &pEncCtx->pSvcParam->sDependencyLayers[pEncCtx->uiDependencyId];if (pDLayerParamInternal->fOutputFrameRate > EPSN && pDLayerParam->iVideoWidth && pDLayerParam->iVideoHeight)dBpp = (double) (pDLayerParam->iSpatialBitrate) / (double) (pDLayerParamInternal->fOutputFrameRate *pDLayerParam->iVideoWidth *pDLayerParam->iVideoHeight);elsedBpp = 0.1;
//Area*2if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 28800) // 90p video:160*90iBppIndex = 0;else if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 115200) // 180p video:320*180iBppIndex = 1;else if (pDLayerParam->iVideoWidth * pDLayerParam->iVideoHeight <= 460800) // 360p video:640*360iBppIndex = 2;elseiBppIndex = 3;//Searchfor (i = 0; i < 3; i++) {if (dBpp <= dBppArray[iBppIndex][i])break;}int32_t iMaxQp = iQpRangeArray[i][0];int32_t iMinQp = iQpRangeArray[i][1];iMinQp = WELS_CLIP3 (iMinQp, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp);iMaxQp = WELS_CLIP3 (iMaxQp, pWelsSvcRc->iMinQp, pWelsSvcRc->iMaxQp);if (0 == pWelsSvcRc->iIdrNum) { //the first IDR framepWelsSvcRc->iInitialQp = dInitialQPArray[iBppIndex][i];} else {//obtain the idr qp using previous idr complexityif (pWelsSvcRc->iNumberMbFrame != pWelsSvcRc->iIntraMbCount) {pWelsSvcRc->iIntraComplexity = pWelsSvcRc->iIntraComplexity * pWelsSvcRc->iNumberMbFrame /pWelsSvcRc->iIntraMbCount;}int64_t iCmplxRatio = WELS_DIV_ROUND64 (iFrameComplexity * INT_MULTIPLY,pWelsSvcRc->iIntraComplxMean);iCmplxRatio = WELS_CLIP3 (iCmplxRatio, INT_MULTIPLY - FRAME_CMPLX_RATIO_RANGE, INT_MULTIPLY + FRAME_CMPLX_RATIO_RANGE);pWelsSvcRc->iQStep = WELS_DIV_ROUND ((pWelsSvcRc->iIntraComplexity * iCmplxRatio),(pWelsSvcRc->iTargetBits * INT_MULTIPLY));pWelsSvcRc->iInitialQp = RcConvertQStep2Qp (pWelsSvcRc->iQStep);}pWelsSvcRc->iInitialQp = WELS_CLIP3 (pWelsSvcRc->iInitialQp, iMinQp, iMaxQp);pEncCtx->iGlobalQp = pWelsSvcRc->iInitialQp;pWelsSvcRc->iQStep = RcConvertQp2QStep (pEncCtx->iGlobalQp);pWelsSvcRc->iLastCalculatedQScale = pEncCtx->iGlobalQp;pWelsSvcRc->iMinFrameQp = WELS_CLIP3 (pEncCtx->iGlobalQp - DELTA_QP_BGD_THD, iMinQp, iMaxQp);pWelsSvcRc->iMaxFrameQp = WELS_CLIP3 (pEncCtx->iGlobalQp + DELTA_QP_BGD_THD, iMinQp, iMaxQp);}

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

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

相关文章

代码还原动态调试之 pstree 0x68(%rbx,%rdx,8)

结构体里的数组访问 &#xff0c;其中rbx是结构体的基址&#xff0c;rdx为数组下标&#xff0c;8为一个数组位占8个字节&#xff0c;0x68为结构体中数组的基址&#xff1b; 0 8 (gdb) x/25xg $rbx-0xc0 0x5555555691a0: 0x0000000000000000 0x000000000…

人工智能驱动材料科学前沿:微软与PNNL联合推进电池材料创新

新型电池技术的研发对实现绿色能源目标具有决定性意义 微软公司与美国太平洋西北国家实验室&#xff08;PNNL&#xff09;近期开展了一项开创性的合作&#xff0c;利用尖端人工智能技术&#xff0c;在极短时间内完成对海量潜在电池材料的系统筛选。 微软和PNNL的研究团队采用了…

解决数据孤岛/计算消耗/误差累积问题,上海人工智能实验室苏锐:FengWu-GHR实现AI气象预测多重突破

「AI 方法出现之前&#xff0c;每 10 年才可以提高 1 天的气象预报技巧&#xff0c;而引入 AI 后&#xff0c;几个月就能提高预报技巧。」 在 2024 北京智源大会「AI for Science」论坛上&#xff0c;上海人工智能实验室青年研究员苏锐回顾了 AI 气象预报的历史发展&#xff0…

深入了解 AndroidX ConstraintLayout 中的 Barrier

androidx.constraintlayout.widget.Barrier&#xff08;简称Barrier&#xff09;是 ConstraintLayout 2.0 中引入的一个新特性&#xff0c;它可以极大地简化复杂布局的实现。本文将详细介绍Barrier 的概念、使用方法以及在实际开发中的应用场景。 什么是 Barrier&#xff1f; …

将一个整型数字翻转

1 题目 输入一个整数n&#xff0c;并将其反转后输出。 2 分析 反转一个整数可以想象成逆置字符串&#xff0c;只不过在这里是以数的形式&#xff0c;如1234&#xff0c;反转后4321&#xff0c;这里可以采用除余分解数的方法&#xff0c;也就是当n不为0时&#xff0c;将其取余…

Leaflet 加载非标栅格切片

Leaflet支持的坐标系Leaflet默认加载切片主要支持WGS84(4326)和web_mecator(3857), 具体的切片规则如下: 1)4326 "lods": [ { "level": 0, "resolution": 1.40625,

web前端组织分析:深入剖析其结构、功能与未来趋势

web前端组织分析&#xff1a;深入剖析其结构、功能与未来趋势 在数字化浪潮的推动下&#xff0c;Web前端组织作为连接用户与数字世界的桥梁&#xff0c;其重要性日益凸显。本文将从四个方面、五个方面、六个方面和七个方面对Web前端组织进行深入分析&#xff0c;揭示其结构特点…

超详细的Linux-Conda环境安装教程

Conda是一个强大的包管理器和环境管理器&#xff0c;广泛应用于数据科学和机器学习领域。本文将详细介绍如何在CentOS系统上安装和配置Conda环境&#xff0c;从而助你高效管理Python及其他语言的开发环境。 前言 在开始安装Conda之前&#xff0c;请确保你的CentOS系统已经更新…

产品心理学:曝光效应

曝光效应&#xff08;the exposure effect or the mere exposure effect&#xff09;&#xff1a;又谓多看效应、&#xff08;简单、单纯&#xff09;暴露效应、&#xff08;纯粹&#xff09;接触效应等等。 它是一种心理现象&#xff0c;指的是我们会偏好自己熟悉的事物&#…

Python开源大模型ChatTTS构建聊天机器人与语音识别系统的好选择

随着人工智能技术的不断发展&#xff0c;开源大模型已成为越来越多开发者关注的焦点。其中&#xff0c;ChatTTS是一个备受瞩目的开源项目&#xff0c;它是一款基于Python的自然语言处理库&#xff0c;可用于构建聊天机器人和语音识别系统。  **项目介绍**  ChatTTS是一个开…

基于PCL实现多边形框选点云并进行裁剪(附C++源码)

文章目录 一.算法效果二.算法原理PNPoly算法直线相交性判断三.代码实现一.算法效果 通过在PCL可视化界面上绘制2D封闭多边形来提取位于该封闭多边形内部或者外部的 的点,算法效果如下: 图1多边形裁剪点云效果图 二.算法原理 PNPoly算法 2D多边形框选裁剪点云,实际上可以简…

java LambdaQueryWapper日期查询

Java LambdaQueryWrapper日期查询 Java LambdaQueryWrapper是MyBatis-Plus提供的一个强大的查询条件构造器。它可以方便地进行复杂的查询操作。在实际开发中&#xff0c;经常需要根据日期进行查询&#xff0c;并且还需要支持各种日期格式的输入。本文将介绍如何使用LambdaQuer…

AI交互数字人如何赋能数智教育?

随着AI交互数字人技术的飞速发展&#xff0c;教育领域正经历着前所未有的变革。AI交互数字人为教育领域注入了全新活力&#xff0c;重塑着教学模式&#xff0c;为学生带来沉浸式学习体验。 AI交互数字人在教育领域中&#xff0c;可以应用在&#xff1a; 1、个性化学习教学指导…

RPA案例学习

京东采集数据 一、搜索商品 流程块 相对应源代码 二、抓取数据 流程块 相对应源代码

React-Redux学习笔记(自用)

1. 环境搭建 插件安装&#xff1a;Redux Toolkit和react-redux npm i reduxjs/toolkit react-redux2、 store目录结构设计 集中状态管理的部分会单独创建一个store目录&#xff08;在src下&#xff09;应用通常会有很多个子模块&#xff0c;所以还会有个modules目录&#x…

医学记录 --- 口腔异味

逻辑图地址 症状 1、反复口臭、腹胀、放屁多还臭 2、牙结石 3、龋病 4、牙周炎 病因 1、口腔卫生不良。如果你不刷牙、不使用牙线或不定期洗牙&#xff0c;口腔中的细菌会繁殖并产生恶臭。 2、吸烟、饮酒、吃辛辣食物、胃肠道问题、口腔干燥等 3、吃糖后没有及时刷牙&#…

React useEffect 执行时机

默认情况下&#xff0c;Effect 在每次渲染&#xff08;包括初始渲染&#xff09;后运行。 如果 React 的所有依赖项都与上次渲染时的值相同&#xff0c;则将跳过本次 Effect。 useEffect(() > {// 这里的代码会在每次渲染后执行 });useEffect(() > {// 这里的代码只会在…

VMware虚拟机三种网络模式设置 - NAT(网络地址转换模式)

一、前言 在前一篇《Bridged&#xff08;桥接模式&#xff09;》中&#xff0c;我详细介绍了虚拟机网络模式设置中的桥接模式。今天详细讲解一下NAT&#xff08;网络地址转换模式&#xff09;。 在虚拟机&#xff08;VM&#xff09;中&#xff0c;NAT&#xff08;Network Addre…

ai智能训练为什么用gpu?

AI智能训练通常需要进行大量的数学计算&#xff0c;特别是矩阵运算&#xff0c;这些计算在GPU&#xff08;图形处理单元&#xff09;上执行得更快。为什么使用GPU而不是CPU的几个要点&#xff1a; 并行处理能力&#xff1a;GPU设计之初是为了处理图形和图像&#xff0c;这需要同…

产线工控安全需要考虑哪些因素

随着工业4.0的推进&#xff0c;智能制造和自动化产线在现代工业中扮演着越来越重要的角色。然而&#xff0c;随着技术的进步&#xff0c;工控系统的安全问题也日益凸显。MCK主机加固方案作为一种先进的安全措施&#xff0c;为产线工控安全提供了强有力的保障。 MCK主机加固方案…