VTM3.0代码阅读:predInterSearch函数

predInterSearch函数在视频编码中扮演关键角色,负责计算inter_ME和Affine_ME模式下的最优运动信息。它先进行单向预测,对L0和L1所有参考帧执行AMVP和ME。接着,双向预测通过4次迭代确定最佳运动信息。比较前向、后向和双向预测的成本,选择最优模式,并存储运动信息。对于非2Nx2N的cu,会合并运动信息。最后,进行4和6参数的Affine_ME计算,MC生成预测像素,以及设置加权预测参数。
摘要由CSDN通过智能技术生成

predInterSearch函数在xCheckRDCostInter中被调用,用来获取inter_ME以及Affine_ME模式下的最优inter运动信息。
首先对单向预测,分别对L0和L1的所有帧进行AMVP、ME,得到各个参考帧下的各种最优的运动信息;
再进行双向预测,双向预测用到了单向时得到的各帧的各种运动信息,通过4次迭代,找到最优的双向运动信息;
对比前向、后向和双向预测的cost,取最优的模式,将运动信息存入pu;
如果cu不是2Nx2N,则需要合并运动信息;
再进行4参数Affine_ME,以及6参数Affine_ME的计算;
统一进行一次MC,得到pred像素信息;
最后再设置加权预测的参数。

//! search of the best candidate for inter prediction
void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner)
{
   
  CodingStructure& cs = *cu.cs;

  AMVPInfo     amvp[2];			//存储一帧经过ME后的最优amvp信息。AMVP选择的运动信息为ME起始点
  Mv           cMvSrchRngLT;
  Mv           cMvSrchRngRB;

  Mv           cMvZero;

  Mv           cMv[2];				//两个单向预测的最优mv
  Mv           cMvBi[2];				//双向预测的最优mv
  Mv           cMvTemp[2][33];
  Mv           cMvHevcTemp[2][33];
  int          iNumPredDir = cs.slice->isInterP() ? 1 : 2;		//前向/后向预测

  Mv           cMvPred[2][33];			//存储AMVP得到的最优mvp

  Mv           cMvPredBi[2][33];		//双向预测时,ME的起点mv
  int          aaiMvpIdxBi[2][33];

  int          aaiMvpIdx[2][33];		//2表示前向后向预测,33表示L0、L1参考列表中最多33帧
  int          aaiMvpNum[2][33];		//AMVP后得到的最优MvpIdx和MvpNum

  AMVPInfo     aacAMVPInfo[2][33];		//存储每一帧的最优AMVP信息

  int          iRefIdx[2]={
   0,0}; //If un-initialized, may cause SEGV in bi-directional prediction iterative stage. 最优mv的refIdx
  int          iRefIdxBi[2];

  uint32_t         uiMbBits[3] = {
   1, 1, 0};

  uint32_t         uiLastMode = 0;
  uint32_t         uiLastModeTemp = 0;
  int          iRefStart, iRefEnd;

  int          bestBiPRefIdxL1 = 0;
  int          bestBiPMvpL1    = 0;
  Distortion   biPDistTemp     = std::numeric_limits<Distortion>::max();

#if JVET_L0646_GBI
  uint8_t      gbiIdx          = (cu.cs->slice->isInterB() ? cu.GBiIdx : GBI_DEFAULT);
  bool         enforceGBiPred = false;
#endif
  MergeCtx     mergeCtx;

  // Loop over Prediction Units
  CHECK(!cu.firstPU, "CU does not contain any PUs");
  uint32_t         puIdx = 0;
  auto &pu = *cu.firstPU;				//xCheckRDCostInter函数中添加的pu

  {
   
    // motion estimation only evaluates luma component
    m_maxCompIDToPred = MAX_NUM_COMPONENT;
//    m_maxCompIDToPred = COMPONENT_Y;

    CHECK(pu.cu != &cu, "PU is contained in another CU");

    if (cu.cs->sps->getSpsNext().getUseSubPuMvp())
    {
   
      Size bufSize = g_miScaling.scale(pu.lumaSize());
      mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
    }

    PU::spanMotionInfo( pu );
    Distortion   uiHevcCost = std::numeric_limits<Distortion>::max();
    Distortion   uiAffineCost = std::numeric_limits<Distortion>::max();
    Distortion   uiCost[2] = {
    std::numeric_limits<Distortion>::max(), std::numeric_limits<Distortion>::max() };
    Distortion   uiCostBi  =   std::numeric_limits<Distortion>::max();
    Distortion   uiCostTemp;

    uint32_t         uiBits[3];
    uint32_t         uiBitsTemp;
    Distortion   bestBiPDist = std::numeric_limits<Distortion>::max();

    Distortion   uiCostTempL0[MAX_NUM_REF];
    for (int iNumRef=0; iNumRef < MAX_NUM_REF; iNumRef++)
    {
   
      uiCostTempL0[iNumRef] = std::numeric_limits<Distortion>::max();	//失真都设为最大值
    }
    uint32_t         uiBitsTempL0[MAX_NUM_REF];

    Mv           mvValidList1;
    int          refIdxValidList1 = 0;
    uint32_t     bitsValidList1   = MAX_UINT;
    Distortion   costValidList1   = std::numeric_limits<Distortion>::max();

    PelUnitBuf origBuf = pu.cs->getOrgBuf( pu );			//orig像素信息

    xGetBlkBits( cu.partSize, cs.slice->isInterP(), puIdx, uiLastMode, uiMbBits );	//统计bit数

    m_pcRdCost->selectMotionLambda( cu.transQuantBypass );

    unsigned imvShift = pu.cu->imv << 1;
      //  Uni-directional prediction							//单向预测
      for ( int iRefList = 0; iRefList < iNumPredDir; iRefList++ )		//L0、L1
      {
   
        RefPicList  eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
#if JVET_L0293_CPR
        int refPicNumber = cs.slice->getNumRefIdx(eRefPicList);
        if (cs.slice->getSPS()->getSpsNext().getCPRMode() && eRefPicList == REF_PIC_LIST_0)
        {
   
          refPicNumber--;
        }
        for (int iRefIdxTemp = 0; iRefIdxTemp < refPicNumber; iRefIdxTemp++)
#else
        for ( int iRefIdxTemp = 0; iRefIdxTemp < cs.slice->getNumRefIdx(eRefPicList); iRefIdxTemp++ )	//L0或L1中各参考帧
#endif
        {
   
          uiBitsTemp = uiMbBits[iRefList];					//统计bit信息
          if ( cs.slice->getNumRefIdx(eRefPicList) > 1 )
          {
   
            uiBitsTemp += iRefIdxTemp+1;
            if ( iRefIdxTemp == cs.slice->getNumRefIdx(eRefPicList)-1 )
            {
   
              uiBitsTemp--;
            }
          }													//AMVP,获取当前pu周围的最优运动信息,作为ME起点
          xEstimateMvPredAMVP( pu, origBuf, eRefPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], amvp[eRefPicList], false, &biPDistTemp);

          aaiMvpIdx[iRefList][iRefIdxTemp] = pu.mvpIdx[eRefPicList];	//每一帧通过AMVP获取的最优mvp
          aaiMvpNum[iRefList][iRefIdxTemp] = pu.mvpNum[eRefPicList];

          if(cs.slice->getMvdL1ZeroFlag() && iRefList==1 && biPDistTemp < bestBiPDist)	//广义B帧时,L1信息直接复制L0
          {
   
            bestBiPDist = biPDistTemp;
            bestBiPMvpL1 = aaiMvpIdx[iRefList][iRefIdxTemp];
            bestBiPRefIdxL1 = iRefIdxTemp;
          }

          uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdx[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS];	//统计bit信息

          if ( m_pcEncCfg->getFastMEForGenBLowDelayEnabled() && iRefList == 1 )    // list 1
          {
   
            if ( cs.slice->getList1IdxToList0Idx( iRefIdxTemp ) >= 0 )			//如果使用广义B帧,则list1直接复制list0的信息
            {
   
              cMvTemp[1][iRefIdxTemp] = cMvTemp[0][cs.slice->getList1IdxToList0Idx( iRefIdxTemp )];
              uiCostTemp = uiCostTempL0[cs.slice->getList1IdxToList0Idx( iRefIdxTemp )];
              /*first subtract the bit-rate part of the cost of the other list*/
              uiCostTemp -= m_pcRdCost->getCost( uiBitsTempL0[cs.slice->getList1IdxToList0Idx( iRefIdxTemp )] );
              /*correct the bit-rate part of the current ref*/
              m_pcRdCost->setPredictor  ( cMvPred[iRefList][iRefIdxTemp] );
              uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor( cMvTemp[1][iRefIdxTemp].getHor(), cMvTemp[1][iRefIdxTemp].getVer(), imvShift );
              /*calculate the correct cost*/
              uiCostTemp += m_pcRdCost->getCost( uiBitsTemp );
            }
            else
            {
   
              xMotionEstimation( pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值