Skip to content
Snippets Groups Projects
EncCu.cpp 72.9 KiB
Newer Older
  • Learn to ignore specific revisions
  •     tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
        continue;
      }
      CHECK(!(testGbi || (!testGbi && gbiIdx == GBI_DEFAULT)), " !( bTestGbi || (!bTestGbi && gbiIdx == GBI_DEFAULT ) )");
    
      bool isEqualUni = false;
      if( m_pcEncCfg->getUseGBiFast() )
      {
        if( cu.firstPU->interDir != 3 && testGbi == 0 )
        {
          isEqualUni = true;
        }
      }
    #endif
    
      if( !CU::hasSubCUNonZeroMVd( cu ) )
      {
        m_modeCtrl->useModeResult( encTestModeBase, tempCS, partitioner );
        return false;
      }
    
    
      xEncodeInterResidual( tempCS, bestCS, partitioner, encTestModeBase, 0
        , NULL
        , true
        , 0
    
    #if JVET_L0646_GBI
        , &equGBiCost
    #endif
    
    #if JVET_L0646_GBI
      tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
    
      double skipTH = MAX_DOUBLE;
      skipTH = (m_pcEncCfg->getUseGBiFast() ? 1.05 : MAX_DOUBLE);
      if( equGBiCost > curBestCost * skipTH )
      {
        break;
      }
    
      if( m_pcEncCfg->getUseGBiFast() )
      {
        if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 )
        {
          break;
        }
      }
      if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT && xIsGBiSkip(cu) && m_pcEncCfg->getUseGBiFast() )
      {
        break;
      }
     } // for( UChar gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
    #endif
    
    
    void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, int residualPass
      , CodingStructure* imvCS
      , int emtMode
      , bool* bestHasNonResi
    
    #if JVET_L0646_GBI
      , double* equGBiCost
    #endif
    
    {
      if( residualPass == 1 && encTestMode.lossless )
      {
        return;
      }
    
      CodingUnit*            cu        = tempCS->getCU( partitioner.chType );
      double   bestCostInternal        = MAX_DOUBLE;
    
      double           bestCost        = bestCS->cost;
      const SPS&            sps        = *tempCS->sps;
      const int      maxSizeEMT        = tempCS->pcv->noRQT ? EMT_INTER_MAX_CU_WITH_QTBT : EMT_INTER_MAX_CU;
      bool              swapped        = false; // avoid unwanted data copy
      bool             reloadCU        = false;
      const bool considerEmtSecondPass = emtMode && sps.getSpsNext().getUseInterEMT() && partitioner.currArea().lwidth() <= maxSizeEMT && partitioner.currArea().lheight() <= maxSizeEMT;
    
      int minEMTMode = 0;
      int maxEMTMode = (considerEmtSecondPass?1:0);
    
      if( emtMode == 2 )
      {
        minEMTMode = maxEMTMode = (cu->emtFlag?1:0);
      }
    
      for( int curEmtMode = minEMTMode; curEmtMode <= maxEMTMode; curEmtMode++ )
    
        if( reloadCU )
        {
          if( bestCost == bestCS->cost ) //The first EMT pass didn't become the bestCS, so we clear the TUs generated
          {
            tempCS->clearTUs();
          }
          else if( false == swapped )
          {
            tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
            tempCS->copyStructure( *bestCS, partitioner.chType );
            tempCS->getPredBuf().copyFrom( bestCS->getPredBuf() );
            bestCost = bestCS->cost;
            cu       = tempCS->getCU( partitioner.chType );
            swapped = true;
          }
          else
          {
            tempCS->clearTUs();
            bestCost = bestCS->cost;
            cu       = tempCS->getCU( partitioner.chType );
          }
    
          //we need to restart the distortion for the new tempCS, the bit count and the cost
          tempCS->dist     = 0;
          tempCS->fracBits = 0;
          tempCS->cost     = MAX_DOUBLE;
        }
    
        reloadCU    = true; // enable cu reloading
    
    
        const bool skipResidual = residualPass == 1;
        m_pcInterSearch->encodeResAndCalcRdInterCU( *tempCS, partitioner, skipResidual );
    
        xEncodeDontSplit( *tempCS, partitioner );
    
        xCheckDQP( *tempCS, partitioner );
    
    
    #if JVET_L0646_GBI
        if( ETM_INTER_ME == encTestMode.type )
        {
          if( equGBiCost != NULL )
          {
            if( tempCS->cost < (*equGBiCost) && cu->GBiIdx == GBI_DEFAULT )
            {
              (*equGBiCost) = tempCS->cost;
            }
          }
          else
          {
            CHECK(equGBiCost == NULL, "equGBiCost == NULL");
          }
          if( tempCS->slice->getCheckLDC() && !cu->imv && cu->GBiIdx != GBI_DEFAULT && tempCS->cost < m_bestGbiCost[1] )
          {
            if( tempCS->cost < m_bestGbiCost[0] )
            {
              m_bestGbiCost[1] = m_bestGbiCost[0];
              m_bestGbiCost[0] = tempCS->cost;
              m_bestGbiIdx[1] = m_bestGbiIdx[0];
              m_bestGbiIdx[0] = cu->GBiIdx;
            }
            else
            {
              m_bestGbiCost[1] = tempCS->cost;
              m_bestGbiIdx[1] = cu->GBiIdx;
            }
          }
        }
    #endif
    
    
        double emtFirstPassCost = tempCS->cost;
    
        if( imvCS && (tempCS->cost < imvCS->cost) )
        {
          if( imvCS->cost != MAX_DOUBLE )
          {
            imvCS->initStructData( encTestMode.qp, encTestMode.lossless );
          }
          imvCS->copyStructure( *tempCS, partitioner.chType );
        }
        if( NULL != bestHasNonResi && (bestCostInternal > tempCS->cost) )
        {
          bestCostInternal = tempCS->cost;
          *bestHasNonResi  = !cu->rootCbf;
        }
    
    #if WCG_EXT
        DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda( true ) );
    #else
        DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda() );
    #endif
        xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
    
    
        //now we check whether the second pass should be skipped or not
        if( !curEmtMode && maxEMTMode )
        {
          const double thresholdToSkipEmtSecondPass = 1.1; // Skip checking EMT transforms
          const bool bCond1 = !cu->firstTU->cbf[COMPONENT_Y];
    
          const bool bCond3 = emtFirstPassCost > ( bestCost * thresholdToSkipEmtSecondPass );
    
          if( m_pcEncCfg->getFastInterEMT() && (bCond1 || bCond3 ) ) 
          {
            maxEMTMode = 0; // do not test EMT
          }
        }
      } //end emt loop
    
    }
    
    
    void EncCu::xEncodeDontSplit( CodingStructure &cs, Partitioner &partitioner )
    {
      m_CABACEstimator->resetBits();
    
      {
        if( partitioner.canSplit( CU_QUAD_SPLIT, cs ) )
        {
          m_CABACEstimator->split_cu_flag( false, cs, partitioner );
        }
        if( partitioner.canSplit( CU_MT_SPLIT, cs ) )
        {
          m_CABACEstimator->split_cu_mode_mt( CU_DONT_SPLIT, cs, partitioner );
        }
      }
    
      cs.fracBits += m_CABACEstimator->getEstFracBits(); // split bits
      cs.cost      = m_pcRdCost->calcRdCost( cs.fracBits, cs.dist );
    
    }
    
    #if REUSE_CU_RESULTS
    void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner )
    {
      const SPS &sps = *tempCS->sps;
    
      BestEncInfoCache* bestEncCache = dynamic_cast<BestEncInfoCache*>( m_modeCtrl );
      CHECK( !bestEncCache, "If this mode is chosen, mode controller has to implement the mode caching capabilities" );
      EncTestMode cachedMode;
    
      if( bestEncCache->setCsFrom( *tempCS, cachedMode, partitioner ) )
      {
        CodingUnit& cu = *tempCS->cus.front();
        partitioner.setCUData( cu );
    
        if( CU::isIntra( cu ) )
        {
          xReconIntraQT( cu );
        }
        else
        {
          xDeriveCUMV( cu );
          xReconInter( cu );
        }
    
        Distortion finalDistortion = 0;
        const int  numValidComponents = getNumberValidComponents( tempCS->area.chromaFormat );
    
        for( int comp = 0; comp < numValidComponents; comp++ )
        {
          const ComponentID compID = ComponentID( comp );
    
          if( CS::isDualITree( *tempCS ) && toChannelType( compID ) != partitioner.chType )
          {
            continue;
          }
    
          CPelBuf reco = tempCS->getRecoBuf( compID );
          CPelBuf org  = tempCS->getOrgBuf ( compID );
    
    #if WCG_EXT
          if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
          {
            const CPelBuf orgLuma = tempCS->getOrgBuf(tempCS->area.blocks[COMPONENT_Y]);
            finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
          }
          else
    #endif
          finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
        }
    
        m_CABACEstimator->getCtx() = m_CurrCtx->start;
        m_CABACEstimator->resetBits();
    
        CUCtx cuCtx;
        cuCtx.isDQPCoded = true;
        cuCtx.isChromaQpAdjCoded = true;
        m_CABACEstimator->coding_unit( cu, partitioner, cuCtx );
    
        tempCS->dist     = finalDistortion;
        tempCS->fracBits = m_CABACEstimator->getEstFracBits();
        tempCS->cost     = m_pcRdCost->calcRdCost( tempCS->fracBits, tempCS->dist );
    
        xEncodeDontSplit( *tempCS,         partitioner );
        xCheckDQP       ( *tempCS,         partitioner );
        xCheckBestMode  (  tempCS, bestCS, partitioner, cachedMode );
      }
      else
      {
        THROW( "Should never happen!" );
      }
    }
    
    #endif