Skip to content
Snippets Groups Projects
EncModeCtrl.cpp 68.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
        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 );
    
      m_skipThreshold = pOther->m_skipThreshold;
    }
    
    int EncModeCtrlMTnoRQT::getNumParallelJobs( const CodingStructure &cs, Partitioner& partitioner ) const
    {
      int numJobs = 1; // for no-split coding
    
      if( partitioner.canSplit( CU_QUAD_SPLIT, cs ) )
      {
        numJobs = 2;
      }
    
      if( partitioner.canSplit( CU_VERT_SPLIT, cs ) )
      {
        numJobs = 3;
      }
    
      if( partitioner.canSplit( CU_HORZ_SPLIT, cs ) )
      {
        numJobs = 4;
      }
    
      if( partitioner.canSplit( CU_TRIV_SPLIT, cs ) )
      {
        numJobs = 5;
      }
    
      if( partitioner.canSplit( CU_TRIH_SPLIT, cs ) )
      {
        numJobs = 6;
      }
    
      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;
      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;
      return false;
    }
    
    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:
        switch( encTestmode.type )
        {
        case ETM_SPLIT_BT_V:
          return true;
          break;
        default:
          return false;
          break;
        }
        break;
      case 4:
        switch( encTestmode.type )
        {
        case ETM_SPLIT_BT_H:
          return true;
          break;
        default:
          return false;
          break;
        }
        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