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

RcCalculatePictureQp 函数

函数功能

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

函数原理过程

  • 初始化各类变量;
  • 计算帧复杂度iFrameComplexity,如果iUsageType是SCREEN_CONTENT_REAL_TIME,重复赋值帧复杂度iFrameComplexity;
  • 如果iPFrameNum 等于 0;
    • 第一个 P 帧,则iLumaQp等于iInitialQp;
  • 如果iCurrentBitsLevel等于BITS_EXCEEDED;
    • iLumaQp等于iLastCalculatedQScale加上 一个常量;
    • 声明并计算一个变量iLastIdxCodecInVGop,它代表在视频组(Video Group of Pictures, VGop)中最后一个编码帧的索引。这里通过从iFrameCodedInVGop减去1来得到;
    • 如果iLastIdxCodecInVGop 小于 0,就通过加上VGOP_SIZE(视频组的大小)来调整;
    • 声明并计算一个变量iTlLast,它是根据iLastIdxCodecInVGop索引在iTlOfFrames数组中的时间层ID;
    • 计算时间层量化参数差iDeltaQpTemporal,它是当前时间层iTl与上一个时间层iTlLast的差值;
    • 如果上一个时间层是0(表示基础层),而当前时间层大于0(表示增强层),则增加iDeltaQpTemporal的值;
    • 如果当前时间层是0,而上一个时间层大于0,那么减少iDeltaQpTemporal的值;
  • 否则,
    • 调用WELS_DIV_ROUND64函数根据帧复杂度iFrameComplexity和帧复杂度均值iFrameCmplxMean计算复杂度变化率iCmplxRatio;
    • 调用WELS_CLIP3函数限制复杂度变化率iCmplxRatio值;
    • 调用WELS_DIV_ROUND函数根据iLinearCmplx、iCmplxRatio、iTargetBits计算量化步长iQStep;
    • 调用RcConvertQStep2Qp函数将量化步长iQStep转化为量化参数iLumaQp;
    • 声明并计算一个变量iLastIdxCodecInVGop,它代表在视频组(Video Group of Pictures, VGop)中最后一个编码帧的索引。这里通过从iFrameCodedInVGop减去1来得到;
    • 如果iLastIdxCodecInVGop 小于 0,就通过加上VGOP_SIZE(视频组的大小)来调整;
    • 声明并计算一个变量iTlLast,它是根据iLastIdxCodecInVGop索引在iTlOfFrames数组中的时间层ID;
    • 计算时间层量化参数差iDeltaQpTemporal,它是当前时间层iTl与上一个时间层iTlLast的差值;
    • 如果上一个时间层是0(表示基础层),而当前时间层大于0(表示增强层),则增加iDeltaQpTemporal的值;
    • 如果当前时间层是0,而上一个时间层大于0,那么减少iDeltaQpTemporal的值;
  • 根据iLastCalculatedQScale、iFrameDeltaQpLower、iDeltaQpTemporal、iMinQp、iMaxQp计算出量化参数最大值iMaxFrameQp和最小值iMinFrameQp;
  • 根据最大值iMaxFrameQp和最小值iMinFrameQp,限制亮度 qp 值iLumaQp;
  • 如果开启自适应量化;
    • 调用WELS_DIV_ROUND函数根据iAverMotionTextureIndexToDeltaQp重新计算出亮度 qp 值iLumaQp;
    • 根据最大值iMaxFrameQp和最小值iMinFrameQp,限制亮度 qp 值iLumaQp;
  • 调用RcConvertQp2QStep函数将亮度 qp 值iLumaQp转为量化步长iQStep;
  • 将亮度 qp 值iLumaQp赋值给iLastCalculatedQScale和帧级 qp 值iGlobalQp。

函数原理图

在这里插入图片描述

函数源码

