HEVC学习(三十三) —— 去方块滤波之四

本文考察Boundary Strength (BS)的获取过程:

Void TComLoopFilter::xGetBoundaryStrengthSingle ( TComDataCU* pcCU, UInt uiAbsZorderIdx, Int iDir, UInt uiAbsPartIdx )
{
  TComSlice* const pcSlice = pcCU->getSlice();
  
  const UInt uiPartQ = uiAbsPartIdx; //!< 当前CU的地址
  TComDataCU* const pcCUQ = pcCU; //!< 当前CU的指针
  
  UInt uiPartP;
  TComDataCU* pcCUP;
  UInt uiBs = 0;
  
  //-- Calculate Block Index
  if (iDir == EDGE_VER) //!< 垂直边界滤波,获取左邻CU
  {
    pcCUP = pcCUQ->getPULeft(uiPartP, uiPartQ, !pcCU->getSlice()->getLFCrossSliceBoundaryFlag(), false, !m_bLFCrossTileBoundary);
  }
  else  // (iDir == EDGE_HOR) //!< 水平边界滤波,获取上邻CU
  {
#if LINEBUF_CLEANUP
    pcCUP = pcCUQ->getPUAbove(uiPartP, uiPartQ, !pcCU->getSlice()->getLFCrossSliceBoundaryFlag(), false, false, !m_bLFCrossTileBoundary);
#else
    pcCUP = pcCUQ->getPUAbove(uiPartP, uiPartQ, !pcCU->getSlice()->getLFCrossSliceBoundaryFlag(), false, false, false, !m_bLFCrossTileBoundary);
#endif
  }
  
  //-- Set BS for Intra MB : BS = 4 or 3
  if ( pcCUP->isIntra(uiPartP) || pcCUQ->isIntra(uiPartQ) ) //!< 至少有一个CU是帧内预测模式
  {
    uiBs = 2;
  }
  //! 讨论CU不是帧内预测模式的情况
  //-- Set BS for not Intra MB : BS = 2 or 1 or 0
  if ( !pcCUP->isIntra(uiPartP) && !pcCUQ->isIntra(uiPartQ) )
  {
    UInt nsPartQ = uiPartQ;
    UInt nsPartP = uiPartP;
    //!< 至少有一个邻块具有非零残差系数且该边界为TU边界
    if ( m_aapucBS[iDir][uiAbsPartIdx] && (pcCUQ->getCbf( nsPartQ, TEXT_LUMA, pcCUQ->getTransformIdx(nsPartQ)) != 0 || pcCUP->getCbf( nsPartP, TEXT_LUMA, pcCUP->getTransformIdx(nsPartP) ) != 0) )
    {
      uiBs = 1;
    }
    else
    {
      if (iDir == EDGE_HOR)
      {
#if LINEBUF_CLEANUP
        pcCUP = pcCUQ->getPUAbove(uiPartP, uiPartQ, !pcCU->getSlice()->getLFCrossSliceBoundaryFlag(), false, false, !m_bLFCrossTileBoundary);
#else
        pcCUP = pcCUQ->getPUAbove(uiPartP, uiPartQ, !pcCU->getSlice()->getLFCrossSliceBoundaryFlag(), false, true, false, !m_bLFCrossTileBoundary);
#endif
      }//! 接下来的是P slice 和 B slice的情况,咋一看,代码显得比较啰嗦,特别是B slice的情况。但是,不要被这个表象给迷惑了,其实这部分代码对应于    draft 8.7.2.3中关于变量bS[xDi][yDj]的推导过程的描述。先把那部分的内容看了,再回过头来看下面代码,会觉得一点都不复杂,甚至是理所当然的。
      if (pcSlice->isInterB()) //!< 当前片为B slice
      {//! 根据P块和Q块所参考的参考图像是否相同(此时要讨论list0和list1的情况)、它们的运动矢量(水平、垂直两个分量)差值的绝对值是否超过4(即以1/4像素为单位)来设定BS
		  Int iRefIdx;
		  Int *piRefP0, *piRefP1, *piRefQ0, *piRefQ1;
		  iRefIdx = pcCUP->getCUMvField(REF_PIC_LIST_0)->getRefIdx(uiPartP);
		  piRefP0 = (iRefIdx < 0) ? NULL :  (Int*) pcCUP->getSlice()->getRefPic(REF_PIC_LIST_0, iRefIdx);
		  iRefIdx = pcCUP->getCUMvField(REF_PIC_LIST_1)->getRefIdx(uiPartP);
		  piRefP1 = (iRefIdx < 0) ? NULL :  (Int*) pcCUP->getSlice()->getRefPic(REF_PIC_LIST_1, iRefIdx);
		  iRefIdx = pcCUQ->getCUMvField(REF_PIC_LIST_0)->getRefIdx(uiPartQ);
		  piRefQ0 = (iRefIdx < 0) ? NULL :  (Int*) pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx);
		  iRefIdx = pcCUQ->getCUMvField(REF_PIC_LIST_1)->getRefIdx(uiPartQ);
		  piRefQ1 = (iRefIdx < 0) ? NULL :  (Int*) pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx);


		  TComMv pcMvP0 = pcCUP->getCUMvField(REF_PIC_LIST_0)->getMv(uiPartP);
		  TComMv pcMvP1 = pcCUP->getCUMvField(REF_PIC_LIST_1)->getMv(uiPartP);
		  TComMv pcMvQ0 = pcCUQ->getCUMvField(REF_PIC_LIST_0)->getMv(uiPartQ);
		  TComMv pcMvQ1 = pcCUQ->getCUMvField(REF_PIC_LIST_1)->getMv(uiPartQ);

		  if ( ((piRefP0==piRefQ0)&&(piRefP1==piRefQ1)) || ((piRefP0==piRefQ1)&&(piRefP1==piRefQ0)) )
		  {
			  uiBs = 0;
			  if ( piRefP0 != piRefP1 )   // Different L0 & L1
			  {
				  if ( piRefP0 == piRefQ0 )
				  {
					  pcMvP0 -= pcMvQ0;   pcMvP1 -= pcMvQ1;
					  uiBs = (pcMvP0.getAbsHor() >= 4) | (pcMvP0.getAbsVer() >= 4) |
						  (pcMvP1.getAbsHor() >= 4) | (pcMvP1.getAbsVer() >= 4);
				  }
				  else
				  {
					  pcMvP0 -= pcMvQ1;   pcMvP1 -= pcMvQ0;
					  uiBs = (pcMvP0.getAbsHor() >= 4) | (pcMvP0.getAbsVer() >= 4) |
						  (pcMvP1.getAbsHor() >= 4) | (pcMvP1.getAbsVer() >= 4);
				  }
			  }
			  else    // Same L0 & L1
			  {
				  TComMv pcMvSub0 = pcMvP0 - pcMvQ0;
				  TComMv pcMvSub1 = pcMvP1 - pcMvQ1;
				  pcMvP0 -= pcMvQ1;   pcMvP1 -= pcMvQ0;
				  uiBs = ( (pcMvP0.getAbsHor() >= 4) | (pcMvP0.getAbsVer() >= 4) |
					  (pcMvP1.getAbsHor() >= 4) | (pcMvP1.getAbsVer() >= 4) ) &&
					  ( (pcMvSub0.getAbsHor() >= 4) | (pcMvSub0.getAbsVer() >= 4) |
					  (pcMvSub1.getAbsHor() >= 4) | (pcMvSub1.getAbsVer() >= 4) );
			  }
		  }
		  else // for all different Ref_Idx
		  {
			  uiBs = 1;
		  }

      }
      else  // pcSlice->isInterP() //!< 当前片为P slice
      {//! 根据P块和Q块所参考的参考图像是否相同、它们的运动矢量(水平、垂直两个分量)差值的绝对值是否超过4(即以1/4像素为单位)来设定BS
		  Int iRefIdx;
		  Int *piRefP0, *piRefQ0;
		  iRefIdx = pcCUP->getCUMvField(REF_PIC_LIST_0)->getRefIdx(uiPartP);
		  piRefP0 = (iRefIdx < 0) ? NULL :  (Int*) pcCUP->getSlice()->getRefPic(REF_PIC_LIST_0, iRefIdx);
		  iRefIdx = pcCUQ->getCUMvField(REF_PIC_LIST_0)->getRefIdx(uiPartQ);
		  piRefQ0 = (iRefIdx < 0) ? NULL :  (Int*) pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx);
		  TComMv pcMvP0 = pcCUP->getCUMvField(REF_PIC_LIST_0)->getMv(uiPartP);
		  TComMv pcMvQ0 = pcCUQ->getCUMvField(REF_PIC_LIST_0)->getMv(uiPartQ);

		  pcMvP0 -= pcMvQ0;
		  uiBs = (piRefP0 != piRefQ0) | (pcMvP0.getAbsHor() >= 4) | (pcMvP0.getAbsVer() >= 4);

      }
    }   // enf of "if( one of BCBP == 0 )"
  }   // enf of "if( not Intra )"
  
  m_aapucBS[iDir][uiAbsPartIdx] = uiBs;
}


 

发布了97 篇原创文章 · 获赞 855 · 访问量 106万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章