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,一经查实,立即删除!

相关文章

人工智能驱动材料科学前沿:微软与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; …

产品心理学:曝光效应

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

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

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

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…

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

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

希喂、K9、弗列加特主食冻干测评:这次,我们去了美国的实验室

主食冻干你有喂过吗&#xff1f; 作为有七年养猫经验的铲屎官&#xff0c;我强烈推荐&#xff0c;真的值得一试&#xff01; 在宠物经济蓬勃发展的今天&#xff0c;养猫已经成为了一门学问。人们开始追求更加科学、健康的养猫方式。大量喂养案例表明&#xff0c;传统的商业猫粮…

算法训练与程序竞赛题目集合(L2)

目录 L2-001 城市间紧急救援 输入格式: 输出格式: 输入样例: 输出样例: L2-002 链表去重 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; 输出样例&#xff1a; L2-003 月饼 输入格式&#xff1a; 输出格式&#xff1a; 输入样例&#xff1a; …

排序算法Java_实现

1.引言 查找和排序算法是算法的入门知识,其经典思想可以用于比较常见。 1.1 内部排序和外部排序的区别 内部排序:待排序记录存放在计算机随机存储器中(内存)进行排序的过程。 外部排序:待排序记录的数量很大,以至于内存不能一次容纳全部记录,所以在排序过程中需要对外…

LabVIEW_TDMS

1.TDMS设置属性 想给这里写属性怎么整 使用TDMS设置属性函数时&#xff0c;对组名称与通道名称不设置&#xff0c;即可达到上图中的样式。 PS&#xff1a;属性名称如果设置一样则最终生效的值为最后写入的值。如将属性2修改为属性1&#xff0c;则最终只有1个属性1&#xff0c…

Qt项目学习-20240617

Qt项目学习 1.0 文件构建 1.1 预处理命令 C预处理命令是编译过程中的第一步&#xff0c;发生在编译器进行实际编译之前。预处理器&#xff08;preprocessor&#xff09;执行这些命令&#xff0c;它们不是C语言的一部分&#xff0c;但对源代码的编译过程至关重要。以下是一些常…

JavaScript-逻辑中断

学习目标&#xff1a; 掌握逻辑中断 学习内容&#xff1a; 语法逻辑运算符里的短路 语法&#xff1a; function fn(x, y) {x x || 0y y || 0console.log(x y)}fn(1, 2)fn()逻辑运算符里的短路&#xff1a; 短路&#xff1a;只存在于&&和||中&#xff0c;当满足一定…

Vue 前后端分离开发:懒人必备的API SDK

在前后端分离的项目中,前后端通过API进行通信和数据交换。随着项目规模的扩大,API的数量可能从几十个增加到几百个。为了简化API的编写和维护,我们可以利用JavaScript的特性,通过动态生成接口方法来实现懒人开发。本文将详细介绍如何统一接口调用方式、抽象和封装接口,并利…

C++项目——负载均衡在线OJ

前言 学习了这么久的C/C与Linux&#xff0c;终于到了做项目的时候&#xff0c;想想还是有点小激动&#xff0c;哈哈哈哈哈。我们的目标是做一个跟leetcode、牛客类似的在线OJ系统&#xff0c;功能阉割了一些&#xff0c;比如说登录、论坛、求职等等。主要实现了提交题目与判定…

旅游文化管理平台

摘 要 乡村振兴战略典型村落——战旗村&#xff0c;依靠自身优秀的资源迅猛发展。新冠肺炎疫情的影响下&#xff0c;我国旅游业受到巨大冲击。2020年在短暂缓冲后国内旅游业呈现缓慢恢复的态势。新型冠状病毒爆发&#xff0c;第三产业尤其是旅游业发展逐渐走向低靡&#xff0c…

go语言对接S3存储的SDK(支持minio和OSS)

背景 在某个项目中&#xff0c;客户要求支持S3协议的存储&#xff0c;因为之前的项目是go来开发的支持的oss和minio 。 但并不一定支持S3的协议&#xff0c;而且使用了二种SDK&#xff0c;感觉比较麻烦。 既然客户提出来了要求。那我们改一下就是了。 操作 引入 go语言中有对…

AI时代下的自动化代码审计工具

代码审计工具分享 吉祥学安全知识星球&#x1f517;除了包含技术干货&#xff1a;Java代码审计、web安全、应急响应等&#xff0c;还包含了安全中常见的售前护网案例、售前方案、ppt等&#xff0c;同时也有面向学生的网络安全面试、护网面试等。 这两年一直都在提“安全左移”&…