其他分享
首页 > 其他分享> > HEVC代码阅读- -xPredIntraAng函数

HEVC代码阅读- -xPredIntraAng函数

作者:互联网

函数xPredIntraAng

功能:帧内 - -角度预测、DC预测

 

着重关注:

1.数组的相互赋值

2.数组的含义

3.指针的位置变化

*/

// Function for deriving the angular Intra predictions

/** Function for deriving the simplified angular intra predictions.
  // 重建数组参数
 * \param pSrc pointer to reconstructed sample array
 * \param srcStride the stride of the reconstructed sample array

 // 预测数组参数
 * \param rpDst reference to pointer for the prediction sample array
 * \param dstStride the stride of the prediction sample array

 * \param width the width of the block
 * \param height the height of the block
 * \param dirMode the intra prediction mode index
 * \param blkAboveAvailable boolean indication if the block above is available
 * \param blkLeftAvailable boolean indication if the block to the left is available
 *
 * This function derives the prediction samples for the angular mode based on the prediction direction indicated by
 * the prediction mode index. The prediction direction is given by the displacement of the bottom row of the block and
 * the reference row above the block in the case of vertical prediction or displacement of the rightmost column
 * of the block and reference column left from the block in the case of the horizontal prediction. The displacement
 * is signalled at 1/32 pixel accuracy. When projection of the predicted pixel falls inbetween reference samples,
 * the predicted value for the pixel is linearly interpolated from the reference samples. All reference samples are taken
 * from the extended main reference.
 */

Void TComPrediction::xPredIntraAng( Int* pSrc, Int srcStride, Pel*& rpDst, Int dstStride, UInt width, UInt height, UInt dirMode, Bool blkAboveAvailable, Bool blkLeftAvailable, Bool bFilter )
{
  Int k,l;
  Int blkSize        = width;
  Pel* pDst          = rpDst;

  // Map the mode index to main prediction direction and angle
  assert( dirMode > 0 ); //确保非Planar模式

  Bool modeDC        = dirMode < 2;
  Bool modeHor       = !modeDC && (dirMode < 18);
  Bool modeVer       = !modeDC && !modeHor;


  Int intraPredAngle = modeVer ? (Int)dirMode - VER_IDX : modeHor ? -((Int)dirMode - HOR_IDX) : 0;
  Int absAng         = abs(intraPredAngle);
  Int signAng        = intraPredAngle < 0 ? -1 : 1;

  // Set bitshifts and scale the angle parameter to block size
  // 预测模式号对应的“角度”==格数
  Int angTable[9]    = {0,    2,    5,   9,  13,  17,  21,  26,  32};
  // 设置反角度表 ,避免除法运算,后面参考数组的“扩展”会用到
  Int invAngTable[9] = {0, 4096, 1638, 910, 630, 482, 390, 315, 256}; // (256 * 32) / Angle

  Int invAngle       = invAngTable[absAng];
  absAng             = angTable[absAng];
  intraPredAngle     = signAng * absAng;

  // DC预测模式
  if (modeDC)
  {
    // 计算dcval
    Pel dcval = predIntraGetPredValDC(pSrc, srcStride, width, height, blkAboveAvailable, blkLeftAvailable);

    for (k=0;k<blkSize;k++)
    {
      for (l=0;l<blkSize;l++)
      {
        // 对预测数组中的每个元素赋值dcval
        pDst[k*dstStride+l] = dcval;
      }
    }
  }

  // 角度预测
  else
  {
    Pel* refMain;// 主
    Pel* refSide;// 辅
    Pel  refAbove[2*MAX_CU_SIZE+1];// 上 数组
    Pel  refLeft[2*MAX_CU_SIZE+1];// 左 数组

    // 参考数组的初始化
    if (intraPredAngle < 0)
    {
      for (k=0;k<blkSize+1;k++)
      {
        refAbove[k+blkSize-1] = pSrc[k-srcStride-1];
      }
      for (k=0;k<blkSize+1;k++)
      {
        refLeft[k+blkSize-1] = pSrc[(k-1)*srcStride-1];
      }

      // 视模式而定,选择 “主” 参考
      refMain = (modeVer ? refAbove : refLeft) + (blkSize-1);
      refSide = (modeVer ? refLeft : refAbove) + (blkSize-1);

      // 将refside数组“扩展”到refmain数组上
      Int invAngleSum    = 128;       // rounding for (shift by 8)
      for (k=-1; k>blkSize*intraPredAngle>>5; k--)
      {
        invAngleSum += invAngle;
        refMain[k] = refSide[invAngleSum>>8];
      }
    }
    //if (intraPredAngle < 0)
    else //intraPredAngle>=0
    {// 此过程与if过程类似
      for (k=0;k<2*blkSize+1;k++)
      {
        refAbove[k] = pSrc[k-srcStride-1];
      }
      for (k=0;k<2*blkSize+1;k++)
      {
        refLeft[k] = pSrc[(k-1)*srcStride-1];
      }
      refMain = modeVer ? refAbove : refLeft;
      refSide = modeVer ? refLeft  : refAbove;
    }


    //垂直或者水平?这里包括水平模式吗
    if (intraPredAngle == 0)
    {
      for (k=0;k<blkSize;k++)
      {
        for (l=0;l<blkSize;l++)
        {
          pDst[k*dstStride+l] = refMain[l+1];
        }
      }

      if ( bFilter )// 滤波- -默认开启
      {
        for (k=0;k<blkSize;k++)
        {
          pDst[k*dstStride] = Clip ( pDst[k*dstStride] + (( refSide[k+1] - refSide[0] ) >> 1) );
        }
      }
    }
    // if (intraPredAngle == 0)
    else//角度不为0,此时考虑投影的问题
    {
      Int deltaPos=0;
      Int deltaInt;
      Int deltaFract;
      Int refMainIndex;

      //计算出“格数”deltaInt和“权重”deltaFract
      for (k=0;k<blkSize;k++)
      {
        deltaPos += intraPredAngle;
        deltaInt   = deltaPos >> 5;
        deltaFract = deltaPos & (32 - 1);

        //如果“权重”不为0,说明未投影到像素点上,而是投影在两个像素点之间
        if (deltaFract)
        {
          // 加权插值计算
          for (l=0;l<blkSize;l++)
          {
            refMainIndex        = l+deltaInt+1;
            pDst[k*dstStride+l] = (Pel) ( ((32-deltaFract)*refMain[refMainIndex]+deltaFract*refMain[refMainIndex+1]+16) >> 5 );
          }
        }

        // if (deltaFract)
        else
        {
          // 直接进行整像素的复制
          for (l=0;l<blkSize;l++)
          {
            pDst[k*dstStride+l] = refMain[l+deltaInt+1];
          }
        }
      }
    }

    // 如果是水平模式,则进行一个翻转
    if (modeHor)
    {
      Pel  tmp;
      for (k=0;k<blkSize-1;k++)
      {
        for (l=k+1;l<blkSize;l++)
        {
          tmp                 = pDst[k*dstStride+l];
          pDst[k*dstStride+l] = pDst[l*dstStride+k];
          pDst[l*dstStride+k] = tmp;
        }
      }
    }
  }
}

 

标签:HEVC,reference,Int,intraPredAngle,代码,xPredIntraAng,prediction,param,block
来源: https://blog.csdn.net/magic_show_time/article/details/113616077