[置顶] HEVC学习(三十六) —— 去方块滤波之七

本文介绍关于去方块滤波的最后一个函数(这一系列基本上只讨论了亮度分量的情况,色度分量的情况类似,不单独做出分析)。

Void TComLoopFilter::xEdgeFilterLuma( TComDataCU* pcCU, UInt uiAbsZorderIdx, UInt uiDepth, Int iDir, Int iEdge  )
{
  TComPicYuv* pcPicYuvRec = pcCU->getPic()->getPicYuvRec(); //!< 重建图像(滤波前)
  Pel* piSrc    = pcPicYuvRec->getLumaAddr( pcCU->getAddr(), uiAbsZorderIdx ); //!< 指向当前PU对应的重建像素的首地址
  Pel* piTmpSrc = piSrc;
  
  Int  iStride = pcPicYuvRec->getStride(); //!< 图像的跨度
  Int iQP = 0;
  Int iQP_P = 0;
  Int iQP_Q = 0;
  UInt uiNumParts = pcCU->getPic()->getNumPartInWidth()>>uiDepth; //!< 当前PU的以partition为单位的宽度
  
  UInt  uiPelsInPart = g_uiMaxCUWidth >> g_uiMaxCUDepth;
  UInt  uiBsAbsIdx = 0, uiBs = 0;
  Int   iOffset, iSrcStep;
  
  Bool  bPCMFilter = (pcCU->getSlice()->getSPS()->getUsePCM() && pcCU->getSlice()->getSPS()->getPCMFilterDisableFlag())? true : false;
  Bool  bPartPNoFilter = false;
  Bool  bPartQNoFilter = false; 
  UInt  uiPartPIdx = 0;
  UInt  uiPartQIdx = 0;
  TComDataCU* pcCUP = pcCU; 
  TComDataCU* pcCUQ = pcCU;
  Int  betaOffsetDiv2 = pcCUQ->getSlice()->getDeblockingFilterBetaOffsetDiv2();
  Int  tcOffsetDiv2 = pcCUQ->getSlice()->getDeblockingFilterTcOffsetDiv2();
  //! iEdge为边界上的PU以partition为单元的序号
  if (iDir == EDGE_VER)
  {
    iOffset = 1;
    iSrcStep = iStride;
    piTmpSrc += iEdge*uiPelsInPart; //!< 每个8x8滤波单元是不重叠的
  }
  else  // (iDir == EDGE_HOR)
  {
    iOffset = iStride;
    iSrcStep = 1;
    piTmpSrc += iEdge*uiPelsInPart*iStride;
  }
  
  for ( UInt iIdx = 0; iIdx < uiNumParts; iIdx++ ) //!< 遍历PU中的每个partition
  {
    uiBsAbsIdx = xCalcBsIdx( pcCU, uiAbsZorderIdx, iDir, iEdge, iIdx); //!< partition对应的ZScan地址
    uiBs = m_aapucBS[iDir][uiBsAbsIdx];
    if ( uiBs ) //!< uiBs == 1 or uiBs == 2
    {
      iQP_Q = pcCU->getQP( uiBsAbsIdx );
      uiPartQIdx = uiBsAbsIdx;
      // Derive neighboring PU index
      if (iDir == EDGE_VER)
      {
        pcCUP = pcCUQ->getPULeft (uiPartPIdx, uiPartQIdx,!pcCU->getSlice()->getLFCrossSliceBoundaryFlag(), false, !m_bLFCrossTileBoundary);
      }
      else  // (iDir == EDGE_HOR)
      {
#if LINEBUF_CLEANUP
        pcCUP = pcCUQ->getPUAbove(uiPartPIdx, uiPartQIdx,!pcCU->getSlice()->getLFCrossSliceBoundaryFlag(), false, false, !m_bLFCrossTileBoundary);
#else
        pcCUP = pcCUQ->getPUAbove(uiPartPIdx, uiPartQIdx,!pcCU->getSlice()->getLFCrossSliceBoundaryFlag(), false, false, false, !m_bLFCrossTileBoundary);
#endif
      }

      iQP_P = pcCUP->getQP(uiPartPIdx);
      iQP = (iQP_P + iQP_Q + 1) >> 1;	//!< draft (8-264)
      Int iBitdepthScale = 1 << (g_bitDepthY-8);
      
      Int iIndexTC = Clip3(0, MAX_QP+DEFAULT_INTRA_TC_OFFSET, Int(iQP + DEFAULT_INTRA_TC_OFFSET*(uiBs-1) + (tcOffsetDiv2 << 1))); //!< draft (8-267)
      Int iIndexB = Clip3(0, MAX_QP, iQP + (betaOffsetDiv2 << 1)); //!< draft (8-265)
      
      Int iTc =  tctable_8x8[iIndexTC]*iBitdepthScale; //!< draft (8-268)
      Int iBeta = betatable_8x8[iIndexB]*iBitdepthScale; //!< draft (8-266)
      Int iSideThreshold = (iBeta+(iBeta>>1))>>3; //!< 阈值
      Int iThrCut = iTc*10;

      UInt  uiBlocksInPart = uiPelsInPart / 4 ? uiPelsInPart / 4 : 1; //!< 4 / 1 = 1
      for (UInt iBlkIdx = 0; iBlkIdx<uiBlocksInPart; iBlkIdx ++)
      {
        Int dp0 = xCalcDP( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*4+0), iOffset); //!< draft漏标号了
        Int dq0 = xCalcDQ( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*4+0), iOffset); //!< draft (8-269)
        Int dp3 = xCalcDP( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*4+3), iOffset); //!< draft (8-270)
        Int dq3 = xCalcDQ( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*4+3), iOffset); //!< draft (8-271)
        Int d0 = dp0 + dq0; //!< draft (8-272)
        Int d3 = dp3 + dq3; //!< draft (8-273)
        
        Int dp = dp0 + dp3; //!< draft (8-274)
        Int dq = dq0 + dq3; //!< draft (8-275)
        Int d =  d0 + d3; //!< draft (8-276)
        
        if (bPCMFilter || pcCU->getSlice()->getPPS()->getTransquantBypassEnableFlag())
        {
          // Check if each of PUs is I_PCM with LF disabling
          bPartPNoFilter = (bPCMFilter && pcCUP->getIPCMFlag(uiPartPIdx));
          bPartQNoFilter = (bPCMFilter && pcCUQ->getIPCMFlag(uiPartQIdx));

          // check if each of PUs is lossless coded
          bPartPNoFilter = bPartPNoFilter || (pcCUP->isLosslessCoded(uiPartPIdx) );
          bPartQNoFilter = bPartQNoFilter || (pcCUQ->isLosslessCoded(uiPartQIdx) );
        }

        if (d < iBeta)
        { 
          Bool bFilterP = (dp < iSideThreshold); //!< dEp
          Bool bFilterQ = (dq < iSideThreshold); //!< dEq
          //! xUseStrongFiltering对应于draft 8.7.2.4.6
          Bool sw =  xUseStrongFiltering( iOffset, 2*d0, iBeta, iTc, piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*4+0))
          && xUseStrongFiltering( iOffset, 2*d3, iBeta, iTc, piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*4+3)); //!< dE
          //! sw即strong weak,该函数用于判断最终滤波的强弱
          for ( Int i = 0; i < DEBLOCK_SMALLEST_BLOCK/2; i++)
          {//! 最终进行真正的滤波
            xPelFilterLuma( piTmpSrc+iSrcStep*(iIdx*uiPelsInPart+iBlkIdx*4+i), iOffset, d, iBeta, iTc, sw, bPartPNoFilter, bPartQNoFilter, iThrCut, bFilterP, bFilterQ);
          }
        }
      }
    }
  }
}


 

你可能感兴趣的:(hm,HEVC,deblock,去方块滤波)