HM代码阅读:帧内预测(一)

来源:互联网 发布:yum erase remove区别 编辑:程序博客网 时间:2024/05/21 14:53

本文的代码均是TEncSearch::estIntraPredLumaQT函数或被它调用的函数中的代码。在TEncSearch::estIntraPredLumaQT函数中,首先确定RMD(Rough Mode Decision)候选。RMD的候选模式的个数由以下两个数组确定:

const UChar g_aucIntraModeNumFast_UseMPM[MAX_CU_DEPTH] ={  3,  //   2x2  8,  //   4x4  8,  //   8x8  3,  //  16x16  3,  //  32x32  3   //  64x64};const UChar g_aucIntraModeNumFast_NotUseMPM[MAX_CU_DEPTH] ={  3,  //   2x2  9,  //   4x4  9,  //   8x8  4,  //  16x16   33  4,  //  32x32   33  5   //  64x64   33};

从上面两个数组可以看出,RMD模式的个数与PU的大小有关。PU较小(4x4或8x8)时,RMD个数为8;PU较大(16x16或32x32或64x64)时,RMD个数为3。选择RMD时,uiMode按代价uiCost在CandCostList中从小到大排列在CandModeList中。

UInt TEncSearch::xUpdateCandList( UInt uiMode, Double uiCost, UInt uiFastCandNum, UInt * CandModeList, Double * CandCostList ){  UInt i;  UInt shift=0;  // 确定插入位置shift(从右至左)  while ( shift<uiFastCandNum && uiCost<CandCostList[ uiFastCandNum-1-shift ] )  {    shift++;  }  if( shift!=0 )  {    // 插入点及之后的模式号外后挪    for(i=1; i<shift; i++)    {      CandModeList[ uiFastCandNum-i ] = CandModeList[ uiFastCandNum-1-i ];      CandCostList[ uiFastCandNum-i ] = CandCostList[ uiFastCandNum-1-i ];    }    // 在插入点插入相应的模式号    CandModeList[ uiFastCandNum-shift ] = uiMode;    CandCostList[ uiFastCandNum-shift ] = uiCost;    return 1;  }  return 0;}

上面函数的返回值用作TEncSearch::estIntraPredLumaQT中定义的变量CandNum的增量,然而CandNum的值没有被使用,因此上面函数的返回值是没有用处的。CandCostList以从小到大的顺序,往后挪时,会把cost最大的模式覆盖掉,这样做是合理。

RMO后,再加入MPM(most probable mode)模式。如果MPM模式不在RMO产生的集合里,则加入MPM模式。

      if (m_pcEncCfg->getFastUDIUseMPMEnabled())      {        Int uiPreds[NUM_MOST_PROBABLE_MODES] = {-1, -1, -1};        Int iMode = -1;        pcCU->getIntraDirPredictor( uiPartOffset, uiPreds, COMPONENT_Y, &iMode ); // 获取MPM模式        // MPM模式的个数        const Int numCand = ( iMode >= 0 ) ? iMode : Int(NUM_MOST_PROBABLE_MODES);        for( Int j=0; j < numCand; j++)        {          Bool mostProbableModeIncluded = false;          Int mostProbableMode = uiPreds[j];          for( Int i=0; i < numModesForFullRD; i++)          {            mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]);          }          if (!mostProbableModeIncluded)          {            uiRdModeList[numModesForFullRD++] = mostProbableMode;          }        }      }

获取MPM模式的代码如下(在指针piMode指向的变量中赋MPM的个数):

/** Get most probable intra modes*\param   uiAbsPartIdx    partition index*\param   uiIntraDirPred  pointer to the array for MPM storage*\param   compID          colour component ID*\param   piMode          it is set with MPM mode in case both MPM are equal. It is used to restrict RD search at encode side.*\returns Number of MPM*/Void TComDataCU::getIntraDirPredictor( UInt uiAbsPartIdx, Int uiIntraDirPred[NUM_MOST_PROBABLE_MODES], const ComponentID compID, Int* piMode ) const{  UInt        LeftPartIdx  = MAX_UINT;  UInt        AbovePartIdx = MAX_UINT;  Int         iLeftIntraDir, iAboveIntraDir;  const TComSPS *sps=getSlice()->getSPS();  const UInt partsPerMinCU = 1<<(2*(sps->getMaxTotalCUDepth() - sps->getLog2DiffMaxMinCodingBlockSize()));  const ChannelType chType = toChannelType(compID);  const ChromaFormat chForm = getPic()->getChromaFormat();  // Get intra direction of left PU  const TComDataCU *pcCULeft = getPULeft( LeftPartIdx, m_absZIdxInCtu + uiAbsPartIdx );  if (isChroma(compID))  {    LeftPartIdx = getChromasCorrespondingPULumaIdx(LeftPartIdx, chForm, partsPerMinCU);  }  // 若左边PU不是Intra块,则赋为DC模式:Any unavailable prediction mode is considered to be Intra_DC.  iLeftIntraDir  = pcCULeft ? ( pcCULeft->isIntra( LeftPartIdx ) ? pcCULeft->getIntraDir( chType, LeftPartIdx ) : DC_IDX ) : DC_IDX;  // Get intra direction of above PU  const TComDataCU *pcCUAbove = getPUAbove( AbovePartIdx, m_absZIdxInCtu + uiAbsPartIdx, true, true );  if (isChroma(compID))  {    AbovePartIdx = getChromasCorrespondingPULumaIdx(AbovePartIdx, chForm, partsPerMinCU);  }  // 若上边PU不是Intra块,则赋为DC模式:Any unavailable prediction mode is considered to be Intra_DC.  iAboveIntraDir = pcCUAbove ? ( pcCUAbove->isIntra( AbovePartIdx ) ? pcCUAbove->getIntraDir( chType, AbovePartIdx ) : DC_IDX ) : DC_IDX;  if (isChroma(chType))  {    if (iLeftIntraDir  == DM_CHROMA_IDX)    {      iLeftIntraDir  = pcCULeft-> getIntraDir( CHANNEL_TYPE_LUMA, LeftPartIdx  );    }    if (iAboveIntraDir == DM_CHROMA_IDX)    {      iAboveIntraDir = pcCUAbove->getIntraDir( CHANNEL_TYPE_LUMA, AbovePartIdx );    }  }  assert (2<NUM_MOST_PROBABLE_MODES);  if(iLeftIntraDir == iAboveIntraDir) // 若左边和上边PU的模式相同,MPM数量为1。  {    if( piMode )    {      *piMode = 1;    }    if (iLeftIntraDir > 1) // angular modes    {      uiIntraDirPred[0] = iLeftIntraDir;      uiIntraDirPred[1] = ((iLeftIntraDir + 29) % 32) + 2;       uiIntraDirPred[2] = ((iLeftIntraDir - 1 ) % 32) + 2;     }    else //non-angular    {      uiIntraDirPred[0] = PLANAR_IDX;      uiIntraDirPred[1] = DC_IDX;      uiIntraDirPred[2] = VER_IDX;    }  }  else // 若左边和上边PU的模式不同,MPM数量为2。  {    if( piMode )    {      *piMode = 2;    }    uiIntraDirPred[0] = iLeftIntraDir;  // 左边PU的模式作为MPM模式    uiIntraDirPred[1] = iAboveIntraDir; // 上边PU的模式作为MPM模式    if (iLeftIntraDir && iAboveIntraDir ) //both modes are non-planar    {      uiIntraDirPred[2] = PLANAR_IDX;    }    else    {      uiIntraDirPred[2] =  (iLeftIntraDir+iAboveIntraDir)<2? VER_IDX : DC_IDX;    }  }  for (UInt i=0; i<NUM_MOST_PROBABLE_MODES; i++)  {    assert(uiIntraDirPred[i] < 35);  }}

上面的代码中条件if (isChroma(chType))均不会满足,调用时给的chType均是COMPONENT_Y。

0 0