⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 motionestimation.cpp

📁 JMVM MPEG MVC/3DAV 测试平台 国际通用标准
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        {
          xPelLogSearch   ( pcRefPelData[0], cMv, uiMinSAD, false, m_iMaxLogStep << ((NULL == pcBSP) ? 1 : 0) );
        }
        break;
      case 3:
        {
          rcMbDataAccess.getMvPredictors( m_acMvPredictors );
          xPelLogSearch   ( pcRefPelData[0], cMv, uiMinSAD, true, (NULL == pcBSP) ? 2 : 1 );
        }
        break;
      case 4:
        {
          rcMbDataAccess.getMvPredictors( m_acMvPredictors );
          xTZSearch( pcRefPelData[0], cMv, uiMinSAD );
        }
        break;
      default:
        RERR();
        break;
      }
    }
    cMv <<= 2;
  }
  else
  {
    Mv cMvBase = cMv;
    cMv.limitComponents( m_cMin, m_cMax );
    if( ! ( cMvBase == cMv ) )
    {
      // don't refine in that case
      rcMv     = cMvBase;
      ruiBits += 2;
      ruiCost  = MSYS_UINT_MAX / 2;
      // >>>> bug fix by H.Schwarz 19/9/05
      if( bOriginalSearchModeIsYUVSAD )
      {
        m_cParams.setFullPelDFunc( DF_YUV_SAD );
      }
      // <<<< bug fix by H.Schwarz 19/9/05
      return Err::m_nOK;
    }
  }
  // heiko.schwarz@hhi.fhg.de (fix for uninitialized memory with YUV_SAD and bi-directional search) >>>>
  if( bOriginalSearchModeIsYUVSAD )
  {
    m_cParams.setFullPelDFunc( DF_YUV_SAD );
  }
  // <<< heiko.schwarz@hhi.fhg.de (fix for uninitialized memory with YUV_SAD and bi-directional search)


  //===== SUB-PEL ESTIMATION =====
  xGetMotionCost( 1 != ( 1 & m_cParams.getSubPelDFunc() ), 0 );
  m_pcXDistortion->getDistStruct( uiMode, m_cParams.getSubPelDFunc(), false, m_cXDSS );
  m_cXDSS.pYOrg = pcWeightedYuvBuffer->getLumBlk();
  xSetCostScale( 0 );

  xSubPelSearch( pcRefPelData[1], cMv, uiMinSAD, uiBlk, uiMode, bQPelRefinementOnly );

  Short sHor      = cMv.getHor();
  Short sVer      = cMv.getVer();
  UInt  uiMvBits  = xGetBits( sHor, sVer );
  ruiBits        += uiMvBits;
  ruiCost         = (UInt)floor( fWeight * (Double)( uiMinSAD - xGetCost( uiMvBits ) ) ) + xGetCost( ruiBits );
  rcMv            = cMv;

  return Err::m_nOK;
}


