HM 코드 읽기: 프레임 내 예측(一)

10184 단어 H.265
본고의 코드는 모두 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 ( shift1-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는 작은 순서에서 큰 순서로 뒤로 옮길 때 가장 큰 코스트의 패턴을 덮어쓰는 것이 합리적이다.
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 (2if(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; iassert(uiIntraDirPred[i] < 35);
  }
}

위 코드의 조건if(ischroma(chType)는 모두 만족하지 않으며, 호출할 때 주는chType은 모두COMPONENTY.

좋은 웹페이지 즐겨찾기