Skip to content
Snippets Groups Projects
UnitTools.cpp 99.5 KiB
Newer Older
  • Learn to ignore specific revisions
  •         PU::getInterMergeCandidates ( pu, mrgCtx 
    #if JVET_L0054_MMVD
              , 0
    #endif
            );
    
            PU::restrictBiPredMergeCands( 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;
    }
    
    int CU::getMaxNeighboriMVCandNum( const CodingStructure& cs, const Position& pos )
    {
      const int  numDefault     = 0;
      int        maxImvNumCand  = 0;
    
      // Get BCBP of left PU
    #if HEVC_TILES_WPP
      const CodingUnit *cuLeft  = cs.getCURestricted( pos.offset( -1, 0 ), cs.slice->getIndependentSliceIdx(), cs.picture->tileMap->getTileIdxMap( pos ), CH_L );
    #else
      const CodingUnit *cuLeft  = cs.getCURestricted( pos.offset( -1, 0 ), cs.slice->getIndependentSliceIdx(), CH_L );
    #endif
      maxImvNumCand = ( cuLeft ) ? cuLeft->imvNumCand : numDefault;
    
      // Get BCBP of above PU
    #if HEVC_TILES_WPP
      const CodingUnit *cuAbove = cs.getCURestricted( pos.offset( 0, -1 ), cs.slice->getIndependentSliceIdx(), cs.picture->tileMap->getTileIdxMap( pos ), CH_L );
    #else
      const CodingUnit *cuAbove = cs.getCURestricted( pos.offset( 0, -1 ), cs.slice->getIndependentSliceIdx(), CH_L );
    #endif
      maxImvNumCand = std::max( maxImvNumCand, ( cuAbove ) ? cuAbove->imvNumCand : numDefault );
    
      return maxImvNumCand;
    }
    
    
    #if JVET_L0646_GBI
    bool CU::isGBiIdxCoded( const CodingUnit &cu )
    {
      if( cu.cs->sps->getSpsNext().getUseGBi() == false )
      {
        CHECK(cu.GBiIdx != GBI_DEFAULT, "Error: cu.GBiIdx != GBI_DEFAULT");
        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->interDir == 3 && !cu.firstPU->mergeFlag )
      {
        return true;
      }
    
      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 );
        }
      }
    }
    #endif
    
    
    // TU tools
    
    #if HEVC_USE_4x4_DSTVII
    bool TU::useDST(const TransformUnit &tu, const ComponentID &compID)
    {
      return isLuma(compID) && tu.cu->predMode == MODE_INTRA;
    }
    
    #endif
    
    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 )
    {
    #if ENABLE_BMS
      return getCbfAtDepth( tu, compID, tu.depth );
    #else
      return tu.cbf[compID];
    #endif
    }
    
    #if ENABLE_BMS
    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);
    }
    #else
    void TU::setCbf( TransformUnit &tu, const ComponentID &compID, const bool &cbf )
    {
      tu.cbf[compID] = cbf;
    }
    #endif
    
    bool TU::hasTransformSkipFlag(const CodingStructure& cs, const CompArea& area)
    {
      uint32_t transformSkipLog2MaxSize = cs.pps->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize();
    
      if( cs.pcv->rectCUs )
      {
        return ( area.width * area.height <= (1 << ( transformSkipLog2MaxSize << 1 )) );
      }
      return ( area.width <= (1 << transformSkipLog2MaxSize) );
    }
    
    uint32_t TU::getGolombRiceStatisticsIndex(const TransformUnit &tu, const ComponentID &compID)
    {
      const bool transformSkip    = tu.transformSkip[compID];
      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;
    }
    
    #if HEVC_USE_MDCS
    uint32_t TU::getCoefScanIdx(const TransformUnit &tu, const ComponentID &compID)
    {
      //------------------------------------------------
    
      //this mechanism is available for intra only
    
      if( !CU::isIntra( *tu.cu ) )
      {
        return SCAN_DIAG;
      }
    
      //------------------------------------------------
    
      //check that MDCS can be used for this TU
    
    
      const CompArea &area      = tu.blocks[compID];
      const SPS &sps            = *tu.cs->sps;
      const ChromaFormat format = sps.getChromaFormatIdc();
    
    
      const uint32_t maximumWidth  = MDCS_MAXIMUM_WIDTH  >> getComponentScaleX(compID, format);
      const uint32_t maximumHeight = MDCS_MAXIMUM_HEIGHT >> getComponentScaleY(compID, format);
    
      if ((area.width > maximumWidth) || (area.height > maximumHeight))
      {
        return SCAN_DIAG;
      }
    
      //------------------------------------------------
    
      //otherwise, select the appropriate mode
    
      const PredictionUnit &pu = *tu.cs->getPU( area.pos(), toChannelType( compID ) );
    
      uint32_t uiDirMode = PU::getFinalIntraMode(pu, toChannelType(compID));
    
      //------------------
    
           if (abs((int) uiDirMode - VER_IDX) <= MDCS_ANGLE_LIMIT)
      {
        return SCAN_HOR;
      }
      else if (abs((int) uiDirMode - HOR_IDX) <= MDCS_ANGLE_LIMIT)
      {
        return SCAN_VER;
      }
      else
      {
        return SCAN_DIAG;
      }
    }
    
    #endif
    bool TU::hasCrossCompPredInfo( const TransformUnit &tu, const ComponentID &compID )
    {
      return ( isChroma(compID) && tu.cs->pps->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && TU::getCbf( tu, COMPONENT_Y ) &&
             ( CU::isInter(*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.transformSkip[i] && 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;
    }
    
    bool TU::needsSqrt2Scale( const Size& size )
    {
      return (((g_aucLog2[size.width] + g_aucLog2[size.height]) & 1) == 1);
    }
    
    #if HM_QTBT_AS_IN_JEM_QUANT
    
    bool TU::needsBlockSizeTrafoScale( const Size& size )
    {
      return needsSqrt2Scale( size ) || isNonLog2BlockSize( size );
    }
    #else
    bool TU::needsQP3Offset(const TransformUnit &tu, const ComponentID &compID)
    {
      if( tu.cs->pcv->rectCUs && !tu.transformSkip[compID] )
      {
        return ( ( ( g_aucLog2[tu.blocks[compID].width] + g_aucLog2[tu.blocks[compID].height] ) & 1 ) == 1 );
      }
      return false;
    }
    #endif
    
    
    
    
    
    // other tools
    
    uint32_t getCtuAddr( const Position& pos, const PreCalcValues& pcv )
    {
      return ( pos.x >> pcv.maxCUWidthLog2 ) + ( pos.y >> pcv.maxCUHeightLog2 ) * pcv.widthInCtus;
    }