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