HEVC之MPM和PU预测模式在编码过程中的关系

HEVC编码时,根据MPM和pu的预测模式来选择使用一个bin还是5个bin编码预测模式索引,若pu的预测模式和mpm中某一模式相同,则编码mpm中的索引,用一个bin。如果pu的预测模式不属于mpm列表中的预测模式,则用5个bin编码该pu的预测模式,这个过程属于熵编码阶段,以HM为例,该过程发生在函数codeIntraDirLumaAng中。

Void TEncSbac::codeIntraDirLumaAng( TComDataCU* pcCU, UInt absPartIdx, Bool isMultiple)
{
  UInt dir[4],j;
  Int preds[4][NUM_MOST_PROBABLE_MODES] = {{-1, -1, -1},{-1, -1, -1},{-1, -1, -1},{-1, -1, -1}};
  Int predIdx[4] ={ -1,-1,-1,-1};
  PartSize mode = pcCU->getPartitionSize( absPartIdx );  // PU的划分方式  [wzq 8/24/2020 ]
  UInt partNum = isMultiple?(mode==SIZE_NxN?4:1):1;
  UInt partOffset = ( pcCU->getPic()->getNumPartitionsInCtu() >> ( pcCU->getDepth(absPartIdx) << 1 ) ) >> 2;
  for (j=0;j<partNum;j++)
  {
    dir[j] = pcCU->getIntraDir( CHANNEL_TYPE_LUMA, absPartIdx+partOffset*j );
    pcCU->getIntraDirPredictor(absPartIdx+partOffset*j, preds[j], COMPONENT_Y); // 构造MPM列表  [wzq 8/24/2020 ]
    for(UInt i = 0; i < NUM_MOST_PROBABLE_MODES; i++)
    {
      if(dir[j] == preds[j][i]) // preds[]是构造的3个mpms  [wzq 8/24/2020 ]
      {
        predIdx[j] = i;   // predIdx[j]存储预测模式在mpm中的indx,  [wzq 9/25/2020 ]
      }
    }
    m_pcBinIf->encodeBin((predIdx[j] != -1)? 1 : 0, m_cCUIntraPredSCModel.get( 0, 0, 0 ) );
  }
  for (j=0;j<partNum;j++)
  {
    if(predIdx[j] != -1)
    {
      m_pcBinIf->encodeBinEP( predIdx[j] ? 1 : 0 );
      if (predIdx[j])
      {
        m_pcBinIf->encodeBinEP( predIdx[j]-1 ); // 编码预测模式在mpm中的indx,用一个bin  [wzq 9/25/2020 ]
      }
    }
    else          // 预测模式不属于mpm中的任一个  [wzq 9/25/2020 ]
    {
      if (preds[j][0] > preds[j][1])
      {
        std::swap(preds[j][0], preds[j][1]);
      }
      if (preds[j][0] > preds[j][2])
      {
        std::swap(preds[j][0], preds[j][2]);
      }
      if (preds[j][1] > preds[j][2])
      {
        std::swap(preds[j][1], preds[j][2]);
      }
      for(Int i = (Int(NUM_MOST_PROBABLE_MODES) - 1); i >= 0; i--)
      {
        dir[j] = dir[j] > preds[j][i] ? dir[j] - 1 : dir[j];
      }
      m_pcBinIf->encodeBinsEP( dir[j], 5 );   // 用5bin编码预测模式的indx  [wzq 9/25/2020 ]
    }
  }
  return;
}

在SVT-HEVC中,该过程发生在函数EncodeIntraLumaModeSecondStage中

static void EncodeIntraLumaModeSecondStage(
	CabacEncodeContext_t   *cabacEncodeCtxPtr,
    EB_U8                   leftNeighborMode,
    EB_U8                   topNeighborMode,
    EB_U32                  lumaMode)
{
	EB_S32 predictionIndex;

	EB_U32 lumaPredictionArray[3];

	if (leftNeighborMode == topNeighborMode) {

		if (leftNeighborMode > 1) { // For angular modes
			lumaPredictionArray[0] = leftNeighborMode;
			lumaPredictionArray[1] = ((leftNeighborMode + 29) & 0x1F) + 2;
			lumaPredictionArray[2] = ((leftNeighborMode - 1) & 0x1F) + 2;
		}
		else { // Non Angular modes
			lumaPredictionArray[0] = EB_INTRA_PLANAR;
			lumaPredictionArray[1] = EB_INTRA_DC;
			lumaPredictionArray[2] = EB_INTRA_VERTICAL;
		}
	}
	else {
		lumaPredictionArray[0] = leftNeighborMode;
		lumaPredictionArray[1] = topNeighborMode;

		if (leftNeighborMode && topNeighborMode) {
			lumaPredictionArray[2] = EB_INTRA_PLANAR; // when both modes are non planar
		}
		else {
			lumaPredictionArray[2] = (leftNeighborMode + topNeighborMode) < 2 ? EB_INTRA_VERTICAL : EB_INTRA_DC;
		}
	}

	predictionIndex = (lumaMode == lumaPredictionArray[0]) ? 0 :
		(lumaMode == lumaPredictionArray[1]) ? 1 :
		(lumaMode == lumaPredictionArray[2]) ? 2 :
		-1; // luma mode is not equal to any of the predictors

	if (predictionIndex != -1) 
	{
		EncodeBypassOneBin(&(cabacEncodeCtxPtr->bacEncContext),predictionIndex ? 1 : 0);

		if (predictionIndex) 
		{
			EncodeBypassOneBin(&(cabacEncodeCtxPtr->bacEncContext),predictionIndex - 1);
		}
	}
	else 
	{
		if (lumaPredictionArray[0] > lumaPredictionArray[1]) 
		{
			SWAP(lumaPredictionArray[0], lumaPredictionArray[1]);
		}

		if (lumaPredictionArray[0] > lumaPredictionArray[2]) 
		{
			SWAP(lumaPredictionArray[0], lumaPredictionArray[2]);
		}

		if (lumaPredictionArray[1] > lumaPredictionArray[2]) 
		{
			SWAP(lumaPredictionArray[1], lumaPredictionArray[2]);
		}

		lumaMode =
			(lumaMode > lumaPredictionArray[2]) ? lumaMode - 1 :
			lumaMode;
		lumaMode =
			(lumaMode > lumaPredictionArray[1]) ? lumaMode - 1 :
			lumaMode;
		lumaMode =
			(lumaMode > lumaPredictionArray[0]) ? lumaMode - 1 :
			lumaMode;

		EncodeBypassBins( &(cabacEncodeCtxPtr->bacEncContext),lumaMode,5);
	}

}

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值