HEVC代码分析-predIntraAng

predIntraAng

获取当前tu的预测像素值

Void TComPrediction::predIntraAng( const ComponentID compID, UInt uiDirMode, Pel* piOrg /* Will be null for decoding */, UInt uiOrgStride, Pel* piPred, UInt uiStride, TComTU &rTu, const Bool bUseFilteredPredSamples, const Bool bUseLosslessDPCM )
{
  // compID分量ID,uiDirMode预测角度,piOrg原始块指针(该函数被解码器调用的时候这个参数值为null),piPred预测块指针,rTu当前tu,bUseFilteredPredSamples是否使用滤波后的参考像素,bUseLosslessDPCM是否使用无损的DPCM编码方式
  const ChannelType    channelType = toChannelType(compID); // 当前分量是亮度还是色度
  const TComRectangle &rect        = rTu.getRect(isLuma(compID) ? COMPONENT_Y : COMPONENT_Cb); // 当前tu的形状信息
  const Int            iWidth      = rect.width; // 当前tu宽
  const Int            iHeight     = rect.height; // 当前tu高

  assert( g_aucConvertToBit[ iWidth ] >= 0 ); //   4x  4
  assert( g_aucConvertToBit[ iWidth ] <= 5 ); // 128x128
  //assert( iWidth == iHeight  );

        Pel *pDst = piPred;

  // get starting pixel in block
  const Int sw = (2 * iWidth + 1); // 相当于参考像素的stride

  if ( bUseLosslessDPCM )
  {
	// 无损编码,只有水平或竖直模式有可能采用
    const Pel *ptrSrc = getPredictorPtr( compID, false ); // 使用未滤波的参考像素
    // Sample Adaptive intra-Prediction (SAP)
    if (uiDirMode==HOR_IDX)
    {
	  // 如果是水平模式,预测块最左边一列由相邻的参考像素copy而来,其余列填充对应位置的原始像素值
      // left column filled with reference samples
      // remaining columns filled with piOrg data (if available).
      for(Int y=0; y<iHeight; y++)
      {
        piPred[y*uiStride+0] = ptrSrc[(y+1)*sw]; // 最左边一列
      }
      if (piOrg!=0)
      {
		// 原始图像可得,则其余列填充原始像素值
        piPred+=1; // miss off first column
        for(Int y=0; y<iHeight; y++, piPred+=uiStride, piOrg+=uiOrgStride)
        {
          memcpy(piPred, piOrg, (iWidth-1)*sizeof(Pel));
        }
      }
    }
    else // VER_IDX
    {
	  // // 如果是竖直模式,预测块最上边一行由相邻的参考像素copy而来,其余行填充对应位置的原始像素值
      // top row filled with reference samples
      // remaining rows filled with piOrd data (if available)
      for(Int x=0; x<iWidth; x++)
      {
        piPred[x] = ptrSrc[x+1];
      }
      if (piOrg!=0)
      {
        piPred+=uiStride; // miss off the first row
        for(Int y=1; y<iHeight; y++, piPred+=uiStride, piOrg+=uiOrgStride)
        {
          memcpy(piPred, piOrg, iWidth*sizeof(Pel));
        }
      }
    }
  }
  else
  {
	// 正常的有损编码
    const Pel *ptrSrc = getPredictorPtr( compID, bUseFilteredPredSamples ); // 参考像素指针

    if ( uiDirMode == PLANAR_IDX )
    {
	  // planar模式
      xPredIntraPlanar( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight );
    }
    else
    {
	  // 非planar模式
      // Create the prediction
            TComDataCU *const pcCU              = rTu.getCU(); // 当前tu对应的CU
      const UInt              uiAbsPartIdx      = rTu.GetAbsPartIdxTU(); // 当前tu的绝对坐标
      const Bool              enableEdgeFilters = !(pcCU->isRDPCMEnabled(uiAbsPartIdx) && pcCU->getCUTransquantBypass(uiAbsPartIdx)); //是否需要边缘滤波,水平或垂直模式的才有可能用得到
#if O0043_BEST_EFFORT_DECODING
      const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getStreamBitDepth(channelType);
#else
      const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getBitDepth(channelType); // 当前channel的位宽
#endif
	  // 非planar模式的预测函数
      xPredIntraAng( channelsBitDepthForPrediction, ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType, uiDirMode, enableEdgeFilters );

      if( uiDirMode == DC_IDX )
      {
		// 如果是DC模式,还需要判断是否需要进一步的滤波操作
        xDCPredFiltering( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType );
      }
    }
  }

}

相关调用分析

xPredIntraPlanar
xPredIntraAng
predIntraGetPredValDC和xDCPredFiltering

发布了25 篇原创文章 · 获赞 46 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/huster1446/article/details/103594425