openh264 帧内预测编码过程源码分析

函数关系

在这里插入图片描述

  1. 说明:
    可以看到完成帧内预测编码的核心函数就是 WelsMdI16x16WelsMdI4x4WelsMdI4x4Fast WelsMdIntraChroma 四个函数。

原理

WelsMdI16x16函数

  1. 功能:针对16x16像素块的帧内模式决策
  2. 过程
  • 局部变量申明;
  • 根据宏块的领域宏块情况计算得出iOffset;
  • iAvailCount 和 kpAvailMode 用于获取当前宏块可用的帧内预测模式数量和预测模式列表;
  • 如果iAvailCount大于 3,且提供 pfIntra16x16Combined3函数;
    • 则调用pfIntra16x16Combined3函数来获取最佳模式iBestMode和成本iBestCost;
    • 从kpAvailMode[3]中确定当前模式iCurMode,表明考虑 第四种模式;
    • 调用pfGetLumaI16x16Pred函数,根据当前模式编号 iCurMode 生成预测块,并将结果存储在 pDst 中;
    • pfMdCost[BLOCK_16x16] 函数计算当前预测块 pDst 和编码图像 pEnc 之间的成本iCurCost;
    • iCurCost小于iBestCost,
      • 将iCurMode和iCurCost确定最佳模式iBestMode和成本iBestCost;
    • 否则,
      • 则调用pfGetLumaI16x16Pred函数使用最佳模式iBestMode重新生成预测块,并存储在 pDst 中;
    • iIdx 被设置为1,最佳成本 iBestCost 被加上量化参数 iLambda,作为总开销;
  • 否则
    • iBestMode 被初始化为第一个可用模式,即 kpAvailMode[0];
    • for 循环遍历所有可用的模式iAvailCount;
      • 在每次循环迭代中,iCurMode 被设置为当前考虑的模式编号iCurMode;
      • 调用 pfGetLumaI16x16Pred[iCurMode] 函数,根据当前模式编号 iCurMode 生成预测块;
      • 使用 pfMdCost[BLOCK_16x16] 函数计算当前预测块 pDst 和编码图像 pEnc 之间的成本iCurCost;
      • iCurCost 加上量化参数 iLambda 与当前模式编号的编码长度(使用 BsSizeUE 函数和 g_kiMapModeI16x16 数组计算)的乘积;
      • 如果 iCurCost小于 iBestCost;
        • 更新iBestMode、iBestCost、iIdx、pDst;iIdx 通过异或操作 ^ 0x01 来切换,这在每次找到更好的模式时都会发生;
        • iIdx用来指向预测块pPredI16x16;
    • 更新缓存SMbCache中pMemPredChroma、pMemPredLuma、uiLumaI16x16Mode;
    • 返回 最佳代价iBestCost。
  1. 原理图
    在这里插入图片描述
  2. 说明
  • pfGetLumaI16x16Pred函数指针根据不同的模式指向不同的函数,具体在WelsInitIntraPredFuncs函数中定义。
  • pfMdCost函数指针根据 fastmode 模式指向pfSampleSadpfSampleSatd函数指针,而且根据不同预测模式指向不同的函数实现,具体在WelsInitSampleSadFunc函数中定义。
  1. 源码:
int32_t WelsMdI16x16 (SWelsFuncPtrList* pFunc, SDqLayer* pCurDqLayer, SMbCache* pMbCache, int32_t iLambda) {
  const int8_t*  kpAvailMode;
  int32_t iAvailCount;
  int32_t iIdx = 0;
  uint8_t* pPredI16x16[2] = {pMbCache->pMemPredMb, pMbCache->pMemPredMb + 256};
  uint8_t* pDst       = pPredI16x16[0];
  uint8_t* pDec       = pMbCache->SPicData.pCsMb[0];
  uint8_t* pEnc       = pMbCache->SPicData.pEncMb[0];
  int32_t iLineSizeDec = pCurDqLayer->iCsStride[0];
  int32_t iLineSizeEnc = pCurDqLayer->iEncStride[0];
  int32_t i, iCurCost, iCurMode, iBestMode, iBestCost = INT_MAX;

  int32_t iOffset = pMbCache->uiNeighborIntra & 0x07;
  iAvailCount = g_kiIntra16AvaliMode[iOffset][4];
  kpAvailMode = g_kiIntra16AvaliMode[iOffset];
  if (iAvailCount > 3 && pFunc->sSampleDealingFuncs.pfIntra16x16Combined3) {
    iBestCost = pFunc->sSampleDealingFuncs.pfIntra16x16Combined3 (pDec, iLineSizeDec, pEnc, iLineSizeEnc, &iBestMode,
                iLambda, pDst/*temp*/);
    iCurMode = kpAvailMode[3];
    pFunc->pfGetLumaI16x16Pred[iCurMode] (pDst, pDec, iLineSizeDec);
    iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_16x16] (pDst, 16, pEnc, iLineSizeEnc) + iLambda * 4 ;
    if (iCurCost < iBestCost) {
      iBestMode = iCurMode;
      iBestCost = iCurCost;
    } else {
      pFunc->pfGetLumaI16x16Pred[iBestMode] (pDst, pDec, iLineSizeDec);
    }
    iIdx = 1;
    iBestCost += iLambda;
  } else {
    iBestMode = kpAvailMode[0];
    for (i = 0; i < iAvailCount; ++ i) {
      iCurMode = kpAvailMode[i];

      assert (iCurMode >= 0 && iCurMode < 7);

      pFunc->pfGetLumaI16x16Pred[iCurMode] (pDst, pDec, iLineSizeDec);
      iCurCost = pFunc->sSampleDealingFuncs.pfMdCost[BLOCK_16x16] (pDst, 16, pEnc, iLineSizeEnc);
      iCurCost += iLambda * (BsSizeUE (g_kiMapModeI16x16[iCurMode]));
      if (iCurCost < iBestCost) {
        iBestMode = iCurMode;
        iBestCost = iCurCost;
        iIdx = iIdx ^ 0x01;
        pDst = pPredI16x16[iIdx];
      }
    }
  }
  pMbCache->pMemPredChroma = pPredI16x16[iIdx];

  pMbCache->pMemPredLuma = pPredI16x16[iIdx ^ 0x01];
  pMbCache->uiLumaI16x16Mode  = iBestMode;
  return iBestCost;
}

WelsMdI4x4函数

  1. 功能:针对4x4像素块的帧内模式决策
  2. 过程:类似 I16x16,只不过预测模式更多,有 16 种模式;
  3. 源码:略

WelsMdI4x4Fast函数

  1. 功能:针对4x4像素块的帧内模式决策的快速实现逻辑
  2. 过程:类似 I16x16,只不过预测模式更多,有 16 中模式,但采用了快速算法;
  3. 源码:略

WelsMdIntraChroma函数

  1. 功能:针对色度像素块的帧内模式决策
  2. 过程:类似 I16x16决策过程,色度的预测模式跟 I16x16 块一样,有 7 种模式;
  3. 源码:略
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码流怪侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值