VVC/JEM代码学习3:getIntraDirPredictor

(个人理解)

    该函数的作用就是在亮度分量预测时在67种模式中选取6个MPMs。首先是查看当前CU邻近5个CU的亮度预测模式和DC和planar模式,加入顺序为左,上,planar,DC,左下,右上,最后是左上(如果该模式MPM中以存在,不重复添加)。如果这几个模式形成的MPM的数目不足6,则将列表里的角度模式的相邻模式也加入。如果还不足6,则加入默认模式。默认模式列表为{PLANAR_IDX, DC_IDX, VER_IDX, HOR_IDX, 2, DIA_IDX(34)}。

Void TComDataCU::getIntraDirPredictor( UInt uiAbsPartIdx, Int uiIntraDirPred[NUM_MOST_PROBABLE_MODES], const ComponentID compID

#if VCEG_AZ07_INTRA_65ANG_MODES && !JVET_C0055_INTRA_MPM
                                      , Int &iLeftAboveCase
#endif
                                      , Int* piMode  )
{
#if JVET_C0055_INTRA_MPM
  // This function is not used for chroma texture type.
  // If it is used for chroma, DM mode should be converted to real mode during MPM list derivation.
#if !JVET_E0062_MULTI_DMS
  assert( isLuma(compID) );
#endif


  const ChannelType chType = toChannelType(compID);//表示三个分量中的哪一个;
  Bool includedMode[NUM_INTRA_MODE];//NUM_INTRA_MODE=73;
  memset( includedMode, false, sizeof(includedMode) );


  UInt modeIdx = 0, partIdx;


#if VCEG_AZ07_INTRA_65ANG_MODES
  const Int offset = 62;
#else
  const Int offset = 29;
#endif
  const Int mod = offset + 3;


  UInt width  = getWidth(uiAbsPartIdx);//64;
  UInt height = getHeight(uiAbsPartIdx);//64;


#if !JVET_C0024_QTBT
  if( getPartitionSize(uiAbsPartIdx) == SIZE_NxN )
  {
    width  >>= 1;
    height >>= 1;
  }
#endif


  UInt partIdxLT = m_absZIdxInCtu + uiAbsPartIdx;
  UInt partIdxRT = g_auiRasterToZscan [g_auiZscanToRaster[ partIdxLT ] + width / m_pcPic->getMinCUWidth() - 1 ];
  UInt partIdxLB = g_auiRasterToZscan [g_auiZscanToRaster[ partIdxLT ] + ( (height / m_pcPic->getMinCUHeight()) - 1 ) * m_pcPic->getNumPartInCtuWidth()];
#if JVET_E0062_MULTI_DMS//Cb分量最大模式数量为5,其他为6;
  Int iMaxModeNum = (compID == COMPONENT_Cb ? NUM_DM_MODES : NUM_MOST_PROBABLE_MODES);
  if(compID == COMPONENT_Cb)
  {
    Int i = 0;
    for(; i< NUM_DM_MODES; i++)
    {
      if (uiIntraDirPred[i] == INVALID_CHROMAMODE)
      {
        break;
      }
      else
      {
        includedMode[uiIntraDirPred[i]] = true;
      }
    }
#if COM16_C806_LMCHROMA
    includedMode[LM_CHROMA_IDX] = true;
#endif


#if JVET_E0077_MMLM
    includedMode[MMLM_CHROMA_IDX] = true;
#endif
#if JVET_E0077_LM_MF
    for (Int iF = 0; iF < LM_FILTER_NUM; iF++)//LM_FILTER_NUM=4;
    {
        includedMode[LM_CHROMA_F1_IDX + iF] = true;
    }
#endif


    modeIdx = i;
  }
#endif
  // left
  TComDataCU *cu = getPULeft( partIdx, partIdxLB );//得到左边的相邻PU;
  if( cu && cu->isIntra(partIdx) )//若左边相邻块存在且使帧内预测模式;
  {
    uiIntraDirPred[modeIdx] = cu->getIntraDir( chType, partIdx );//得到左边相邻块的帧内预测方向;
    if( !includedMode[uiIntraDirPred[modeIdx]] )
    {
      includedMode[uiIntraDirPred[modeIdx]] = true;
      modeIdx++;
    }   
  }
#if JVET_E0062_MULTI_DMS
  if(compID == COMPONENT_Cb && modeIdx == NUM_DM_MODES )
  {
    return;
  }
#endif


  // above
  cu = getPUAbove( partIdx, partIdxRT );
  if( cu && cu->isIntra(partIdx) )
  {
    uiIntraDirPred[modeIdx] = cu->getIntraDir( chType, partIdx );//若上边相邻块存在且使帧内预测模式;
    if( !includedMode[uiIntraDirPred[modeIdx]] )
    {
      includedMode[uiIntraDirPred[modeIdx]] = true;
      modeIdx++;
    }   
  }
#if JVET_E0062_MULTI_DMS
  if( compID == COMPONENT_Cb && modeIdx == NUM_DM_MODES )
  {
    return;
  }
#endif


  if( piMode )
  {
    *piMode = Int(modeIdx > 1) + 1;
  }
#if JVET_E0062_MULTI_DMS  
  if(compID != COMPONENT_Cb)
  {
#endif  
  // PLANAR mode
  uiIntraDirPred[modeIdx] = PLANAR_IDX;
  if( !includedMode[uiIntraDirPred[modeIdx]] )//如果没有包括Planar模式,则将该模式包括进去,并将模式索引加1;
  {
    includedMode[uiIntraDirPred[modeIdx]] = true;
    modeIdx++;
  }


  // DC mode
#if !VCEG_AZ07_INTRA_65ANG_MODES
  if( modeIdx < NUM_MOST_PROBABLE_MODES )
#endif
  {
    uiIntraDirPred[modeIdx] = DC_IDX;
    if( !includedMode[uiIntraDirPred[modeIdx]] )
    {
      includedMode[uiIntraDirPred[modeIdx]] = true;//如果没有包括DC模式,则将该模式包括进去,并将模式索引加1;
      modeIdx++;
    }
  }
#if JVET_E0062_MULTI_DMS  
  }
#endif 
  // below left
#if !VCEG_AZ07_INTRA_65ANG_MODES
  if( modeIdx < NUM_MOST_PROBABLE_MODES )
#endif
  {
    cu = getPUBelowLeft( partIdx, partIdxLB );
    if( cu && cu->isIntra(partIdx) )//若左下相邻块存在且使帧内预测模式;
    {
      uiIntraDirPred[modeIdx] = cu->getIntraDir( chType, partIdx );
      if( !includedMode[uiIntraDirPred[modeIdx]] )
      {
        includedMode[uiIntraDirPred[modeIdx]] = true;
        modeIdx++;
      }
    }
  }
#if JVET_E0062_MULTI_DMS
  if( compID == COMPONENT_Cb && modeIdx == NUM_DM_MODES )
  {
    return;
  }
#endif


  // above right
#if !VCEG_AZ07_INTRA_65ANG_MODES
  if( modeIdx < NUM_MOST_PROBABLE_MODES )
#endif
  {
    cu = getPUAboveRight( partIdx, partIdxRT );
    if( cu && cu->isIntra(partIdx) )//若右上相邻块存在且使帧内预测模式;
    {
      uiIntraDirPred[modeIdx] = cu->getIntraDir( chType, partIdx );
      if( !includedMode[uiIntraDirPred[modeIdx]] )
      {
        includedMode[uiIntraDirPred[modeIdx]] = true;
        modeIdx++;
      }
    }
  }
#if JVET_E0062_MULTI_DMS
  if( compID == COMPONENT_Cb && modeIdx == NUM_DM_MODES )
  {
    return;
  }
#endif


  //above left
#if JVET_E0062_MULTI_DMS  
  if( modeIdx < iMaxModeNum )//iMaxModeNum=6;
#else
  if( modeIdx < NUM_MOST_PROBABLE_MODES )
#endif
  {
    cu = getPUAboveLeft( partIdx, partIdxLT );
    if( cu && cu->isIntra(partIdx) )//若左上相邻块存在且使帧内预测模式;
    {
      uiIntraDirPred[modeIdx] = cu->getIntraDir( chType, partIdx );
      if( !includedMode[uiIntraDirPred[modeIdx]] )
      {
        includedMode[uiIntraDirPred[modeIdx]] = true;
        modeIdx++;
      }
    }
  }
#if JVET_E0062_MULTI_DMS
  if( compID == COMPONENT_Cb && modeIdx == NUM_DM_MODES )
  {
    return;
  }
 
  if(compID == COMPONENT_Cb)
  {
    // PLANAR mode
    uiIntraDirPred[modeIdx] = PLANAR_IDX;
    if( !includedMode[uiIntraDirPred[modeIdx]] )
    {
      includedMode[uiIntraDirPred[modeIdx]] = true;
      modeIdx++;
    }


    if( compID == COMPONENT_Cb && modeIdx == NUM_DM_MODES )
    {
      return;
    }


    // DC mode
#if !VCEG_AZ07_INTRA_65ANG_MODES
    if( modeIdx < NUM_MOST_PROBABLE_MODES )
#endif
    {
      uiIntraDirPred[modeIdx] = DC_IDX;
      if( !includedMode[uiIntraDirPred[modeIdx]] )
      {
        includedMode[uiIntraDirPred[modeIdx]] = true;
        modeIdx++;
      }
    }


    if( compID == COMPONENT_Cb && modeIdx == NUM_DM_MODES )
    {
      return;
    }
  }
#endif 
  UInt numAddedModes = modeIdx;


  // -+1 derived modes
#if JVET_E0062_MULTI_DMS  //如果MPM里的候选模式个数少于6,则将列表中角度模式相邻的模式加入;
  for( UInt idx = 0; idx < numAddedModes && modeIdx < iMaxModeNum; idx++ )
#else
  for( UInt idx = 0; idx < numAddedModes && modeIdx < NUM_MOST_PROBABLE_MODES; idx++ )
#endif
  {   
    UInt mode = uiIntraDirPred[idx];
    
    // directional mode
    if( mode <= DC_IDX )
    {
      continue;
    }


    // -1
    uiIntraDirPred[modeIdx] = ((mode + offset) % mod) + 2;


    if( !includedMode[uiIntraDirPred[modeIdx]] )
    {
      includedMode[uiIntraDirPred[modeIdx]] = true;
      modeIdx++;
    }    


#if JVET_E0062_MULTI_DMS
    if( modeIdx == iMaxModeNum )
#else
    if( modeIdx == NUM_MOST_PROBABLE_MODES )
#endif
    {
      break;
    }


    // +1
    uiIntraDirPred[modeIdx] = ((mode - 1) % mod) + 2;


    if( !includedMode[uiIntraDirPred[modeIdx]] )
    {
      includedMode[uiIntraDirPred[modeIdx]] = true;
      modeIdx++;
    }   
  }


  // default modes
  UInt defaultIntraModes[] = {PLANAR_IDX, DC_IDX, VER_IDX, HOR_IDX, 2, DIA_IDX};
  assert( modeIdx > 1 );
#if JVET_E0062_MULTI_DMS  
  for( UInt idx = 2; idx < iMaxModeNum && modeIdx < iMaxModeNum; idx++)//如果MPM里的模式个数还小于6,则加入默认模式;
#else
  for( UInt idx = 2; idx < NUM_MOST_PROBABLE_MODES && modeIdx < NUM_MOST_PROBABLE_MODES; idx++ )
#endif
  {
    uiIntraDirPred[modeIdx] = defaultIntraModes[idx];
    if( !includedMode[uiIntraDirPred[modeIdx]] )
    {
      includedMode[uiIntraDirPred[modeIdx]] = true;
      modeIdx++;
    }
  }
#if JVET_E0062_MULTI_DMS  
  assert( modeIdx == iMaxModeNum );

#if JVET_E0062_MULTI_DMS
  for (UInt i=0; i<iMaxModeNum; i++)
#else
  for (UInt i=0; i<NUM_MOST_PROBABLE_MODES; i++)
#endif
  {
#if VCEG_AZ07_INTRA_65ANG_MODES
    assert(uiIntraDirPred[i] < (NUM_INTRA_MODE-1));
#else
    assert(uiIntraDirPred[i] < 35);
#endif
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值