void RcCalculatePictureQp (sWelsEncCtx* pEncCtx) {
  SWelsSvcRc* pWelsSvcRc        = &pEncCtx->pWelsSvcRc[pEncCtx->uiDependencyId];
  int32_t iTl                   = pEncCtx->uiTemporalId;
  SRCTemporal* pTOverRc         = &pWelsSvcRc->pTemporalOverRc[iTl];
  int32_t iLumaQp = 0;
  int32_t iDeltaQpTemporal = 0;
  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;
  }
  if (0 == pTOverRc->iPFrameNum) {
    iLumaQp = pWelsSvcRc->iInitialQp;
  } else if (pWelsSvcRc->iCurrentBitsLevel == BITS_EXCEEDED) {
    iLumaQp = pWelsSvcRc->iLastCalculatedQScale + DELTA_QP_BGD_THD;
//limit QP
    int32_t iLastIdxCodecInVGop = pWelsSvcRc->iFrameCodedInVGop - 1;
    if (iLastIdxCodecInVGop < 0)
      iLastIdxCodecInVGop += VGOP_SIZE;
    int32_t iTlLast = pWelsSvcRc->iTlOfFrames[iLastIdxCodecInVGop];
    iDeltaQpTemporal = iTl - iTlLast;
    if (0 == iTlLast && iTl > 0)
      iDeltaQpTemporal += 1;
    else if (0 == iTl && iTlLast > 0)
      iDeltaQpTemporal -= 1;

  } else {
    int64_t iCmplxRatio = WELS_DIV_ROUND64 (iFrameComplexity * INT_MULTIPLY,
                                            pTOverRc->iFrameCmplxMean);
    iCmplxRatio = WELS_CLIP3 (iCmplxRatio, INT_MULTIPLY - FRAME_CMPLX_RATIO_RANGE, INT_MULTIPLY + FRAME_CMPLX_RATIO_RANGE);

    pWelsSvcRc->iQStep = WELS_DIV_ROUND ((pTOverRc->iLinearCmplx * iCmplxRatio), (pWelsSvcRc->iTargetBits * INT_MULTIPLY));
    iLumaQp = RcConvertQStep2Qp (pWelsSvcRc->iQStep);
    WelsLog (& (pEncCtx->sLogCtx), WELS_LOG_DEBUG,
             "iCmplxRatio = %d,frameComplexity = %" PRId64 ",iFrameCmplxMean = %" PRId64 ",iQStep = %d,iLumaQp = %d", (int)iCmplxRatio,
             iFrameComplexity, pTOverRc->iFrameCmplxMean, pWelsSvcRc->iQStep, iLumaQp);
//limit QP
    int32_t iLastIdxCodecInVGop = pWelsSvcRc->iFrameCodedInVGop - 1;
    if (iLastIdxCodecInVGop < 0)
      iLastIdxCodecInVGop += VGOP_SIZE;
    int32_t iTlLast = pWelsSvcRc->iTlOfFrames[iLastIdxCodecInVGop];
    int32_t iDeltaQpTemporal = iTl - iTlLast;
    if (0 == iTlLast && iTl > 0)
      iDeltaQpTemporal += 1;
    else if (0 == iTl && iTlLast > 0)
      iDeltaQpTemporal -= 1;
  }
  pWelsSvcRc->iMinFrameQp =  WELS_CLIP3 (pWelsSvcRc->iLastCalculatedQScale - pWelsSvcRc->iFrameDeltaQpLower +
                                         iDeltaQpTemporal, pTOverRc->iMinQp, pTOverRc->iMaxQp) ;
  pWelsSvcRc->iMaxFrameQp =  WELS_CLIP3 (pWelsSvcRc->iLastCalculatedQScale + pWelsSvcRc->iFrameDeltaQpUpper +
                                         iDeltaQpTemporal, pTOverRc->iMinQp, pTOverRc->iMaxQp);

  iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iMinFrameQp, pWelsSvcRc->iMaxFrameQp);

  if (pEncCtx->pSvcParam->bEnableAdaptiveQuant) {

    iLumaQp =  WELS_DIV_ROUND (iLumaQp * INT_MULTIPLY - pEncCtx->pVaa->sAdaptiveQuantParam.iAverMotionTextureIndexToDeltaQp,
                               INT_MULTIPLY);
    iLumaQp = WELS_CLIP3 (iLumaQp, pWelsSvcRc->iMinFrameQp, pWelsSvcRc->iMaxFrameQp);
  }
  pWelsSvcRc->iQStep = RcConvertQp2QStep (iLumaQp);
  pWelsSvcRc->iLastCalculatedQScale = iLumaQp;
  pEncCtx->iGlobalQp = iLumaQp;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL【触发器、存储过程、函数、范式】

