Skip to content
Snippets Groups Projects
UnitTools.cpp 140 KiB
Newer Older
  • Learn to ignore specific revisions
  • rlliao's avatar
    rlliao committed
      int32_t idxH  = (int32_t)(g_aucLog2[pu.lheight()] - MIN_CU_LOG2);
    
      for( int32_t y = 0; y < mb.height; y++ )
      {
        for( int32_t x = 0; x < mb.width; x++ )
        {
    
    rlliao's avatar
    rlliao committed
          if( g_triangleMvStorage[splitDir][idxH][idxW][y][x] == 2 )
    
          {
            mb.at( x, y ).isInter   = true;
    
    rlliao's avatar
    rlliao committed
            mb.at( x, y ).interDir  = biMv.interDir;
            mb.at( x, y ).refIdx[0] = biMv.refIdx[0];
            mb.at( x, y ).refIdx[1] = biMv.refIdx[1];
            mb.at( x, y ).mv    [0] = biMv.mv    [0];
            mb.at( x, y ).mv    [1] = biMv.mv    [1];
    
            mb.at( x, y ).sliceIdx  = biMv.sliceIdx;
    
    rlliao's avatar
    rlliao committed
          else if( g_triangleMvStorage[splitDir][idxH][idxW][y][x] == 0 )
    
          {
            mb.at( x, y ).isInter   = true;
    
    rlliao's avatar
    rlliao committed
            mb.at( x, y ).interDir  = triangleMrgCtx.interDirNeighbours[candIdx0];
            mb.at( x, y ).refIdx[0] = triangleMrgCtx.mvFieldNeighbours[ candIdx0 << 1     ].refIdx;
            mb.at( x, y ).refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
            mb.at( x, y ).mv    [0] = triangleMrgCtx.mvFieldNeighbours[ candIdx0 << 1     ].mv;
            mb.at( x, y ).mv    [1] = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
    
            mb.at( x, y ).sliceIdx  = biMv.sliceIdx;
    
    rlliao's avatar
    rlliao committed
            mb.at( x, y ).interDir  = triangleMrgCtx.interDirNeighbours[candIdx1];
            mb.at( x, y ).refIdx[0] = triangleMrgCtx.mvFieldNeighbours[ candIdx1 << 1     ].refIdx;
            mb.at( x, y ).refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx;
            mb.at( x, y ).mv    [0] = triangleMrgCtx.mvFieldNeighbours[ candIdx1 << 1     ].mv;
            mb.at( x, y ).mv    [1] = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
    
            mb.at( x, y ).sliceIdx  = biMv.sliceIdx;
    
          }
        }
      }
    }
    
    int32_t PU::mappingRefPic( const PredictionUnit &pu, int32_t refPicPoc, bool targetRefPicList )
    {
      int32_t numRefIdx = pu.cs->slice->getNumRefIdx( (RefPicList)targetRefPicList );
    
      for( int32_t i = 0; i < numRefIdx; i++ )
      {
        if( pu.cs->slice->getRefPOC( (RefPicList)targetRefPicList, i ) == refPicPoc )
        {
          return i;
        }
      }
      return -1;
    }
    
    
    void CU::resetMVDandMV2Int( CodingUnit& cu, InterPrediction *interPred )
    {
      for( auto &pu : CU::traversePUs( cu ) )
      {
        MergeCtx mrgCtx;
    
        if( !pu.mergeFlag )
        {
          if( pu.interDir != 2 /* PRED_L1 */ )
          {
            Mv mv        = pu.mv[0];
            Mv mvPred;
            AMVPInfo amvpInfo;
    
    Yu Han's avatar
    Yu Han committed
            if (CU::isIBC(*pu.cu))
    
    Yu Han's avatar
    Yu Han committed
              PU::fillIBCMvpCand(pu, amvpInfo);
    
    Yu Han's avatar
    Yu Han committed
            else
    
            PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[0], amvpInfo);
            pu.mvpNum[0] = amvpInfo.numCand;
    
            mvPred       = amvpInfo.mvCand[pu.mvpIdx[0]];
    
    Xiang Li's avatar
    Xiang Li committed
            mv.roundTransPrecInternal2Amvr(cu.imv);
    
            pu.mv[0]     = mv;
            Mv mvDiff    = mv - mvPred;
            pu.mvd[0]    = mvDiff;
          }
          if( pu.interDir != 1 /* PRED_L0 */ )
          {
            Mv mv        = pu.mv[1];
            Mv mvPred;
            AMVPInfo amvpInfo;
            PU::fillMvpCand(pu, REF_PIC_LIST_1, pu.refIdx[1], amvpInfo);
            pu.mvpNum[1] = amvpInfo.numCand;
    
            mvPred       = amvpInfo.mvCand[pu.mvpIdx[1]];
    
    Xiang Li's avatar
    Xiang Li committed
            mv.roundTransPrecInternal2Amvr(cu.imv);
    
            Mv mvDiff    = mv - mvPred;
    
            if( pu.cu->cs->slice->getMvdL1ZeroFlag() && pu.interDir == 3 /* PRED_BI */ )
            {
              pu.mvd[1] = Mv();
              mv = mvPred;
            }
            else
            {
              pu.mvd[1] = mvDiff;
            }
            pu.mv[1] = mv;
          }
    
        }
        else
        {
    
            PU::getInterMergeCandidates ( pu, mrgCtx
    
    
            mrgCtx.setMergeInfo( pu, pu.mergeIdx );
        }
    
        PU::spanMotionInfo( pu, mrgCtx );
      }
    }
    
    bool CU::hasSubCUNonZeroMVd( const CodingUnit& cu )
    {
      bool bNonZeroMvd = false;
    
      for( const auto &pu : CU::traversePUs( cu ) )
      {
        if( ( !pu.mergeFlag ) && ( !cu.skip ) )
        {
          if( pu.interDir != 2 /* PRED_L1 */ )
          {
            bNonZeroMvd |= pu.mvd[REF_PIC_LIST_0].getHor() != 0;
            bNonZeroMvd |= pu.mvd[REF_PIC_LIST_0].getVer() != 0;
          }
          if( pu.interDir != 1 /* PRED_L0 */ )
          {
            if( !pu.cu->cs->slice->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ )
            {
              bNonZeroMvd |= pu.mvd[REF_PIC_LIST_1].getHor() != 0;
              bNonZeroMvd |= pu.mvd[REF_PIC_LIST_1].getVer() != 0;
            }
          }
        }
      }
    
      return bNonZeroMvd;
    }
    
    
    bool CU::hasSubCUNonZeroAffineMVd( const CodingUnit& cu )
    {
      bool nonZeroAffineMvd = false;
    
      if ( !cu.affine || cu.firstPU->mergeFlag )
      {
        return false;
      }
    
      for ( const auto &pu : CU::traversePUs( cu ) )
      {
        if ( ( !pu.mergeFlag ) && ( !cu.skip ) )
        {
          if ( pu.interDir != 2 /* PRED_L1 */ )
          {
            for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
            {
              nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_0][i].getHor() != 0;
              nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_0][i].getVer() != 0;
            }
          }
    
          if ( pu.interDir != 1 /* PRED_L0 */ )
          {
            if ( !pu.cu->cs->slice->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ )
            {
              for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
              {
                nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_1][i].getHor() != 0;
                nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_1][i].getVer() != 0;
              }
            }
          }
        }
      }
    
      return nonZeroAffineMvd;
    }
    
    
    int CU::getMaxNeighboriMVCandNum( const CodingStructure& cs, const Position& pos )
    {
      const int  numDefault     = 0;
      int        maxImvNumCand  = 0;
    
      // Get BCBP of left PU
    
      const CodingUnit *cuLeft  = cs.getCURestricted( pos.offset( -1, 0 ), pos, cs.slice->getIndependentSliceIdx(), cs.picture->brickMap->getBrickIdxRsMap( pos ), CH_L );
    
      maxImvNumCand = ( cuLeft ) ? cuLeft->imvNumCand : numDefault;
    
      // Get BCBP of above PU
    
      const CodingUnit *cuAbove = cs.getCURestricted( pos.offset( 0, -1 ), pos, cs.slice->getIndependentSliceIdx(), cs.picture->brickMap->getBrickIdxRsMap( pos ), CH_L );
    
      maxImvNumCand = std::max( maxImvNumCand, ( cuAbove ) ? cuAbove->imvNumCand : numDefault );
    
      return maxImvNumCand;
    }
    
    
    uint8_t CU::getSbtInfo( uint8_t idx, uint8_t pos )
    {
      return ( pos << 4 ) + ( idx << 0 );
    }
    
    uint8_t CU::getSbtIdx( const uint8_t sbtInfo )
    {
      return ( sbtInfo >> 0 ) & 0xf;
    }
    
    uint8_t CU::getSbtPos( const uint8_t sbtInfo )
    {
      return ( sbtInfo >> 4 ) & 0x3;
    }
    
    uint8_t CU::getSbtMode( uint8_t sbtIdx, uint8_t sbtPos )
    {
      uint8_t sbtMode = 0;
      switch( sbtIdx )
      {
      case SBT_VER_HALF: sbtMode = sbtPos + SBT_VER_H0;  break;
      case SBT_HOR_HALF: sbtMode = sbtPos + SBT_HOR_H0;  break;
      case SBT_VER_QUAD: sbtMode = sbtPos + SBT_VER_Q0;  break;
      case SBT_HOR_QUAD: sbtMode = sbtPos + SBT_HOR_Q0;  break;
      default:           assert( 0 );
      }
    
      assert( sbtMode < NUMBER_SBT_MODE );
      return sbtMode;
    }
    
    uint8_t CU::getSbtIdxFromSbtMode( uint8_t sbtMode )
    {
      if( sbtMode <= SBT_VER_H1 )
        return SBT_VER_HALF;
      else if( sbtMode <= SBT_HOR_H1 )
        return SBT_HOR_HALF;
      else if( sbtMode <= SBT_VER_Q1 )
        return SBT_VER_QUAD;
      else if( sbtMode <= SBT_HOR_Q1 )
        return SBT_HOR_QUAD;
      else
      {
        assert( 0 );
        return 0;
      }
    }
    
    uint8_t CU::getSbtPosFromSbtMode( uint8_t sbtMode )
    {
      if( sbtMode <= SBT_VER_H1 )
        return sbtMode - SBT_VER_H0;
      else if( sbtMode <= SBT_HOR_H1 )
        return sbtMode - SBT_HOR_H0;
      else if( sbtMode <= SBT_VER_Q1 )
        return sbtMode - SBT_VER_Q0;
      else if( sbtMode <= SBT_HOR_Q1 )
        return sbtMode - SBT_HOR_Q0;
      else
      {
        assert( 0 );
        return 0;
      }
    }
    
    uint8_t CU::targetSbtAllowed( uint8_t sbtIdx, uint8_t sbtAllowed )
    {
      uint8_t val = 0;
      switch( sbtIdx )
      {
      case SBT_VER_HALF: val = ( ( sbtAllowed >> SBT_VER_HALF ) & 0x1 ); break;
      case SBT_HOR_HALF: val = ( ( sbtAllowed >> SBT_HOR_HALF ) & 0x1 ); break;
      case SBT_VER_QUAD: val = ( ( sbtAllowed >> SBT_VER_QUAD ) & 0x1 ); break;
      case SBT_HOR_QUAD: val = ( ( sbtAllowed >> SBT_HOR_QUAD ) & 0x1 ); break;
      default:           CHECK( 1, "unknown SBT type" );
      }
      return val;
    }
    
    uint8_t CU::numSbtModeRdo( uint8_t sbtAllowed )
    {
      uint8_t num = 0;
      uint8_t sum = 0;
      num = targetSbtAllowed( SBT_VER_HALF, sbtAllowed ) + targetSbtAllowed( SBT_HOR_HALF, sbtAllowed );
      sum += std::min( SBT_NUM_RDO, ( num << 1 ) );
      num = targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) + targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed );
      sum += std::min( SBT_NUM_RDO, ( num << 1 ) );
      return sum;
    }
    
    bool CU::isMtsMode( const uint8_t sbtInfo )
    {
      return getSbtIdx( sbtInfo ) == SBT_OFF_MTS;
    }
    
    bool CU::isSbtMode( const uint8_t sbtInfo )
    {
      uint8_t sbtIdx = getSbtIdx( sbtInfo );
      return sbtIdx >= SBT_VER_HALF && sbtIdx <= SBT_HOR_QUAD;
    }
    
    bool CU::isSameSbtSize( const uint8_t sbtInfo1, const uint8_t sbtInfo2 )
    {
      uint8_t sbtIdx1 = getSbtIdxFromSbtMode( sbtInfo1 );
      uint8_t sbtIdx2 = getSbtIdxFromSbtMode( sbtInfo2 );
      if( sbtIdx1 == SBT_HOR_HALF || sbtIdx1 == SBT_VER_HALF )
        return sbtIdx2 == SBT_HOR_HALF || sbtIdx2 == SBT_VER_HALF;
      else if( sbtIdx1 == SBT_HOR_QUAD || sbtIdx1 == SBT_VER_QUAD )
        return sbtIdx2 == SBT_HOR_QUAD || sbtIdx2 == SBT_VER_QUAD;
      else
        return false;
    }
    
    
    bool CU::isGBiIdxCoded( const CodingUnit &cu )
    {
    
      if( cu.cs->sps->getUseGBi() == false )
    
      {
        CHECK(cu.GBiIdx != GBI_DEFAULT, "Error: cu.GBiIdx != GBI_DEFAULT");
        return false;
      }
    
    
    Yu Han's avatar
    Yu Han committed
      if (cu.predMode == MODE_IBC)
      {
        return false;
      }
    
    
      if( cu.predMode == MODE_INTRA || cu.cs->slice->isInterP() )
      {
        return false;
      }
    
      if( cu.lwidth() * cu.lheight() < GBI_SIZE_CONSTRAINT )
      {
        return false;
      }
    
      if( !cu.firstPU->mergeFlag )
    
        if( cu.firstPU->interDir == 3 )
        {
    
    		WPScalingParam *wp0;
    		WPScalingParam *wp1;
    
    		int refIdx0 = cu.firstPU->refIdx[REF_PIC_LIST_0];
    		int refIdx1 = cu.firstPU->refIdx[REF_PIC_LIST_1];
    
    		cu.cs->slice->getWpScaling(REF_PIC_LIST_0, refIdx0, wp0);
    		cu.cs->slice->getWpScaling(REF_PIC_LIST_1, refIdx1, wp1);
    
    		if ((wp0[COMPONENT_Y].bPresentFlag || wp0[COMPONENT_Cb].bPresentFlag || wp0[COMPONENT_Cr].bPresentFlag
    			|| wp1[COMPONENT_Y].bPresentFlag || wp1[COMPONENT_Cb].bPresentFlag || wp1[COMPONENT_Cr].bPresentFlag)
    			)
    		{
    			return false;
    		}
    
      return false;
    }
    
    uint8_t CU::getValidGbiIdx( const CodingUnit &cu )
    {
      if( cu.firstPU->interDir == 3 && !cu.firstPU->mergeFlag )
      {
        return cu.GBiIdx;
      }
      else if( cu.firstPU->interDir == 3 && cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_DEFAULT_N )
      {
        // This is intended to do nothing here.
      }
      else if( cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_SUBPU_ATMVP )
      {
        CHECK(cu.GBiIdx != GBI_DEFAULT, " cu.GBiIdx != GBI_DEFAULT ");
      }
      else
      {
        CHECK(cu.GBiIdx != GBI_DEFAULT, " cu.GBiIdx != GBI_DEFAULT ");
      }
    
      return GBI_DEFAULT;
    }
    
    void CU::setGbiIdx( CodingUnit &cu, uint8_t uh )
    {
      int8_t uhCnt = 0;
    
      if( cu.firstPU->interDir == 3 && !cu.firstPU->mergeFlag )
      {
        cu.GBiIdx = uh;
        ++uhCnt;
      }
      else if( cu.firstPU->interDir == 3 && cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_DEFAULT_N )
      {
        // This is intended to do nothing here.
      }
      else if( cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_SUBPU_ATMVP )
      {
        cu.GBiIdx = GBI_DEFAULT;
      }
      else
      {
        cu.GBiIdx = GBI_DEFAULT;
      }
    
      CHECK(uhCnt <= 0, " uhCnt <= 0 ");
    }
    
    uint8_t CU::deriveGbiIdx( uint8_t gbiLO, uint8_t gbiL1 )
    {
      if( gbiLO == gbiL1 )
      {
        return gbiLO;
      }
      const int8_t w0 = getGbiWeight(gbiLO, REF_PIC_LIST_0);
      const int8_t w1 = getGbiWeight(gbiL1, REF_PIC_LIST_1);
      const int8_t th = g_GbiWeightBase >> 1;
      const int8_t off = 1;
    
      if( w0 == w1 || (w0 < (th - off) && w1 < (th - off)) || (w0 >(th + off) && w1 >(th + off)) )
      {
        return GBI_DEFAULT;
      }
      else
      {
        if( w0 > w1 )
        {
          return ( w0 >= th ? gbiLO : gbiL1 );
        }
        else
        {
          return ( w1 >= th ? gbiL1 : gbiLO );
        }
      }
    }
    
    bool CU::bdpcmAllowed( const CodingUnit& cu, const ComponentID compID )
    {
      bool bdpcmAllowed = compID == COMPONENT_Y;
           bdpcmAllowed &= CU::isIntra( cu );
           bdpcmAllowed &= ( cu.lwidth() <= 32 && cu.lheight() <= 32 );
    
      return bdpcmAllowed;
    }
    
    // TU tools
    
    bool TU::isNonTransformedResidualRotated(const TransformUnit &tu, const ComponentID &compID)
    {
      return tu.cs->sps->getSpsRangeExtension().getTransformSkipRotationEnabledFlag() && tu.blocks[compID].width == 4 && tu.cu->predMode == MODE_INTRA;
    }
    
    bool TU::getCbf( const TransformUnit &tu, const ComponentID &compID )
    {
      return getCbfAtDepth( tu, compID, tu.depth );
    }
    
    bool TU::getCbfAtDepth(const TransformUnit &tu, const ComponentID &compID, const unsigned &depth)
    {
      return ((tu.cbf[compID] >> depth) & 1) == 1;
    }
    
    void TU::setCbfAtDepth(TransformUnit &tu, const ComponentID &compID, const unsigned &depth, const bool &cbf)
    {
      // first clear the CBF at the depth
      tu.cbf[compID] &= ~(1  << depth);
      // then set the CBF
      tu.cbf[compID] |= ((cbf ? 1 : 0) << depth);
    }
    
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    bool TU::isTSAllowed(const TransformUnit &tu, const ComponentID compID)
    {
      bool    tsAllowed = compID == COMPONENT_Y;
      const int maxSize = tu.cs->pps->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize();
    
      tsAllowed &= tu.cs->pps->getUseTransformSkip();
      tsAllowed &= !tu.cu->transQuantBypass;
    
      tsAllowed &= ( !tu.cu->ispMode || !isLuma(compID) );
    
      tsAllowed &= !( tu.cu->bdpcmMode && tu.lwidth() <= BDPCM_MAX_CU_SIZE && tu.lheight() <= BDPCM_MAX_CU_SIZE );
    
    Tung Nguyen's avatar
    Tung Nguyen committed
      SizeType transformSkipMaxSize = 1 << maxSize;
      tsAllowed &= tu.lwidth() <= transformSkipMaxSize && tu.lheight() <= transformSkipMaxSize;
    
      tsAllowed &= !tu.cu->sbtInfo;
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    
      return tsAllowed;
    }
    
    bool TU::isMTSAllowed(const TransformUnit &tu, const ComponentID compID)
    {
      bool   mtsAllowed = compID == COMPONENT_Y;
      const int maxSize = CU::isIntra( *tu.cu ) ? MTS_INTRA_MAX_CU_SIZE : MTS_INTER_MAX_CU_SIZE;
    
    
      mtsAllowed &= CU::isIntra( *tu.cu ) ? tu.cs->sps->getUseIntraMTS() : tu.cs->sps->getUseInterMTS() && CU::isInter( *tu.cu );
    
    Tung Nguyen's avatar
    Tung Nguyen committed
      mtsAllowed &= ( tu.lwidth() <= maxSize && tu.lheight() <= maxSize );
    
      mtsAllowed &= !tu.cu->ispMode;
    
      mtsAllowed &= !tu.cu->sbtInfo;
    
      mtsAllowed &= !( tu.cu->bdpcmMode && tu.lwidth() <= BDPCM_MAX_CU_SIZE && tu.lheight() <= BDPCM_MAX_CU_SIZE );
    
    Tung Nguyen's avatar
    Tung Nguyen committed
      return mtsAllowed;
    }
    
    
    uint32_t TU::getGolombRiceStatisticsIndex(const TransformUnit &tu, const ComponentID &compID)
    {
    
      const bool transformSkip    = tu.mtsIdx==MTS_SKIP;
    
      const bool transquantBypass = tu.cu->transQuantBypass;
    
      //--------
    
      const uint32_t channelTypeOffset = isChroma(compID) ? 2 : 0;
      const uint32_t nonTransformedOffset = (transformSkip || transquantBypass) ? 1 : 0;
    
      //--------
    
      const uint32_t selectedIndex = channelTypeOffset + nonTransformedOffset;
      CHECK( selectedIndex >= RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS, "Invalid golomb rice adaptation statistics set" );
    
      return selectedIndex;
    }
    
    bool TU::hasCrossCompPredInfo( const TransformUnit &tu, const ComponentID &compID )
    {
    
    Yu Han's avatar
    Yu Han committed
      return (isChroma(compID) && tu.cs->pps->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && TU::getCbf(tu, COMPONENT_Y) &&
        (!CU::isIntra(*tu.cu) || PU::isChromaIntraModeCrossCheckMode(*tu.cs->getPU(tu.blocks[compID].pos(), toChannelType(compID)))));
    
    }
    
    uint32_t TU::getNumNonZeroCoeffsNonTS( const TransformUnit& tu, const bool bLuma, const bool bChroma )
    {
      uint32_t count = 0;
      for( uint32_t i = 0; i < ::getNumberValidTBlocks( *tu.cs->pcv ); i++ )
      {
    
        if( tu.blocks[ i ].valid() && tu.mtsIdx != MTS_SKIP && TU::getCbf( tu, ComponentID( i ) ) )
    
        {
          if( isLuma  ( tu.blocks[i].compID ) && !bLuma   ) continue;
          if( isChroma( tu.blocks[i].compID ) && !bChroma ) continue;
    
          uint32_t area = tu.blocks[i].area();
          const TCoeff* coeff = tu.getCoeffs( ComponentID( i ) ).buf;
          for( uint32_t j = 0; j < area; j++ )
          {
            count += coeff[j] != 0;
          }
        }
      }
      return count;
    }
    
    
    uint32_t TU::getNumNonZeroCoeffsNonTSCorner8x8( const TransformUnit& tu, const bool lumaFlag, const bool chromaFlag )
    {
      const uint32_t lumaWidth       = tu.blocks[ 0 ].width,  chromaWidth  = tu.blocks[ 1 ].width;
      const uint32_t lumaHeight      = tu.blocks[ 0 ].height, chromaHeight = tu.blocks[ 1 ].height;
      bool           luma4x4TUFlag   = lumaWidth     == 4 && lumaHeight   == 4;
      bool           chroma4x4TUFlag = chromaWidth   == 4 && chromaHeight == 4;
      bool           luma8x8TUFlag   = lumaWidth     == 8 && lumaHeight   == 8;
      bool           chroma8x8TUFlag = chromaWidth   == 8 && chromaHeight == 8;
      bool           lumaCountFlag   = ( lumaWidth   >= 8 && lumaHeight   >= 8 ) || luma4x4TUFlag;
      bool           chromaCountFlag = ( chromaWidth >= 8 && chromaHeight >= 8 ) || chroma4x4TUFlag;
    
      uint32_t count = 0;
      for( uint32_t i = 0; i < ::getNumberValidTBlocks( *tu.cs->pcv ); i++ )
      {
    
        if( tu.blocks[ i ].valid() && tu.mtsIdx != MTS_SKIP && TU::getCbf( tu, ComponentID( i ) ) )
    
        {
          if(   isLuma( tu.blocks[ i ].compID ) && (   !lumaFlag ||   !lumaCountFlag ) ) continue;
          if( isChroma( tu.blocks[ i ].compID ) && ( !chromaFlag || !chromaCountFlag ) ) continue;
    
          const ScanElement * scan  = g_coefTopLeftDiagScan8x8[ gp_sizeIdxInfo->idxFrom( tu.blocks[ i ].width ) ];
          const TCoeff*       coeff = tu.getCoeffs( ComponentID( i ) ).buf;
    
          int startPos = MAX_LFNST_COEF_NUM, endPos = 47;
          if( ( isLuma( tu.blocks[ i ].compID ) && luma4x4TUFlag ) || ( isChroma( tu.blocks[ i ].compID ) && chroma4x4TUFlag ) )
          {
            startPos = 8; endPos = 15;
          }
          else if( ( isLuma( tu.blocks[ i ].compID ) && luma8x8TUFlag ) || ( isChroma( tu.blocks[ i ].compID ) && chroma8x8TUFlag ) )
          {
            startPos = 8; endPos = 47;
          }
          const ScanElement *scanPtr = scan + startPos;
          for( uint32_t j = startPos; j <= endPos; j++ )
          {
            count += coeff[ scanPtr->idx ] != 0;
            scanPtr++;
          }
        }
      }
      return count;
    }
    
    
    bool TU::needsSqrt2Scale( const TransformUnit &tu, const ComponentID &compID )
    {
      const Size &size=tu.blocks[compID];
    
      const bool isTransformSkip = tu.mtsIdx==MTS_SKIP && isLuma(compID);
    
    Karl Sharman's avatar
    Karl Sharman committed
      return (!isTransformSkip) && (((g_aucLog2[size.width] + g_aucLog2[size.height]) & 1) == 1);
    
    bool TU::needsBlockSizeTrafoScale( const TransformUnit &tu, const ComponentID &compID )
    {
      return needsSqrt2Scale( tu, compID ) || isNonLog2BlockSize( tu.blocks[compID] );
    }
    
    TransformUnit* TU::getPrevTU( const TransformUnit &tu, const ComponentID compID )
    {
      TransformUnit* prevTU = tu.prev;
    
      if( prevTU != nullptr && ( prevTU->cu != tu.cu || !prevTU->blocks[compID].valid() ) )
      {
        prevTU = nullptr;
      }
    
      return prevTU;
    }
    
    bool TU::getPrevTuCbfAtDepth( const TransformUnit &currentTu, const ComponentID compID, const int trDepth )
    {
      const TransformUnit* prevTU = getPrevTU( currentTu, compID );
      return ( prevTU != nullptr ) ? TU::getCbfAtDepth( *prevTU, compID, trDepth ) : false;
    }
    
    
    // other tools
    
    uint32_t getCtuAddr( const Position& pos, const PreCalcValues& pcv )
    {
      return ( pos.x >> pcv.maxCUWidthLog2 ) + ( pos.y >> pcv.maxCUHeightLog2 ) * pcv.widthInCtus;
    }
    
    
    int getNumModesMip(const Size& block)
    {
      if (block.width > (4 * block.height) || block.height > (4 * block.width))
      {
        return 0;
      }
    
      if( block.width == 4 && block.height == 4 )
      {
        return 35;
      }
      else if (block.width <= 8 && block.height <= 8)
      {
        return 19;
      }
      else
      {
        return 11;
      }
    }
    
    int getNumEpBinsMip(const Size& block)
    {
      int numModes = getNumModesMip(block);
      return int(std::ceil((std::log2(numModes - NUM_MPM_MIP - 1))));
    }
    
    bool mipModesAvailable(const Size& block)
    {
      return (getNumModesMip(block));
    }