VTM1.0代码阅读:xDeriveCUMV函数

coding_unit函数中的pred_data()获取cu的预测参数数据,xDeriveCUMV则根据pred_data()获取的预测参数数据,计算得到运动信息mv。
pred_data()对于skip模式,只解码了一个merge_idx;对于merge模式,解码了merge_flag和merge_idx;对于inter_ME模式,解码了对应预测方向的refIdx、mvd、mvpIdx。
xDeriveCUMV根据这些数据,得到skip、merge和inter_ME模式的mv。其中skip和merge获取mv过程一样,因为skip相比merge模式只是少了残差变换系数。

Void DecCu::xDeriveCUMV( CodingUnit &cu )
{
  for( auto &pu : CU::traversePUs( cu ) )	//对cu的每个pu计算mv	而vtm中的cu是不会划分pu的,即只有一个pu
  {
    MergeCtx mrgCtx;			//merge候选列表

    if( pu.mergeFlag )			//merge / skip
    {
      if( cu.cs->pps->getLog2ParallelMergeLevelMinus2() && cu.partSize != SIZE_2Nx2N && cu.lumaSize().width <= 8 )	//一般false
      {
        if( !mrgCtx.hasMergedCandList )
        {
          // temporarily set size to 2Nx2N
          PartSize                 tmpPS    = SIZE_2Nx2N;
          PredictionUnit           tmpPU    = pu;
          static_cast<UnitArea&> ( tmpPU )  = cu;
          std::swap( tmpPS, cu.partSize );
          PU::getInterMergeCandidates( tmpPU, mrgCtx, pu.mergeIdx );
          std::swap( tmpPS, cu.partSize );
          mrgCtx.hasMergedCandList          = true;
        }
      }
      else
      {
        PU::getInterMergeCandidates( pu, mrgCtx, pu.mergeIdx );	//构建merge列表
      }												//参数pu.mergeIdx,让merge列表构建到mergeIdx个就结束
          
      mrgCtx.setMergeInfo( pu, pu.mergeIdx );	//由mergeIdx和merge列表,确定了pu各种运动信息,包含mv
          
      if( pu.interDir == 3 /* PRED_BI */ && PU::isBipredRestriction(pu) )
      {											//双向预测,但是pu满足一定条件时,后向预测设为不可用,变为前向单向预测
        pu.mv    [REF_PIC_LIST_1] = Mv(0, 0);
        pu.refIdx[REF_PIC_LIST_1] = -1;
        pu.interDir               =  1;
      }
      PU::spanMotionInfo( pu, mrgCtx );      //pu的运动信息扩展到pu中所有小块
    }
    else			//inter_ME模式
    {
      for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )	//参考列表L0/l1
      {
        RefPicList eRefList = RefPicList( uiRefListIdx );		//pu.interDir=1 2 3分别为前向、后向、双向预测
        if ( pu.cs->slice->getNumRefIdx( eRefList ) > 0 && ( pu.interDir & ( 1 << uiRefListIdx ) ) )	//pu.interDir & (1<<uiRefListIdx)写法真好
        {										//参考列表中有参考帧,而且,pu的参考方向有这个uiRefListIdx方向
          AMVPInfo amvpInfo;		//AMVP候选列表
          PU::fillMvpCand( pu, eRefList, pu.refIdx[eRefList], amvpInfo );	//构建AMVP候选列表,用到refIdx
          pu.mvpNum [eRefList] = amvpInfo.numCand;
          pu.mv     [eRefList] = amvpInfo.mvCand[pu.mvpIdx [eRefList]] + pu.mvd[eRefList];	//根据mvpIdx在AMVP列表中查找得到mvp,再加上mvd就得到mv
        }
      }
      PU::spanMotionInfo( pu, mrgCtx );		//pu的运动信息扩展到pu中所有小块
    }
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值