#if JMVM_ONLY  // JVT-U052
ErrVal
MotionEstimation::estimateBlockWithStart( Icp&                 rcIcp,
                                          const MbDataAccess&  rcMbDataAccess,
                                          const IntFrame&      rcRefFrame,
                                          Mv&                  rcMv,         // <-- MVSTART / --> MV
                                          Mv&                  rcMvPred,
                                          UInt&                ruiBits,
                                          UInt&                ruiCost,
                                          UInt                 uiBlk,
                                          UInt                 uiMode,
                                          Bool                 bQPelRefinementOnly,
                                          UInt                 uiSearchRange,
                                          const PW*             pcPW,
                                          MEBiSearchParameters* pcBSP )
{
  const LumaIdx    cIdx                 = B4x4Idx(uiBlk);
  IntYuvMbBuffer*  pcWeightedYuvBuffer  = NULL;
  IntYuvPicBuffer* pcRefPelData[2];
  IntYuvMbBuffer   cWeightedYuvBuffer;

  pcRefPelData[0] = const_cast<IntFrame&>(rcRefFrame).getFullPelYuvBuffer();
  pcRefPelData[1] = const_cast<IntFrame&>(rcRefFrame).getHalfPelYuvBuffer();

  m_pcXDistortion->set4x4Block( cIdx );
  pcRefPelData[0]->set4x4Block( cIdx );
  pcRefPelData[1]->set4x4Block( cIdx );

  if( bQPelRefinementOnly ) rcMv = rcMvPred;

  UInt   uiMinSAD  = MSYS_UINT_MAX;
  Mv     cMv       = rcMv;
  Double fWeight   = 1.0;
  Double afCW[2]   = { 1.0, 1.0 };

  Icp    cIcp      = rcIcp;

  Bool      bOriginalSearchModeIsYUVSAD  = ( m_cParams.getFullPelDFunc() == DF_YUV_SAD );
  const Int iXSize                       = m_pcXDistortion->getBlockWidth  ( uiMode ); 
  const Int iYSize                       = m_pcXDistortion->getBlockHeight ( uiMode ); 

  if( pcBSP ) // bi prediction
  {
    ROF( pcBSP->pcAltRefPelData    );
    ROF( pcBSP->pcAltRefFrame      );
    ROF( pcBSP->apcWeight[LIST_0]  );
    ROF( pcBSP->apcWeight[LIST_1]  );

    pcWeightedYuvBuffer               = &cWeightedYuvBuffer;
    pcWeightedYuvBuffer   ->set4x4Block( cIdx );
    pcBSP->pcAltRefPelData->set4x4Block( cIdx );

    if( rcMbDataAccess.getSH().getPPS().getWeightedBiPredIdc() == 2 ) // implicit weighting
    {
      //----- get implicit weights -----
      PW              acIPW[2];
      const IntFrame* pcFrameL0 = ( pcBSP->uiL1Search ? pcBSP->pcAltRefFrame : &rcRefFrame          );
      const IntFrame* pcFrameL1 = ( pcBSP->uiL1Search ? &rcRefFrame          : pcBSP->pcAltRefFrame );
      Int             iScale    = rcMbDataAccess.getSH().getDistScaleFactorWP( pcFrameL0, pcFrameL1 );

      //----- weighting -----
      if( iScale == 128 ) // same distance -> use normal function for same result
      {
        m_pcSampleWeighting->inverseLumaSamples         ( pcWeightedYuvBuffer,
                                                          m_pcXDistortion->getYuvMbBuffer(),
                                                          pcBSP->pcAltRefPelData,
                                                          iYSize, iXSize );
        fWeight             = 0.5;
      }
      else
      {
        acIPW[1].scaleL1Weight( iScale   );
        acIPW[0].scaleL0Weight( acIPW[1] );
        m_pcSampleWeighting->weightInverseLumaSamples   ( pcWeightedYuvBuffer,
                                                          m_pcXDistortion->getYuvMbBuffer(),
                                                          pcBSP->pcAltRefPelData,
                                                          &acIPW[pcBSP->uiL1Search],
                                                          &acIPW[1-pcBSP->uiL1Search],
                                                          fWeight, iYSize, iXSize );
      }
    }
    else if( pcBSP->apcWeight[LIST_0]->getLumaWeightFlag() || 
             pcBSP->apcWeight[LIST_1]->getLumaWeightFlag()   )
    {
      //----- explicit weighting -----
      m_pcSampleWeighting->weightInverseLumaSamples     ( pcWeightedYuvBuffer,
                                                          m_pcXDistortion->getYuvMbBuffer(),
                                                          pcBSP->pcAltRefPelData,
                                                          pcBSP->apcWeight[pcBSP->uiL1Search],
                                                          pcBSP->apcWeight[1-pcBSP->uiL1Search],
                                                          fWeight, iYSize, iXSize );
    }
    else
    {
      //----- standard weighting -----
      m_pcSampleWeighting->inverseLumaSamples    ( pcWeightedYuvBuffer,
                                                  m_pcXDistortion->getYuvMbBuffer(),
                                                  pcBSP->pcAltRefPelData,
                                                  iYSize, iXSize );
      fWeight   = 0.5;
    }
  }
  else // unidirectional prediction
  {
    ROF( pcPW );

    if( pcPW->getLumaWeightFlag() || ( bOriginalSearchModeIsYUVSAD && pcPW->getChromaWeightFlag() ) )
    {
      pcWeightedYuvBuffer = &cWeightedYuvBuffer;
      pcWeightedYuvBuffer ->set4x4Block( cIdx );

      //----- weighting -----
      m_pcSampleWeighting->weightInverseLumaSamples   ( pcWeightedYuvBuffer,
                                                        m_pcXDistortion->getYuvMbBuffer(),
                                                        pcPW, fWeight, iYSize, iXSize );
      if( bOriginalSearchModeIsYUVSAD )
      {
        m_pcSampleWeighting->weightInverseChromaSamples( pcWeightedYuvBuffer,
                                                         m_pcXDistortion->getYuvMbBuffer(),
                                                         pcPW, afCW, iYSize, iXSize );
      }
    }
    else
    {
      //----- no weighting -----
      pcWeightedYuvBuffer = m_pcXDistortion->getYuvMbBuffer();
      fWeight = afCW[0] = afCW[1] = 1.0;
    }
  }

  //===== FULL-PEL ESTIMATION ======
  if( bOriginalSearchModeIsYUVSAD && ( pcBSP /* bi-prediction */ || fWeight != afCW[0] || fWeight != afCW[1] /* different component weights */ ) )
  {
    m_cParams.setFullPelDFunc( DF_SAD ); // set to normal SAD
  }
  // <<< heiko.schwarz@hhi.fhg.de (fix for uninitialized memory with YUV_SAD and bi-directional search)
  xGetMotionCost( ( 1 != m_cParams.getFullPelDFunc() ), 0 );
  m_pcXDistortion->getDistStruct( uiMode, m_cParams.getFullPelDFunc(), false, m_cXDSS );
  m_cXDSS.pYOrg = pcWeightedYuvBuffer->getLumBlk();
  m_cXDSS.pUOrg = pcWeightedYuvBuffer->getCbBlk ();
  m_cXDSS.pVOrg = pcWeightedYuvBuffer->getCrBlk ();
  xSetPredictor( rcMvPred );
  xSetCostScale( 2 );

  if( ! bQPelRefinementOnly )
  {
    if( uiSearchRange )
    {
      xPelBlockSearch     ( cIcp, pcRefPelData[0], cMv, uiMinSAD, uiSearchRange );
    }
    else
    {
      switch( m_cParams.getSearchMode() )
      {
      case 0:
        {
          xPelBlockSearch ( pcRefPelData[0], cMv, uiMinSAD );
        }
        break;
      case 1:
        {
          xPelSpiralSearch( pcRefPelData[0], cMv, uiMinSAD );
        }
        break;
      case 2:
        {
          xPelLogSearch   ( pcRefPelData[0], cMv, uiMinSAD, false, m_iMaxLogStep << ((NULL == pcBSP) ? 1 : 0) );
        }
        break;
      case 3:
        {
          rcMbDataAccess.getMvPredictors( m_acMvPredictors );
          xPelLogSearch   ( pcRefPelData[0], cMv, uiMinSAD, true, (NULL == pcBSP) ? 2 : 1 );
        }
        break;
      case 4:
        {
          rcMbDataAccess.getMvPredictors( m_acMvPredictors );
          xTZSearch( cIcp, pcRefPelData[0], cMv, uiMinSAD );
        }
        break;
      default:
        ROT(1);
        break;
      }
    }
    cMv <<= 2;
  }
  else
  {
    Mv cMvBase = cMv;
    cMv.limitComponents( m_cMin, m_cMax );
    if( ! ( cMvBase == cMv ) )
    {
      // don't refine in that case
      rcMv     = cMvBase;
      ruiBits += 2;
      ruiCost  = MSYS_UINT_MAX / 2;
      // >>>> bug fix by H.Schwarz 19/9/05
      if( bOriginalSearchModeIsYUVSAD )
      {
        m_cParams.setFullPelDFunc( DF_YUV_SAD );
      }
      // <<<< bug fix by H.Schwarz 19/9/05
      return Err::m_nOK;
    }
  }
  // heiko.schwarz@hhi.fhg.de (fix for uninitialized memory with YUV_SAD and bi-directional search) >>>>
  if( bOriginalSearchModeIsYUVSAD )
  {
    m_cParams.setFullPelDFunc( DF_YUV_SAD );
  }
  // <<< heiko.schwarz@hhi.fhg.de (fix for uninitialized memory with YUV_SAD and bi-directional search)


  //===== SUB-PEL ESTIMATION =====
  xGetMotionCost( 1 != ( 1 & m_cParams.getSubPelDFunc() ), 0 );
  m_pcXDistortion->getDistStruct( uiMode, m_cParams.getSubPelDFunc(), false, m_cXDSS );
  m_cXDSS.pYOrg = pcWeightedYuvBuffer->getLumBlk();
  xSetCostScale( 0 );

  xSubPelSearch( cIcp, pcRefPelData[1], cMv, uiMinSAD, uiBlk, uiMode, bQPelRefinementOnly );

  Short sHor      = cMv.getHor();
  Short sVer      = cMv.getVer();
  UInt  uiMvBits  = xGetBits( sHor, sVer );
  ruiBits        += uiMvBits;
  ruiCost         = (UInt)floor( fWeight * (Double)( uiMinSAD - xGetCost( uiMvBits ) ) ) + xGetCost( ruiBits );
  rcMv            = cMv;

  rcIcp           = cIcp;

  return Err::m_nOK;
}
#endif





