Skip to content
Snippets Groups Projects
EncModeCtrl.cpp 70.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
        if( !bestCS || ( bestCS && isModeSplit( bestMode ) ) )
        {
          return false;
        }
        else
        {
    #if REUSE_CU_RESULTS
          setFromCs( *bestCS, partitioner );
    
    #endif
          // assume the non-split modes are done and set the marks for the best found mode
          if( bestCS && bestCU )
          {
            if( CU::isInter( *bestCU ) )
            {
              relatedCU.isInter   = true;
    #if HM_CODED_CU_INFO
              relatedCU.isSkip   |= bestCU->skip;
    
              relatedCU.isMMVDSkip |= bestCU->mmvdSkip;
    
    #endif
              relatedCU.GBiIdx    = bestCU->GBiIdx;
    
    Yu Han's avatar
    Yu Han committed
    #if JVET_M0483_IBC
    
    Yu Han's avatar
    Yu Han committed
            else if (CU::isIBC(*bestCU))
            {
              relatedCU.isIBC = true;
    #if HM_CODED_CU_INFO
              relatedCU.isSkip |= bestCU->skip;
    #endif
            }
    #endif
    
            else if( CU::isIntra( *bestCU ) )
            {
              relatedCU.isIntra   = true;
            }
    #if ENABLE_SPLIT_PARALLELISM
    
    #if REUSE_CU_RESULTS
            BestEncInfoCache::touch(partitioner.currArea());
    #endif
            CacheBlkInfoCtrl::touch(partitioner.currArea());
    
    #endif
            cuECtx.set( IS_BEST_NOSPLIT_SKIP, bestCU->skip );
          }
        }
    
        return false;
      }
    }
    
    bool EncModeCtrlMTnoRQT::useModeResult( const EncTestMode& encTestmode, CodingStructure*& tempCS, Partitioner& partitioner )
    {
      xExtractFeatures( encTestmode, *tempCS );
    
      ComprCUCtx& cuECtx = m_ComprCUCtxList.back();
    
    
      if(      encTestmode.type == ETM_SPLIT_BT_H )
      {
        cuECtx.set( BEST_HORZ_SPLIT_COST, tempCS->cost );
      }
      else if( encTestmode.type == ETM_SPLIT_BT_V )
      {
        cuECtx.set( BEST_VERT_SPLIT_COST, tempCS->cost );
      }
      else if( encTestmode.type == ETM_SPLIT_TT_H )
      {
        cuECtx.set( BEST_TRIH_SPLIT_COST, tempCS->cost );
      }
      else if( encTestmode.type == ETM_SPLIT_TT_V )
      {
        cuECtx.set( BEST_TRIV_SPLIT_COST, tempCS->cost );
      }
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #if !JVET_M0464_UNI_MTS
    
    Karsten Suehring's avatar
    Karsten Suehring committed
      else if( encTestmode.type == ETM_INTRA )
    
      {
        const CodingUnit cu = *tempCS->getCU( partitioner.chType );
    
        if( !cu.emtFlag )
        {
          cuECtx.bestEmtSize2Nx2N1stPass = tempCS->cost;
        }
    
    #if JVET_M0102_INTRA_SUBPARTITIONS
        if (!cu.ispMode)
        {
          cuECtx.bestCostEmtFirstPassNoIsp = tempCS->cost;
        }
    #endif
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #endif
    
    
      if( m_pcEncCfg->getIMV4PelFast() && m_pcEncCfg->getIMV() && encTestmode.type == ETM_INTER_ME )
      {
        int imvMode = ( encTestmode.opts & ETO_IMV ) >> ETO_IMV_SHIFT;
    
        if( imvMode == 1 )
        {
          if( tempCS->cost < cuECtx.get<double>( BEST_IMV_COST ) )
          {
            cuECtx.set( BEST_IMV_COST, tempCS->cost );
          }
        }
        else if( imvMode == 0 )
        {
          if( tempCS->cost < cuECtx.get<double>( BEST_NO_IMV_COST ) )
          {
            cuECtx.set( BEST_NO_IMV_COST, tempCS->cost );
          }
        }
      }
    
      if( encTestmode.type == ETM_SPLIT_QT )
      {
        int maxQtD = 0;
        for( const auto& cu : tempCS->cus )
        {
          maxQtD = std::max<int>( maxQtD, cu->qtDepth );
        }
        cuECtx.set( MAX_QT_SUB_DEPTH, maxQtD );
      }
    
    
      int maxMtD = tempCS->pcv->getMaxBtDepth( *tempCS->slice, partitioner.chType ) + partitioner.currImplicitBtDepth;
    
      if( encTestmode.type == ETM_SPLIT_BT_H )
      {
        if( tempCS->cus.size() > 2 )
    
          int h_2   = tempCS->area.blocks[partitioner.chType].height / 2;
          int cu1_h = tempCS->cus.front()->blocks[partitioner.chType].height;
          int cu2_h = tempCS->cus.back() ->blocks[partitioner.chType].height;
    
          cuECtx.set( DO_TRIH_SPLIT, cu1_h < h_2 || cu2_h < h_2 || partitioner.currMtDepth + 1 == maxMtD );
    
      }
      else if( encTestmode.type == ETM_SPLIT_BT_V )
      {
        if( tempCS->cus.size() > 2 )
    
          int w_2   = tempCS->area.blocks[partitioner.chType].width / 2;
          int cu1_w = tempCS->cus.front()->blocks[partitioner.chType].width;
          int cu2_w = tempCS->cus.back() ->blocks[partitioner.chType].width;
    
          cuECtx.set( DO_TRIV_SPLIT, cu1_w < w_2 || cu2_w < w_2 || partitioner.currMtDepth + 1 == maxMtD );
    
        }
      }
    
      // for now just a simple decision based on RD-cost or choose tempCS if bestCS is not yet coded
    
    Nan Hu's avatar
    Nan Hu committed
    #if JVET_M0428_ENC_DB_OPT
    
    #if JVET_M0445_MCTS
      if( tempCS->features[ENC_FT_RD_COST] != MAX_DOUBLE && ( !cuECtx.bestCS || ( ( tempCS->features[ENC_FT_RD_COST] + ( tempCS->useDbCost ? tempCS->costDbOffset : 0 ) ) < ( cuECtx.bestCS->features[ENC_FT_RD_COST] + ( tempCS->useDbCost ? cuECtx.bestCS->costDbOffset : 0 ) ) ) ) )
    #else
    
    Nan Hu's avatar
    Nan Hu committed
      if( !cuECtx.bestCS || ( ( tempCS->features[ENC_FT_RD_COST] + ( tempCS->useDbCost ? tempCS->costDbOffset : 0 ) ) < ( cuECtx.bestCS->features[ENC_FT_RD_COST] + ( tempCS->useDbCost ? cuECtx.bestCS->costDbOffset : 0 ) ) ) )
    
    #endif
    #else
    #if JVET_M0445_MCTS
      if( tempCS->features[ENC_FT_RD_COST] != MAX_DOUBLE && ( !cuECtx.bestCS || tempCS->features[ENC_FT_RD_COST] < cuECtx.bestCS->features[ENC_FT_RD_COST] ) )
    
    Nan Hu's avatar
    Nan Hu committed
    #else
    
      if( !cuECtx.bestCS || tempCS->features[ENC_FT_RD_COST] < cuECtx.bestCS->features[ENC_FT_RD_COST] )
    
    Nan Hu's avatar
    Nan Hu committed
    #endif
    
      {
        cuECtx.bestCS = tempCS;
        cuECtx.bestCU = tempCS->cus[0];
        cuECtx.bestTU = cuECtx.bestCU->firstTU;
    
        if( isModeInter( encTestmode ) )
        {
          //Here we take the best cost of both inter modes. We are assuming only the inter modes (and all of them) have come before the intra modes!!!
          cuECtx.bestInterCost = cuECtx.bestCS->cost;
        }
    
        return true;
      }
      else
      {
        return false;
      }
    }
    
    #if ENABLE_SPLIT_PARALLELISM
    void EncModeCtrlMTnoRQT::copyState( const EncModeCtrl& other, const UnitArea& area )
    {
      const EncModeCtrlMTnoRQT* pOther = dynamic_cast<const EncModeCtrlMTnoRQT*>( &other );
    
      CHECK( !pOther, "Trying to copy state from a different type of controller" );
    
      this->EncModeCtrl        ::copyState( *pOther, area );
      this->CacheBlkInfoCtrl   ::copyState( *pOther, area );
    
    #if REUSE_CU_RESULTS
      this->BestEncInfoCache   ::copyState( *pOther, area );
    #endif
    
    #if JVET_M0140_SBT
    
      this->SaveLoadEncInfoSbt ::copyState( *pOther );
    
    
      m_skipThreshold = pOther->m_skipThreshold;
    }
    
    int EncModeCtrlMTnoRQT::getNumParallelJobs( const CodingStructure &cs, Partitioner& partitioner ) const
    {
    
      int numJobs = 0;
    
      if(      partitioner.canSplit( CU_TRIH_SPLIT, cs ) )
    
        numJobs = 6;
    
      else if( partitioner.canSplit( CU_TRIV_SPLIT, cs ) )
    
        numJobs = 5;
    
      else if( partitioner.canSplit( CU_HORZ_SPLIT, cs ) )
    
      else if (partitioner.canSplit(CU_VERT_SPLIT, cs))
    
        numJobs = 3;
    
      else if( partitioner.canSplit( CU_QUAD_SPLIT, cs ) )
    
        numJobs = 2;
      }
      else if( partitioner.canSplit( CU_DONT_SPLIT, cs ) )
      {
        numJobs = 1;
    
      }
    
      CHECK( numJobs >= NUM_RESERVERD_SPLIT_JOBS, "More jobs specified than allowed" );
    
      return numJobs;
    }
    
    bool EncModeCtrlMTnoRQT::isParallelSplit( const CodingStructure &cs, Partitioner& partitioner ) const
    {
      if( partitioner.getImplicitSplit( cs ) != CU_DONT_SPLIT || cs.picture->scheduler.getSplitJobId() != 0 ) return false;
    
    #if JVET_M0113_M0188_QG_SIZE
      if( cs.pps->getUseDQP() && partitioner.currQgEnable() ) return false;
    #else
      if( cs.pps->getUseDQP() && partitioner.currDepth <= cs.pps->getMaxCuDQPDepth() ) return false;
    #endif
    
      const int numJobs = getNumParallelJobs( cs, partitioner );
      const int numPxl  = partitioner.currArea().Y().area();
      const int parlAt  = m_pcEncCfg->getNumSplitThreads() <= 3 ? 1024 : 256;
      if(  cs.slice->isIntra() && numJobs > 2 && ( numPxl == parlAt || !partitioner.canSplit( CU_QUAD_SPLIT, cs ) ) ) return true;
      if( !cs.slice->isIntra() && numJobs > 1 && ( numPxl == parlAt || !partitioner.canSplit( CU_QUAD_SPLIT, cs ) ) ) return true;
    
    }
    
    bool EncModeCtrlMTnoRQT::parallelJobSelector( const EncTestMode& encTestmode, const CodingStructure &cs, Partitioner& partitioner ) const
    {
      // Job descriptors
      //  - 1: all non-split modes
      //  - 2: QT-split
      //  - 3: all vertical modes but TT_V
      //  - 4: all horizontal modes but TT_H
      //  - 5: TT_V
      //  - 6: TT_H
      switch( cs.picture->scheduler.getSplitJobId() )
      {
      case 1:
        // be sure to execute post dont split
        return !isModeSplit( encTestmode );
        break;
      case 2:
        return encTestmode.type == ETM_SPLIT_QT;
        break;
      case 3:
    
        return encTestmode.type == ETM_SPLIT_BT_V;
    
        return encTestmode.type == ETM_SPLIT_BT_H;
    
        break;
      case 5:
        return encTestmode.type == ETM_SPLIT_TT_V;
        break;
      case 6:
        return encTestmode.type == ETM_SPLIT_TT_H;
        break;
      default:
        THROW( "Unknown job-ID for parallelization of EncModeCtrlMTnoRQT: " << cs.picture->scheduler.getSplitJobId() );
        break;
      }
    }
    
    #endif