HEVC代码学习13:predInterSearch函数

在上一章的xCheckRDCostInter学习中,我们知道了,进行帧间搜索的入口实际是predInterSearch,今天我们就来对他进行学习。
推荐看大神博客
http://blog.csdn.net/nb_vol_1/article/details/51162391

predInterSearch主要作用是进行运动估计和运动补偿。
1.对CU的每一个PU遍历参考列表中的参考图像,进行运动估计,找到最优参考帧和MV。
2.对于B帧,需要对后向参考预测块进行运动补偿,在运动补偿之后重新进行运动估计,找到最优MV。
3.对于非2Nx2N的分块,需要计算并合并他们的运动估计代价。
4.最后进行运动补偿,设置加权预测。

其中涉及了广义B帧的处理,前后参考列表中的参考图像都是用当前图像之前的图像,且两个参考列表完全一致,因此list0和list1相同。

使用到了以下重要函数:
1.xEstimateMvPredAMVP:AMVP的入口函数,执行AMVP操作。
2.xMotionEstimation:运动估计的入口函数,进行运动搜索,找到MV。
3.motionCompensation:运动补偿的入口函数,进行运动补偿,构造匹配块信息。

这里补充一下AMVP与运动估计的关系。AMVP会为运动估计ME提供候选MVP,ME会选择其中率失真代价最小的MVP作为起点,进行搜索,找到最优的MV。

另外MVD也是在predInterSearch函数中计算的,找到最优MV后,会根据MVD = MV - MVP计算MVD。

//帧间搜索最佳候选
//! search of the best candidate for inter prediction
#if AMP_MRG
Void TEncSearch::predInterSearch( TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, TComYuv* pcRecoYuv DEBUG_STRING_FN_DECLARE(sDebug), Bool bUseRes, Bool bUseMRG )
#else
Void TEncSearch::predInterSearch( TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, TComYuv* pcRecoYuv, Bool bUseRes )
#endif
{
  for(UInt i=0; i<NUM_REF_PIC_LIST_01; i++)
  {
    m_acYuvPred[i].clear();
  }
  m_cYuvPredTemp.clear();
  pcPredYuv->clear();

  if ( !bUseRes )
  {
    pcResiYuv->clear();
  }

  pcRecoYuv->clear();

  TComMv       cMvSrchRngLT;    //左上
  TComMv       cMvSrchRngRB;    //右下

  TComMv       cMvZero;
  TComMv       TempMv; //kolya

  TComMv       cMv[2];
  TComMv       cMvBi[2];
  TComMv       cMvTemp[2][33];

  Int          iNumPart    = pcCU->getNumPartitions();      //分块数
  Int          iNumPredDir = pcCU->getSlice()->isInterP() ? 1 : 2;    //预测方向,P帧为1,B帧为2

  TComMv       cMvPred[2][33];      //记录前向参考帧的MV

  TComMv       cMvPredBi[2][33];    //记录后向参考帧的MV
  Int          aaiMvpIdxBi[2][33];    //记录后向参考帧的MVP索引

  Int          aaiMvpIdx[2][33];    //记录前向参考帧的MVP索引
  Int          aaiMvpNum[2][33];    //记录MVP的数量

  AMVPInfo     aacAMVPInfo[2][33];      //记录AMVP的信息

  Int          iRefIdx[2]={
  0,0}; //If un-initialized, may cause SEGV in bi-directional prediction iterative stage.
  Int          iRefIdxBi[2];

  UInt         uiPartAddr;
  Int          iRoiWidth, iRoiHeight;

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

  UInt         uiLastMode = 0;
  Int          iRefStart, iRefEnd;

  PartSize     ePartSize = pcCU->getPartitionSize( 0 );

  Int          bestBiPRefIdxL1 = 0;
  Int          bestBiPMvpL1 = 0;
  Distortion   biPDistTemp = std::numeric_limits<Distortion>::max();    //将失真置为最大

  TComMvField cMvFieldNeighbours[MRG_MAX_NUM_CANDS << 1]; // double length for mv of both lists 为了双向MV,长度为2倍
  UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS];
  Int numValidMergeCand = 0 ;

  //初始化,将所有分块的失真都置为最大
  for ( Int iPartIdx = 0; iPartIdx < iNumPart; iPartIdx++ )
  {
    Distortion   uiCost[2] = { std::numeric_limits<Distortion>::max(), std::numeric_limits<Distortion>::max() };     
    Distortion   uiCostBi  =   std::numeric_limits<Distortion>::max();     
    Distortion   uiCostTemp;

    UInt         uiBits[3];
    UInt         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();       
    }
    UInt         uiBitsTempL0[MAX_NUM_REF];

    TComMv       mvValidList1;
    Int          refIdxValidList1 = 0;
    UInt         bitsValidList1 = MAX_UINT;
    Distortion   costValidList1 = std::numeric_limits<Distortion>::max();

    xGetBlkBits( ePartSize, pcCU->getSlice()->isInterP(), iPartIdx, uiLastMode, uiMbBits);   //获取CU块的bitpcCU->getPartIndexAndSize( iPartIdx, uiPartAddr, iRoiWidth, iRoiHeight );    //获取CU的宽、高、起始地址信息

#if AMP_MRG
    Bool bTestNormalMC = true;      //bTestNormalMC指示是否进行正常的MC(ME+MC)

    if ( bUseMRG && pcCU->getWidth( 0 ) > 8 && iNumPart == 2 )      //bUseMRG为真、CU大于8且分块为SIZE_2NxN时,不能进行正常的MC
    {
      bTestNormalMC = false;        
    }

    /*********************************************************正常MC*****************************************************************/
    if (bTestNormalMC)
    {
#endif

    //建立参考列表,P帧只有一个,B帧有两个
    //  Uni-directional prediction
    for ( Int iRefList = 0; iRefList < iNumPredDir; iRefList++ )    //iRefList为当前参考列表
    {
      RefPicList  eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );     //前向后参考列表

      //遍历这个参考列表的所有参考帧 
      for ( Int iRefIdxTemp = 0; iRefIdxTemp < pcCU->getSlice()->getNumRefIdx(eRefPicList); iRefIdxTemp++ )     //iRefIdxTemp为当前参考帧索引
      {
        uiBitsTemp = uiMbBits[iRefList];    //存储参考列表的bitif ( pcCU->getSlice()->getNumRefIdx(eRefPicList) > 1 )      //如果参考列表中的帧数大于1,计算所有参考帧的总bit数
        {
          uiBitsTemp += iRefIdxTemp+1;
          if ( iRefIdxTemp ==
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值