day53 MySQL 触发器 创建触发器&#xff1a;&#xff08;before &#xff1a; 前置触发器、after &#xff1a;后置触发器&#xff09; 语法&#xff1a; delimiter xx 指定分隔符xxcreate trigger 触发器名 [before | after] 触发事件 on 表名 for each row 执行语句begin…

maven:中央仓库验证方式改变:401 Content access is protected by token

前几天向maven中央仓库发布版本&#xff0c;执行上传命令mvn release:perform时报错了&#xff1a; [ERROR] Failed to execute goal org.sonatype.plugins:nexus-staging-maven-plugin:1.6.13:deploy (injected-nexus-deploy) on project xxxxx: Failed to deploy artifacts: …

智慧互联,Vatee万腾平台引领新潮流

在数字化、智能化的新时代&#xff0c;智慧互联正成为推动社会进步的重要力量。在这一潮流中&#xff0c;Vatee万腾平台凭借其卓越的技术实力和创新理念&#xff0c;正引领着新潮流&#xff0c;将智慧互联的理念融入生活的方方面面。 Vatee万腾平台是一个以大数据、云计算、人工…

C#利用SignalR实现通信事例Demo

1.服务端安装SignalR的Nuget包 dotnet add package Microsoft.AspNet.SignalR --version 2.4.3 2.接下来&#xff0c;创建一个ChatHub类&#xff0c;它是SignalR通信的核心&#xff1a; using Microsoft.AspNetCore.SignalR;public class ChatHub : Hub {public static Dict…

聊聊 C# dynamic 类型,并分享一个将 dynamic 类型变量转为其它类型的技巧和实例

前言 dynamic 是一种有别于传统变量类型的动态类型声明&#xff0c;刚开始接触可能在理解上会有些困难&#xff0c;可以简单地把它理解为一个盲盒&#xff0c;你可以任意猜测盒子有什么东西&#xff0c;并认为这些东西真正存在而进行处理&#xff0c;等到真正打开时&#xff0…

文章自动生成器,在线AI写作工具

随着人工智能AI技术的发展&#xff0c;AI技术被应用到越来越多的场景。对于需要创作内容的同学来说&#xff0c;AI写作-文章内容自动生成器是一个非常好的辅助工具。AI写作工具可以提升我们的创作效率&#xff0c;快速的生成文章&#xff0c;然后在根据需求进行调整修改即可。下…

语法制导的翻译和属性文法

属性的分类 1.综合属性 重写规则&#xff08;产生式&#xff09;左部符号的属性是综合属性。一个结点相应文法符号的属性值通过语法分析树中它的子节点的属性之值计算&#xff08;自底向上&#xff09; 2.继承属性 出现在重写规则右部的符号的属性。一个结点相应文法符号的属性…

概念描述——TCP/IP模型中的两个重要分界线

TCP/IP模型中的两个重要分界线 协议的层次概念包含了两个也许不太明显的分界线&#xff0c;一个是协议地址分界线&#xff0c;区分出高层与低层寻址操作&#xff1b;另一个是操作系统分界线&#xff0c;它把系统与应用程序区分开来。 高层协议地址界限 当我们看到TCP/P软件的…

没等来百度惊艳的All in AI,却等来了国产之光的盘古大模型 5.0

6月21日&#xff0c;华为开发者大会&#xff08;HDC 2024&#xff09;在广东东莞正式开幕。盘古大模型5.0的更新&#xff0c;也是此次HDC2024的另一项重头戏。在过去的一年中&#xff0c;盘古大模型正在疯狂向各行各业渗透。 此次&#xff0c;华为方面展示了他们在具身智能、医…

【面向对象】复习(二)

内存对齐 class A{ static int a; } int main(){ A obj; cout<<sizeof(obj); } 在你的代码中&#xff0c;class A 包含一个静态成员变量 a。静态成员变量不属于类的任何特定实例&#xff0c;而是属于整个类。因此&#xff0c;在计算类的实例大小时&#xff0c;静态…

C语言入门系列:指针入门(超详细)

文章目录 一&#xff0c;什么是指针1&#xff0c;内存2&#xff0c;指针是什么&#xff1f; 二&#xff0c;指针的声明1&#xff0c;声明指针类型变量2&#xff0c;二级指针 三&#xff0c;指针的计算1&#xff0c;两个指针运算符1.1 *运算符1.2 & 运算符1.3 &运算符与…

状态压缩DP——AcWing 291. 蒙德里安的梦想

状态压缩DP 定义 状态压缩DP是一种利用二进制数来表示状态的动态规划算法。它通过将状态压缩成一个整数&#xff0c;从而减少状态数量&#xff0c;提高算法效率。 运用情况 状态压缩DP通常用于解决具有状态转移和最优解性质的问题&#xff0c;例如组合优化、图论、游戏等问…

python-邮票组合问题

[题目描述] 某人有四张3分的邮票和三张5分的邮票&#xff0c;用这些邮票中的一张或若干张可以得到多少种不同的邮资&#xff1f;输入格式&#xff1a; 此题无输入。输出格式&#xff1a; 输出可以得到不同邮资的数量。 样例输入 无样例输出 19数据范围&#xff1a; 对于100%的…

华为---RIP路由协议的汇总

8.3 RIP路由协议的汇总 8.3.1 原理概述 当网络中路由器的路由条目非常多时&#xff0c;可以通过路由汇总(又称路由汇聚或路由聚合)来减少路由条目数&#xff0c;加快路由收敛时间和增强网络稳定性。路由汇总的原理是&#xff0c;同一个自然网段内的不同子网的路由在向外(其他…

与Vatee万腾平台同行,共创智能未来

在科技日新月异的今天&#xff0c;智能化已成为推动社会进步的重要力量。Vatee万腾平台&#xff0c;作为这一浪潮中的佼佼者&#xff0c;正以其独特的创新力和前瞻的视野&#xff0c;引领我们迈向智能未来。与Vatee万腾平台同行&#xff0c;我们不仅能享受到科技带来的便捷与舒…

[最新教程]Claude Sonnet 3.5注册方法详细步骤分享,新手小白收藏,文末免费送已注册的Claude账号

一.Claude sonnet 3.5大模型面世 6月21日&#xff0c;被称为“OpenAI 最强竞对”的大模型公司 Anthropic 发布了 Claude 3.5 系列模型中的第一个版本——Claude 3.5 Sonnet。 Anthropic 在官方博客中表示&#xff0c;Claude 3.5 Sonnet 提高了智能化的行业标准&#xff0c;在…

传统图像特征描述及提取方法

目录 一、图像特征描述 二、图像特征的分类 2.1 图像的点、线、面特征 2.2 图像的纹理形状特征 2.3 图像颜色特征 2.4图像的统计特征 三、图像特征提取的评价 一、图像特征描述 图像特征是一幅图像区别于另一幅图像最基本的特征,是其可以作为标志性的属性。 图像特征分为…

2024 年解锁 Android 手机的 7 种简便方法

您是否忘记了 Android 手机的 Android 锁屏密码&#xff0c;并且您的手机已被锁定&#xff1f;您需要使用锁屏解锁 Android 手机&#xff1f;别担心&#xff0c;您不是唯一一个忘记密码的人。我将向您展示如何解锁 Android 手机的锁屏。 密码 PIN 可保护您的 Android 手机和 G…

高考志愿填报,如何权衡学校和专业?

高考是人生的分水岭&#xff0c;成绩好的学生能就读更好的大学&#xff0c;获得更多的学习资源&#xff0c;但也有一些同学即使凭借高分数进入了高校&#xff0c;专业的学习过程却不尽如人意&#xff0c;他们也没有将100%的精力投入到专业学习当中。 无论高考结束之后获得了多…

python--fasApi学习(Dash+FastAPI框架)

在学习fastApi 框架时&#xff0c;发现了一个好用的框架&#xff0c;参考&#xff1a; 博客参考&#xff1a; https://blog.csdn.net/gitblog_00002/article/details/137331157下载文档并部署&#xff1a; 下载代码&#xff1a; git clone https://gitee.com/insistence2022/…