HEVC 帧内预测xPredIntraAng

来源:互联网 发布:ipad老是无法加入网络 编辑:程序博客网 时间:2024/05/21 10:07
帧内预测
xPredIntraAng:传入34种帧内预测模式的模式索引,得到预测图像
pSrc:重建序列的指针
pTrueDst:预测样本的指针
pDst:临时存储预测值指针

(1)if (modeDC),所有像素赋值dcval = predIntraGetPredValDC(pSrc, srcStride, width, height)
(2)else:
(a)if(角度偏移为负):*填写refAbove后半部分的值,用pSrc[x-srcStride-1]
*填写refLeft后半部分的值,用pSrc[(y-1)*srcStride-1]
*偏移refMain、refSide
*根据计算出来的截距将side reference对应的样点值投影给refMainrefMain[k] = refSide[invAngleSum>>8]
(对于模式18~25,须将左侧参考像素按给定方向投影至上方参考像素的左侧,对于模式11~17,须将上方参考像素按给定方向投影至左侧参考像素的上方)

(b)else:refAbove[x] = pSrc[x-srcStride-1]
refLeft[y] = pSrc[(y-1)*srcStride-1]
角度为正时,对于垂直方向的角度预测来说,只参考上方邻点的样点值;对于水平方向的角度预测来说,只参考左方邻点的样点值
(c)如果是horizontal mode,width/height互换
(d)if纯水平或竖直方向,pDst[y*dstStride+x] = refMain[x+1]
(e)else:有加权因子pDsty[x+0] = (Pel) ( ((32-deltaFract)*lastRefMainPel + deltaFract*thisRefMainPel +16) >> 5 )
没有加权因子pDsty[x] = refMain[x+deltaInt+1](deltaInt当前像素对应参考像素在Ref中的位置)
(f)水平模式翻转pTrueDst[x*dstStrideTrue] = pDst[x]
Void TComPrediction::xPredIntraAng(       Int bitDepth,                                    const Pel* pSrc,     Int srcStride,                                          Pel* pTrueDst, Int dstStrideTrue,                                          UInt uiWidth, UInt uiHeight, ChannelType channelType,                                          UInt dirMode, const Bool bEnableEdgeFilters                                  ){  Int width=Int(uiWidth);  Int height=Int(uiHeight);  // Map the mode index to main prediction direction and angle  assert( dirMode != PLANAR_IDX ); //no planar  const Bool modeDC        = dirMode==DC_IDX;  // Do the DC prediction  if (modeDC)  {    const Pel dcval = predIntraGetPredValDC(pSrc, srcStride, width, height);//计算dcval值    for (Int y=height;y>0;y--, pTrueDst+=dstStrideTrue)    {      for (Int x=0; x<width;) // width is always a multiple of 4.      {        pTrueDst[x++] = dcval;//DC模式全用dcval这个值      }    }  }  else // Do angular predictions  {    const Bool       bIsModeVer         = (dirMode >= 18);//判断是否为垂直模式    const Int        intraPredAngleMode = (bIsModeVer) ? (Int)dirMode - VER_IDX :  -((Int)dirMode - HOR_IDX);//与水平(垂直)模式的偏移量    const Int        absAngMode         = abs(intraPredAngleMode);    const Int        signAng            = intraPredAngleMode < 0 ? -1 : 1;    const Bool       edgeFilter         = bEnableEdgeFilters && isLuma(channelType) && (width <= MAXIMUM_INTRA_FILTERED_WIDTH) && (height <= MAXIMUM_INTRA_FILTERED_HEIGHT);    // Set bitshifts and scale the angle parameter to block size    static const Int angTable[9]    = {0,    2,    5,   9,  13,  17,  21,  26,  32};    static const Int invAngTable[9] = {0, 4096, 1638, 910, 630, 482, 390, 315, 256}; // (256 * 32) / Angle    Int invAngle                    = invAngTable[absAngMode];    Int absAng                      = angTable[absAngMode];    Int intraPredAngle              = signAng * absAng;    Pel* refMain;    Pel* refSide;    Pel  refAbove[2*MAX_CU_SIZE+1];    Pel  refLeft[2*MAX_CU_SIZE+1];    // Initialize the Main and Left reference array.    if (intraPredAngle < 0)    {      const Int refMainOffsetPreScale = (bIsModeVer ? height : width ) - 1;      const Int refMainOffset         = height - 1;      for (Int x=0;x<width+1;x++)      {        refAbove[x+refMainOffset] = pSrc[x-srcStride-1];//填写refAbove后半部分的值      }      for (Int y=0;y<height+1;y++)      {        refLeft[y+refMainOffset] = pSrc[(y-1)*srcStride-1];      }      refMain = (bIsModeVer ? refAbove : refLeft)  + refMainOffset;//添加偏移,将refAbove前半部分索引变为负值      refSide = (bIsModeVer ? refLeft  : refAbove) + refMainOffset;      // Extend the Main reference to the left.      Int invAngleSum    = 128;       // rounding for (shift by 8)      for (Int k=-1; k>(refMainOffsetPreScale+1)*intraPredAngle>>5; k--)      {        invAngleSum += invAngle;// 等价于k * invAngle,即求出在side reference上的截距        refMain[k] = refSide[invAngleSum>>8];//根据计算出来的截距将side reference对应的样点值投影给main reference      }    }    else    {      for (Int x=0;x<2*width+1;x++)      {        refAbove[x] = pSrc[x-srcStride-1];      }      for (Int y=0;y<2*height+1;y++)      {        refLeft[y] = pSrc[(y-1)*srcStride-1];      }  //角度为正时,对于垂直方向的角度预测来说,只参考上方邻点的样点值;对于水平方向的角度预测来说,只参考左方邻点的样点值       refMain = bIsModeVer ? refAbove : refLeft ;      refSide = bIsModeVer ? refLeft  : refAbove;    }    // swap width/height if we are doing a horizontal mode:    Pel tempArray[MAX_CU_SIZE*MAX_CU_SIZE];    const Int dstStride = bIsModeVer ? dstStrideTrue : MAX_CU_SIZE;    Pel *pDst = bIsModeVer ? pTrueDst : tempArray;//ModeVer直接将预测样本存入pTrueDst,ModeHor先将预测样本存入tempArray,最后转置    if (!bIsModeVer)    {      std::swap(width, height);//为了代码简便,下面将ModeHor和ModeVer的操作代码合并,所以交换width/height    }    if (intraPredAngle == 0)  // pure vertical or pure horizontal    {      for (Int y=0;y<height;y++)      {        for (Int x=0;x<width;x++)        {          pDst[y*dstStride+x] = refMain[x+1];        }      }      if (edgeFilter)      {        for (Int y=0;y<height;y++)        {          pDst[y*dstStride] = Clip3 (0, ((1 << bitDepth) - 1), pDst[y*dstStride] + (( refSide[y+1] - refSide[0] ) >> 1) );        }      }    }    else    {      Pel *pDsty=pDst;      for (Int y=0, deltaPos=intraPredAngle; y<height; y++, deltaPos+=intraPredAngle, pDsty+=dstStride)      {        const Int deltaInt   = deltaPos >> 5;//计算当前像素对应参考像素在Ref中的位置        const Int deltaFract = deltaPos & (32 - 1);//计算加权因子        if (deltaFract)        {          // Do linear filtering          const Pel *pRM=refMain+deltaInt+1;          Int lastRefMainPel=*pRM++;          for (Int x=0;x<width;pRM++,x++)          {            Int thisRefMainPel=*pRM;            pDsty[x+0] = (Pel) ( ((32-deltaFract)*lastRefMainPel + deltaFract*thisRefMainPel +16) >> 5 );//计算当前像素的预测值            lastRefMainPel=thisRefMainPel;          }        }        else        {          // Just copy the integer samples          for (Int x=0;x<width; x++)          {            pDsty[x] = refMain[x+deltaInt+1];          }        }      }    }    // Flip the block if this is the horizontal mode ,ModeHor就将pDst转置    if (!bIsModeVer)    {      for (Int y=0; y<height; y++)      {        for (Int x=0; x<width; x++)        {          pTrueDst[x*dstStrideTrue] = pDst[x];        }        pTrueDst++;        pDst+=dstStride;      }    }  }}



原创粉丝点击