ErrVal MotionEstimation::initMb( UInt uiMbPosY, UInt uiMbPosX, MbDataAccess& rcMbDataAccess )
{
  RNOK( MotionCompensation::initMb( uiMbPosY, uiMbPosX) );

  return Err::m_nOK;
}





Void MotionEstimation::xPelBlockSearch( IntYuvPicBuffer *pcPelData, Mv& rcMv, UInt& ruiSAD, UInt uiSearchRange )
{
  if( ! uiSearchRange )
  {
    uiSearchRange = m_cParams.getSearchRange();
  }

  Int     iYStride   = pcPelData->getLStride();
  XPel*   pucYRef    = pcPelData->getLumBlk ();
  XPel*   pucYSearch;
  Int     iCStride   = pcPelData->getCStride();
  XPel*   pucURef    = pcPelData->getCbBlk  ();
  XPel*   pucVRef    = pcPelData->getCrBlk  ();
  UInt    uiSad;

  Int y = 0;
  Int x = 0;

  m_cXDSS.iYStride = iYStride;
  m_cXDSS.iCStride = iCStride;

  ruiSAD = MSYS_UINT_MAX;
  rcMv.limitComponents( m_cMin, m_cMax );
  rcMv >>= 2;

  SearchRect cSearchRect;
  cSearchRect.init( uiSearchRange, rcMv, m_cMin, m_cMax );

  pucYSearch  = pucYRef - iYStride * (cSearchRect.iNegVerLimit);

  for(  y = -cSearchRect.iNegVerLimit; y <= cSearchRect.iPosVerLimit; y++ )
  {
    for( x = -cSearchRect.iNegHorLimit; x <= cSearchRect.iPosHorLimit; x++ )
    {
			//JVT-W080 BUG_FIX
			if( OmitPDISearch( x, y+rcMv.getVer(),false ) )
				continue;
			//~JVT-W080 BUG_FIX
      m_cXDSS.pYSearch  = pucYSearch + x;
      m_cXDSS.pUSearch  = pucURef + (y>>1)*iCStride + (x>>1);
      m_cXDSS.pVSearch  = pucVRef + (y>>1)*iCStride + (x>>1);

      uiSad  = m_cXDSS.Func( &m_cXDSS );
      uiSad += xGetCost( x, y);

      if( ruiSAD > uiSad )
      {
        ruiSAD = uiSad;
        rcMv.setVer( y );
        rcMv.setHor( x );
      }
    }
    pucYSearch += iYStride;
  }


  y = rcMv.getVer();
  x = rcMv.getHor();

  ruiSAD -= xGetCost( x, y);

  DO_DBG( m_cXDSS.pYSearch = pucYRef +  y     * iYStride +  x     );
  DO_DBG( m_cXDSS.pUSearch = pucURef + (y>>1) * iCStride + (x>>1) );
  DO_DBG( m_cXDSS.pVSearch = pucVRef + (y>>1) * iCStride + (x>>1) );
  uiSad  = m_cXDSS.Func( &m_cXDSS );
  AOF_DBG( ruiSAD == ( uiSad  = m_cXDSS.Func( &m_cXDSS ) ) );
}

//JVT-W080 BUG_FIX
Bool MotionEstimation::OmitPDISearch( Int x, Int y, Bool bQPel ) // x, y: motion vector corresponding to pel/sub-pel
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -