首页 > 编程语言 >openh264 宏块级码率控制源码分析

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

时间:2024-06-21 21:31:57浏览次数:15  
标签:QP 码率 宏块级 pSOverRc 宏块 源码 pWelsSvcRc pEncCtx

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 gom
    if (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 decision
    iBitsRatio = 10000 * iLeftBits / (iTargetLeftBits + 1);
    if (iBitsRatio < 8409)              //2^(-1.5/6)*10000
      pSOverRc->iCalculatedQpSlice += 2;
    else if (iBitsRatio < 9439)         //2^(-0.5/6)*10000
      pSOverRc->iCalculatedQpSlice += 1;
    else if (iBitsRatio > 10600)        //2^(0.5/6)*10000
      pSOverRc->iCalculatedQpSlice -= 1;
    else if (iBitsRatio > 11900)        //2^(1.5/6)*10000
      pSOverRc->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));
    else
      iAllocateBits = 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++;
  }
}

标签:QP,码率,宏块级,pSOverRc,宏块,源码,pWelsSvcRc,pEncCtx
From: https://blog.csdn.net/yanceyxin/article/details/139869838

相关文章

  • 【CSS in Depth2精译】1.1.4 源码顺序
    解决层叠冲突的最后一环叫做源码顺序,有时又称为出现顺序(orderofappearance)。如果其他判定规则均一致,则样式表中后出现的、或者在页面较晚引入的样式表声明,将最终胜出。也就是说,可以通过控制源码出现的顺序来给示例中的特色链接添加样式。如果两个存在冲突的选择器优先......
  • 阿基米德签证小程序(APP)管理系统源码安装步骤说明
      阿基米德所有系统支持Lunix/windows服务器环境,需要PHP7.1~8.3版本支持(推荐使用8.3),可运行于包括Apache和nginx在内的多种WEB服务器和模式(推荐使用nginx),支持Mysql5.0~8.0数据库(4G以上内存推荐使用8.0,不然就5.7),引擎用InnoDB。框架本身没有什么特别模块要求,具体的应用系统......
  • 在线客服系统源码/IM源码框架架构
    1.在线客服系统概述1.1系统定义与功能在线客服系统是一种基于网络的即时通讯工具,旨在提供实时的客户服务和支持。这种系统允许客户通过文字、图片或文件与客服人员进行交流,从而解决他们的疑问或问题。实时交流:系统支持实时消息传递功能,确保客户能够得到快速响应。多渠道接......
  • 智能自动化棋牌室小程序开发源码
    开发一个智能自动化棋牌室小程序并获取其源码是一个涉及多个技术领域的复杂任务。下面是一个大致的开发流程和注意事项:1.技术选型前端技术:使用微信小程序开发框架,如微信原生开发框架、Taro、Uni-app等。后端技术:选择合适的后端技术栈,如Node.js、Java、Python等,以及数据库......
  • 10个超好看的 404 页面(附源码)
    今天来分享10个超好看的404页面,带动画效果。代码:https://codepen.io/AsyrafHussin/pen/KxWRrK代码:https://codepen.io/salehriaz/pen/erJrZM代码:https://codepen.io/andrew-lawendy/pen/deOpMZ代码:https://codepen.io/Mahi-K/pen/rNzBGgq代码:https://codepen.......
  • 帮企商城10合一万能DIY分销商城小程序源码系统 带源代码包+搭建部署教程
    系统概述这是一款集多种功能于一体的源码系统,旨在为用户提供一站式的商城解决方案。它不仅支持小程序端,还能与其他平台无缝对接,满足不同用户的需求。代码示例系统特色功能一览   1.万能DIY功能:用户可以根据自己的需求和创意,自由定制商城的外观、布局和功能模块,打造......
  • 超级会员卡积分收银系统源码 带完整的安装代码包以及搭建部署教程
    系统概述超级会员卡积分收银系统源码是一款专为商业运营打造的综合性软件解决方案。它集成了会员卡管理、积分管理、收银管理等多种功能,旨在为企业提供高效、便捷、准确的运营管理工具。该系统源码采用先进的技术架构,具有良好的稳定性和扩展性,能够适应不同规模和类型的企业需......
  • 百度在线分销商城小程序源码系统 分销+会员组+新用户福利 前后端分离 带完整的安装代
    系统概述百度在线分销商城小程序源码系统是一款集分销、会员组管理和新用户福利于一体的前后端分离的系统。它采用先进的技术架构,确保系统的稳定性、高效性和安全性。该系统的前端基于小程序开发,为用户提供了便捷的购物体验和交互界面。用户可以通过小程序轻松浏览商品、下单......
  • 基于C#的WPF+halcon开发,视觉和运动控制软件框架源码
    基于C#的WPF+halcon开发,视觉和运动控制软件框架源码带ui设计器和轴卡运控,上手可用,WPFMVVM开发模式,1:1参考easyvision开发,集成几十个软件算子,插件框架可以自定义变量,写c#脚本,自定义流程,包含了halcon脚本和封装的算子,可自定义ui,通过插件形式开发很方便拓展自己的功能。可学......
  • 海贼王 动漫 网页设计 html源码 大作业
    ......