VTM3.0代码阅读:getAffineMergeCand函数

本文详细介绍了VTM3.0编码器中getAffineMergeCand函数的工作流程,该函数用于生成AffineMerge候选列表。在xCheckRDCostAffineMerge2Nx2N函数中被调用,首先存储相邻块的运动信息,然后构建Affine_Merge候选,包括SbTMVP候选、继承的Affine候选和构造的Affine候选。
摘要由CSDN通过智能技术生成

xCheckRDCostAffineMerge2Nx2N函数中调用getAffineMergeCand来获取AffineMerge候选列表。
AffineMerge候选列表的类:

class AffineMergeCtx		//AffineMerge候选列表的类
{
   
	//...
public:
  MvField       mvFieldNeighbours[AFFINE_MRG_MAX_NUM_CANDS << 1][3]; // double length for mv of both lists 5组3控制点
  unsigned char interDirNeighbours[AFFINE_MRG_MAX_NUM_CANDS];	//AffineMerge候选列表长度为5
  EAffineModel  affineType[AFFINE_MRG_MAX_NUM_CANDS];			//4参数、6参数
#if JVET_L0646_GBI
  uint8_t       GBiIdx[AFFINE_MRG_MAX_NUM_CANDS];
#endif
  int           numValidMergeCand;
  int           maxNumMergeCand;

#if JVET_L0369_SUBBLOCK_MERGE
  MergeCtx     *mrgCtx;				//这个merge候选列表是为了获取ATMVP模式给Affine的候选
  MergeType     mergeType[AFFINE_MRG_MAX_NUM_CANDS];	//具体看getAffineMergeCand函数中
#endif
};

getAffineMergeCand的函数流程,构建Affine_Merge候选列表:
前半部分类似merge列表构造过程,首先将相邻块运动信息存入mrgCtx,方便SbTMVP模式获取偏移mv的执行;
后半部分构造Affine_Merge列表过程和L1002中描述相同;
affMrgCtx添加的第一个候选,就是SbTMVP候选;
之后添加:继承的Affine候选、构造的Affine候选、0。

void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx, const int mrgCandIdx )
{
   
  const CodingStructure &cs = *pu.cs;
  const Slice &slice = *pu.cs->slice;
  const uint32_t maxNumAffineMergeCand = slice.getMaxNumAffineMergeCand();

  for ( int i = 0; i < maxNumAffineMergeCand; i++ )		//Affine候选列表初始化
  {
   
    for ( int mvNum = 0; mvNum < 3; mvNum++ )		//3控制点
    {
   
      affMrgCtx.mvFieldNeighbours[(i << 1) + 0][mvNum].setMvField( Mv(), -1 );
      affMrgCtx.mvFieldNeighbours[(i << 1) + 1][mvNum].setMvField( Mv(), -1 );
    }
    affMrgCtx.interDirNeighbours[i] = 0;
    affMrgCtx.affineType[i] = AFFINEMODEL_4PARAM;	//初始化为4参数Affine
#if JVET_L0369_SUBBLOCK_MERGE
    affMrgCtx.mergeType[i] = MRG_TYPE_DEFAULT_N;
#endif
#if JVET_L0646_GBI
    affMrgCtx.GBiIdx[i] = GBI_DEFAULT;
#endif
  }

  affMrgCtx.numValidMergeCand = 0;
  affMrgCtx.maxNumMergeCand = maxNumAffineMergeCand;

#if JVET_L0369_SUBBLOCK_MERGE ///> insert ATMVP candidate		//首先添加SbTMVP模式给Affine的候选
#if JVET_L0293_CPR
  bool enableSubPuMvp = slice.getSPS()->getSpsNext().getUseSubPuMvp() && !(slice.getPOC() == slice.getRefPic(REF_PIC_LIST_0, 0)->getPOC() && slice.isIRAP());
#else
  bool enableSubPuMvp = slice.getSPS()->getSpsNext().getUseSubPuMvp();
#endif
  bool isAvailableSubPu = false;
  if ( enableSubPuMvp && slice.getEnableTMVPFlag() )		//SbTMVP
  {
   
#if JVET_L0293_CPR
    int  cntCPR = 0;
#endif
    MergeCtx mrgCtx = *affMrgCtx.mrgCtx;		//Affine候选列表类中的merge列表
    bool tmpLICFlag = false;

    CHECK( mrgCtx.subPuMvpMiBuf.area() == 0 || !mrgCtx.subPuMvpMiBuf.buf, "Buffer not initialized" );
    mrgCtx.subPuMvpMiBuf.fill( MotionInfo() );

    int pos = 0;
    // Get spatial MV
    const Position posCurRT = pu.Y().topRight();			//首先mrgCtx中存入相邻块的运动信息
    const Position posCurLB = pu.Y().bottomLeft();
    MotionInfo miAbove, miLeft, miAboveRight, miBelowLeft;
													//这里的过程和merge模式时基本一致
    //left 左
    const PredictionUnit* puLeft = cs.getPURestricted( posCurLB.offset( -1, 0 ), pu, pu.chType );
    const bool isAvailableA1 = puLeft && isDiffMER( pu, *puLeft ) && pu.cu != puLeft->cu && CU::isInter( *puLeft->cu );
    if ( isAvailableA1 )
    {
   
      miLeft = puLeft->getMotionInfo( posCurLB.offset( -1, 0 ) );
      // get Inter Dir
      mrgCtx.interDirNeighbours[pos] = miLeft.interDir;

      // get Mv from Left
#if JVET_L0293_CPR
      if (puLeft->cu->cpr)
      {
   
        cntCPR++;
      }
#endif
      mrgCtx.mvFieldNeighbours[pos << 1].setMvField( miLeft.mv[0], miLeft.refIdx[0] );

      if ( slice.isInterB() )
      {
   
        mrgCtx.mvFieldNeighbours[(pos << 1) + 1].setMvField( miLeft.mv[1], miLeft.refIdx[1] );
      }
      pos++;
    }

    // above 上
    const PredictionUnit *puAbove = cs.getPURestricted
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值