Skip to content
Snippets Groups Projects
EncLib.cpp 94.4 KiB
Newer Older
  • Learn to ignore specific revisions
  •   for( unsigned int i = 0; i < m_numVerVirtualBoundaries; i++ )
      {
        pps.setVirtualBoundariesPosX            ( m_virtualBoundariesPosX[i], i );
      }
      for( unsigned int i = 0; i < m_numHorVirtualBoundaries; i++ )
      {
        pps.setVirtualBoundariesPosY            ( m_virtualBoundariesPosY[i], i );
      }
    
    Brian Heng's avatar
    Brian Heng committed
    #endif
    
      pps.pcv = new PreCalcValues( sps, pps, true );
    
    Hendry's avatar
    Hendry committed
      pps.setRpl1IdxPresentFlag(sps.getRPL1IdxPresentFlag());
    
    Brian Heng's avatar
    Brian Heng committed
    #if JVET_P1006_PICTURE_HEADER
    void EncLib::xInitPicHeader(PicHeader &picHeader, const SPS &sps, const PPS &pps)
    {
      int i;
      picHeader.initPicHeader();
    
      // parameter sets
      picHeader.setSPSId( sps.getSPSId() );
      picHeader.setPPSId( pps.getPPSId() );  
      
      // merge list sizes
      picHeader.setMaxNumMergeCand      ( getMaxNumMergeCand()       );
      picHeader.setMaxNumAffineMergeCand( getMaxNumAffineMergeCand() );
      picHeader.setMaxNumTriangleCand   ( getMaxNumTriangleCand()    );
      picHeader.setMaxNumIBCMergeCand   ( getMaxNumIBCMergeCand()    );
      
      // copy partitioning constraints from SPS
      picHeader.setSplitConsOverrideFlag(false);
      picHeader.setMinQTSizes( sps.getMinQTSizes() );
      picHeader.setMaxMTTHierarchyDepths( sps.getMaxMTTHierarchyDepths() );
      picHeader.setMaxBTSizes( sps.getMaxBTSizes() );
      picHeader.setMaxTTSizes( sps.getMaxTTSizes() );
    
      // quantization
      picHeader.setDepQuantEnabledFlag( getDepQuantEnabledFlag() );
      picHeader.setSignDataHidingEnabledFlag( getSignDataHidingEnabledFlag() );
      
      bool bUseDQP = (getCuQpDeltaSubdiv() > 0)? true : false;
    
      if( (getMaxDeltaQP() != 0 )|| getUseAdaptiveQP() )
      {
        bUseDQP = true;
      }
    
    #if SHARP_LUMA_DELTA_QP
      if( getLumaLevelToDeltaQPMapping().isEnabled() )
      {
        bUseDQP = true;
      }
    #endif
    #if ENABLE_QPA
      if( getUsePerceptQPA() && !bUseDQP )
      {
        CHECK( m_cuQpDeltaSubdiv != 0, "max. delta-QP subdiv must be zero!" );
        bUseDQP = (getBaseQP() < 38) && (getSourceWidth() > 512 || getSourceHeight() > 320);
      }
    #endif
    
      if( m_costMode==COST_SEQUENCE_LEVEL_LOSSLESS || m_costMode==COST_LOSSLESS_CODING )
      {
        bUseDQP=false;
      }
    
      if( m_RCEnableRateControl )
      {
        picHeader.setCuQpDeltaSubdivIntra( 0 );
        picHeader.setCuQpDeltaSubdivInter( 0 );
      }
      else if( bUseDQP )
      {
        picHeader.setCuQpDeltaSubdivIntra( m_cuQpDeltaSubdiv );
        picHeader.setCuQpDeltaSubdivInter( m_cuQpDeltaSubdiv );
      }
      else
      {
        picHeader.setCuQpDeltaSubdivIntra( 0 );
        picHeader.setCuQpDeltaSubdivInter( 0 );
      }
    
      if( m_cuChromaQpOffsetSubdiv >= 0 )
      {
        picHeader.setCuChromaQpOffsetSubdivIntra(m_cuChromaQpOffsetSubdiv);
        picHeader.setCuChromaQpOffsetSubdivInter(m_cuChromaQpOffsetSubdiv);
      }
      else
      {
        picHeader.setCuChromaQpOffsetSubdivIntra(0);
        picHeader.setCuChromaQpOffsetSubdivInter(0);
      }
      
      // sub-pictures
      picHeader.setSubPicIdSignallingPresentFlag(sps.getSubPicIdSignallingPresentFlag());
      picHeader.setSubPicIdLen(sps.getSubPicIdLen());
      for(i=0; i<sps.getNumSubPics(); i++) {
        picHeader.setSubPicId(i, sps.getSubPicId(i));
      }
    
      // virtual boundaries
      picHeader.setLoopFilterAcrossVirtualBoundariesDisabledFlag(sps.getLoopFilterAcrossVirtualBoundariesDisabledFlag());
      picHeader.setNumVerVirtualBoundaries(sps.getNumVerVirtualBoundaries());
      picHeader.setNumHorVirtualBoundaries(sps.getNumHorVirtualBoundaries());
      for(i=0; i<3; i++) {
        picHeader.setVirtualBoundariesPosX(sps.getVirtualBoundariesPosX(i), i);
        picHeader.setVirtualBoundariesPosY(sps.getVirtualBoundariesPosY(i), i);
      }
    
      // gradual decoder refresh flag
      picHeader.setGdrPicFlag(false);
      
      // BDOF / DMVR / PROF
    
    #if JVET_P0314_PROF_BDOF_DMVR_HLS
      picHeader.setDisBdofFlag(false);
      picHeader.setDisDmvrFlag(false);
      picHeader.setDisProfFlag(false);
    #else
    
    Brian Heng's avatar
    Brian Heng committed
      picHeader.setDisBdofDmvrFlag(false);
    
    Hendry's avatar
    Hendry committed
    void EncLib::xInitAPS(APS &aps)
    {
      //Do nothing now
    }
    
    Hendry's avatar
    Hendry committed
    
    void EncLib::xInitRPL(SPS &sps, bool isFieldCoding)
    {
      ReferencePictureList*      rpl;
    
      int numRPLCandidates = getRPLCandidateSize(0);
    
      sps.createRPLList0(numRPLCandidates);
      sps.createRPLList1(numRPLCandidates);
    
    Hendry's avatar
    Hendry committed
      RPLList* rplList = 0;
    
      for (int i = 0; i < 2; i++)
      {
        rplList = (i == 0) ? sps.getRPLList0() : sps.getRPLList1();
        for (int j = 0; j < numRPLCandidates; j++)
        {
          const RPLEntry &ge = getRPLEntry(i, j);
          rpl = rplList->getReferencePictureList(j);
          rpl->setNumberOfShorttermPictures(ge.m_numRefPics);
          rpl->setNumberOfLongtermPictures(0);   //Hardcoded as 0 for now. need to update this when implementing LTRP
          rpl->setNumberOfActivePictures(ge.m_numRefPicsActive);
    
          rpl->setLtrpInSliceHeaderFlag(ge.m_ltrp_in_slice_header_flag);
    
    Hendry's avatar
    Hendry committed
    
          for (int k = 0; k < ge.m_numRefPics; k++)
          {
            rpl->setRefPicIdentifier(k, ge.m_deltaRefPics[k], 0);
          }
        }
      }
    
    
      //Check if all delta POC of STRP in each RPL has the same sign
    
    Hendry's avatar
    Hendry committed
      //Check RPLL0 first
      const RPLList* rplList0 = sps.getRPLList0();
      const RPLList* rplList1 = sps.getRPLList1();
    
      uint32_t numberOfRPL = sps.getNumRPL0();
    
    Hendry's avatar
    Hendry committed
    
      bool isAllEntriesinRPLHasSameSignFlag = true;
      bool isFirstEntry = true;
      bool lastSign = true;        //true = positive ; false = negative
      for (uint32_t ii = 0; isAllEntriesinRPLHasSameSignFlag && ii < numberOfRPL; ii++)
      {
        const ReferencePictureList* rpl = rplList0->getReferencePictureList(ii);
        for (uint32_t jj = 0; isAllEntriesinRPLHasSameSignFlag && jj < rpl->getNumberOfActivePictures(); jj++)
        {
          if (!rpl->isRefPicLongterm(jj) && isFirstEntry)
          {
            lastSign = (rpl->getRefPicIdentifier(jj) >= 0) ? true : false;
            isFirstEntry = false;
          }
          else if (!rpl->isRefPicLongterm(jj) && (((rpl->getRefPicIdentifier(jj) - rpl->getRefPicIdentifier(jj - 1)) >= 0 && lastSign == false) || ((rpl->getRefPicIdentifier(jj) - rpl->getRefPicIdentifier(jj - 1)) < 0 && lastSign == true)))
          {
            isAllEntriesinRPLHasSameSignFlag = false;
          }
        }
      }
      //Check RPLL1. Skip it if it is already found out that this flag is not true for RPL0 or if RPL1 is the same as RPL0
    
      numberOfRPL = sps.getNumRPL1();
    
    Hendry's avatar
    Hendry committed
      isFirstEntry = true;
      lastSign = true;
      for (uint32_t ii = 0; isAllEntriesinRPLHasSameSignFlag && !sps.getRPL1CopyFromRPL0Flag() && ii < numberOfRPL; ii++)
      {
        isFirstEntry = true;
        const ReferencePictureList* rpl = rplList1->getReferencePictureList(ii);
        for (uint32_t jj = 0; isAllEntriesinRPLHasSameSignFlag && jj < rpl->getNumberOfActivePictures(); jj++)
        {
          if (!rpl->isRefPicLongterm(jj) && isFirstEntry)
          {
            lastSign = (rpl->getRefPicIdentifier(jj) >= 0) ? true : false;
            isFirstEntry = false;
          }
          else if (!rpl->isRefPicLongterm(jj) && (((rpl->getRefPicIdentifier(jj) - rpl->getRefPicIdentifier(jj - 1)) >= 0 && lastSign == false) || ((rpl->getRefPicIdentifier(jj) - rpl->getRefPicIdentifier(jj - 1)) < 0 && lastSign == true)))
          {
            isAllEntriesinRPLHasSameSignFlag = false;
          }
        }
      }
      sps.setAllActiveRplEntriesHasSameSignFlag(isAllEntriesinRPLHasSameSignFlag);
    }
    
    void EncLib::getActiveRefPicListNumForPOC(const SPS *sps, int POCCurr, int GOPid, uint32_t *activeL0, uint32_t *activeL1)
    {
      if (m_uiIntraPeriod < 0)  //Only for RA
      {
        *activeL0 = *activeL1 = 0;
        return;
      }
      uint32_t rpl0Idx = GOPid;
      uint32_t rpl1Idx = GOPid;
    
      int fullListNum = m_iGOPSize;
      int partialListNum = getRPLCandidateSize(0) - m_iGOPSize;
      int extraNum = fullListNum;
      if (m_uiIntraPeriod < 0)
      {
    
    Fabrice Le Léannec's avatar
    Fabrice Le Léannec committed
    #if JVET_P0345_LD_GOP_8
        if (POCCurr < (2 * m_iGOPSize + 2))
    #else
    
    Hendry's avatar
    Hendry committed
        if (POCCurr < 10)
    
    Fabrice Le Léannec's avatar
    Fabrice Le Léannec committed
    #endif
    
    Hendry's avatar
    Hendry committed
        {
          rpl0Idx = POCCurr + m_iGOPSize - 1;
          rpl1Idx = POCCurr + m_iGOPSize - 1;
        }
        else
        {
          rpl0Idx = (POCCurr%m_iGOPSize == 0) ? m_iGOPSize - 1 : POCCurr%m_iGOPSize - 1;
          rpl1Idx = (POCCurr%m_iGOPSize == 0) ? m_iGOPSize - 1 : POCCurr%m_iGOPSize - 1;
        }
        extraNum = fullListNum + partialListNum;
      }
      for (; extraNum<fullListNum + partialListNum; extraNum++)
      {
        if (m_uiIntraPeriod > 0 && getDecodingRefreshType() > 0)
        {
          int POCIndex = POCCurr%m_uiIntraPeriod;
          if (POCIndex == 0)
            POCIndex = m_uiIntraPeriod;
          if (POCIndex == m_RPLList0[extraNum].m_POC)
          {
            rpl0Idx = extraNum;
            rpl1Idx = extraNum;
            extraNum++;
          }
        }
      }
    
      const ReferencePictureList *rpl0 = sps->getRPLList0()->getReferencePictureList(rpl0Idx);
      *activeL0 = rpl0->getNumberOfActivePictures();
      const ReferencePictureList *rpl1 = sps->getRPLList1()->getReferencePictureList(rpl1Idx);
      *activeL1 = rpl1->getNumberOfActivePictures();
    }
    
    void EncLib::selectReferencePictureList(Slice* slice, int POCCurr, int GOPid, int ltPoc)
    {
      bool isEncodeLtRef = (POCCurr == ltPoc);
      if (m_compositeRefEnabled && isEncodeLtRef)
      {
        POCCurr++;
      }
    
      slice->setRPL0idx(GOPid);
      slice->setRPL1idx(GOPid);
    
      int fullListNum = m_iGOPSize;
      int partialListNum = getRPLCandidateSize(0) - m_iGOPSize;
      int extraNum = fullListNum;
      if (m_uiIntraPeriod < 0)
      {
    
    #if JVET_P0345_LD_GOP_8
    
    Fabrice Le Léannec's avatar
    Fabrice Le Léannec committed
        if (POCCurr < (2 * m_iGOPSize + 2))
    
    #else
    
    Hendry's avatar
    Hendry committed
        if (POCCurr < 10)
    
    #endif
    
    Hendry's avatar
    Hendry committed
        {
          slice->setRPL0idx(POCCurr + m_iGOPSize - 1);
          slice->setRPL1idx(POCCurr + m_iGOPSize - 1);
        }
        else
        {
          slice->setRPL0idx((POCCurr%m_iGOPSize == 0) ? m_iGOPSize - 1 : POCCurr%m_iGOPSize - 1);
          slice->setRPL1idx((POCCurr%m_iGOPSize == 0) ? m_iGOPSize - 1 : POCCurr%m_iGOPSize - 1);
        }
        extraNum = fullListNum + partialListNum;
      }
      for (; extraNum < fullListNum + partialListNum; extraNum++)
      {
        if (m_uiIntraPeriod > 0 && getDecodingRefreshType() > 0)
        {
          int POCIndex = POCCurr%m_uiIntraPeriod;
          if (POCIndex == 0)
            POCIndex = m_uiIntraPeriod;
          if (POCIndex == m_RPLList0[extraNum].m_POC)
          {
            slice->setRPL0idx(extraNum);
            slice->setRPL1idx(extraNum);
            extraNum++;
          }
        }
      }
    
      const ReferencePictureList *rpl0 = (slice->getSPS()->getRPLList0()->getReferencePictureList(slice->getRPL0idx()));
      const ReferencePictureList *rpl1 = (slice->getSPS()->getRPLList1()->getReferencePictureList(slice->getRPL1idx()));
      slice->setRPL0(rpl0);
      slice->setRPL1(rpl1);
    }
    
    #if !JVET_P1004_REMOVE_BRICKS
    
    Karsten Suehring's avatar
    Karsten Suehring committed
      if ( (m_iNumColumnsMinus1==0) && (m_iNumRowsMinus1==0) )
      {
        // one, no bricks
        pps.setSingleTileInPicFlag(true);
        pps.setSingleBrickPerSliceFlag(true);
        pps.setRectSliceFlag(true);
      }
      else
      {
        pps.setSingleTileInPicFlag(false);
        pps.setSingleBrickPerSliceFlag( m_sliceMode==SINGLE_BRICK_PER_SLICE );
        pps.setRectSliceFlag( m_sliceMode==SINGLE_BRICK_PER_SLICE );
    
        if (m_rectSliceFlag)
          pps.setRectSliceFlag(m_rectSliceFlag);
    
    Karsten Suehring's avatar
    Karsten Suehring committed
      }
      pps.setUniformTileSpacingFlag( m_tileUniformSpacingFlag );
    
      pps.setNumTileColumnsMinus1( m_iNumColumnsMinus1 );
      pps.setNumTileRowsMinus1( m_iNumRowsMinus1 );
      if( !m_tileUniformSpacingFlag )
      {
        pps.setTileColumnWidth( m_tileColumnWidth );
        pps.setTileRowHeight( m_tileRowHeight );
      }
    
      else
      {
        pps.setTileColsWidthMinus1(m_uniformTileColsWidthMinus1);
        pps.setTileRowsHeightMinus1(m_uniformTileRowHeightMinus1);
      }
    
    Karsten Suehring's avatar
    Karsten Suehring committed
      pps.setLoopFilterAcrossBricksEnabledFlag( m_loopFilterAcrossBricksEnabledFlag );
    
      //pps.setRectSliceFlag( m_rectSliceFlag );
      pps.setNumSlicesInPicMinus1( m_numSlicesInPicMinus1 );
    
      pps.setTopLeftBrickIdx(m_topLeftBrickIdx);
      pps.setBottomRightBrickIdx(m_bottomRightBrickIdx);
    
      if (m_numSlicesInPicMinus1 > 0)
      {
        std::vector<int> bottomrightdelta(m_numSlicesInPicMinus1 + 1);
        for (int i = 0; i < m_numSlicesInPicMinus1 + 1; i++)
        {
          bottomrightdelta[i] = (i == 0) ? m_bottomRightBrickIdx[i] : m_bottomRightBrickIdx[i] - m_bottomRightBrickIdx[i - 1];
        }
        pps.setBottomRightBrickIdxDelta(bottomrightdelta);
      }
    
    
    Karsten Suehring's avatar
    Karsten Suehring committed
      pps.setLoopFilterAcrossBricksEnabledFlag( m_loopFilterAcrossBricksEnabledFlag );
      pps.setLoopFilterAcrossSlicesEnabledFlag( m_loopFilterAcrossSlicesEnabledFlag );
      pps.setSignalledSliceIdFlag( m_signalledSliceIdFlag );
      pps.setSignalledSliceIdLengthMinus1( m_signalledSliceIdLengthMinus1 );
      pps.setSignalledSliceIdFlag( m_signalledSliceIdFlag );
      pps.setSignalledSliceIdLengthMinus1( m_signalledSliceIdLengthMinus1 );
      pps.setSliceId( m_sliceId );
    
      int numTiles= (m_iNumColumnsMinus1 + 1) * (m_iNumRowsMinus1 + 1);
    
      pps.setNumTilesInPic(numTiles);
    
      std::vector<int> tileHeight(numTiles);
    
    Karsten Suehring's avatar
    Karsten Suehring committed
      if (m_brickSplitMap.empty())
      {
        pps.setBrickSplittingPresentFlag(false);
      }
      else
      {
        pps.setBrickSplittingPresentFlag(true);
    
        std::vector<bool> brickSplitFlag (numTiles, false);
        std::vector<bool> uniformBrickSpacingFlag (numTiles, false);
        std::vector<int>  brickHeightMinus1 (numTiles, 0);
    
        std::vector<int> numBrickRowsMinus2(numTiles, 0);
    
    Karsten Suehring's avatar
    Karsten Suehring committed
        std::vector<std::vector<int>>  brickRowHeightMinus1 (numTiles);
    
        for (auto &brickSplit: m_brickSplitMap)
        {
          int tileIdx = brickSplit.first;
          CHECK ( tileIdx >= numTiles, "Brick split specified for undefined tile");
    
          brickSplitFlag[tileIdx]           = true;
          uniformBrickSpacingFlag [tileIdx] = brickSplit.second.m_uniformSplit;
          if (uniformBrickSpacingFlag [tileIdx])
          {
            brickHeightMinus1[tileIdx]=brickSplit.second.m_uniformHeight - 1;
          }
          else
          {
    
            numBrickRowsMinus2[tileIdx] = brickSplit.second.m_numSplits - 1;
    
    Karsten Suehring's avatar
    Karsten Suehring committed
            brickRowHeightMinus1[tileIdx].resize(brickSplit.second.m_numSplits);
            for (int i=0; i<brickSplit.second.m_numSplits; i++)
            {
              brickRowHeightMinus1[tileIdx][i]=brickSplit.second.m_brickHeight[i] - 1;
            }
          }
        }
        pps.setBrickSplitFlag(brickSplitFlag);
        pps.setUniformBrickSpacingFlag(uniformBrickSpacingFlag);
        pps.setBrickHeightMinus1(brickHeightMinus1);
    
        pps.setNumBrickRowsMinus2(numBrickRowsMinus2);
    
    Karsten Suehring's avatar
    Karsten Suehring committed
        pps.setBrickRowHeightMinus1(brickRowHeightMinus1);
    
        // check brick dimensions
        std::vector<uint32_t> tileRowHeight (m_iNumRowsMinus1+1);
        int picHeightInCtus = (getSourceHeight() + m_maxCUHeight - 1) / m_maxCUHeight;
    
        // calculate all tile row heights
        if( pps.getUniformTileSpacingFlag() )
        {
          //set width and height for each (uniform) tile
          for(int row=0; row < m_iNumRowsMinus1 + 1; row++)
          {
            tileRowHeight[row] = (row+1)*picHeightInCtus/(m_iNumRowsMinus1+1)   - (row*picHeightInCtus)/(m_iNumRowsMinus1 + 1);
          }
        }
        else
        {
          tileRowHeight[ m_iNumRowsMinus1 ] = picHeightInCtus;
    
          for( int j = 0; j < m_iNumRowsMinus1; j++ )
    
    Karsten Suehring's avatar
    Karsten Suehring committed
          {
            tileRowHeight[ j ] = pps.getTileRowHeight( j );
            tileRowHeight[ m_iNumRowsMinus1 ]  =  tileRowHeight[ m_iNumRowsMinus1 ] - pps.getTileRowHeight( j );
          }
        }
    
        // check brick splits for each tile
        for (int tileIdx=0; tileIdx < numTiles; tileIdx++)
        {
    
          const int tileY = tileIdx / (m_iNumColumnsMinus1 + 1);
    
    
          tileHeight[tileIdx] = tileRowHeight[tileY];
    
          if (tileHeight[tileIdx] <= 1)
          {
            CHECK(pps.getBrickSplitFlag(tileIdx) != 0, "The value of brick_split_flag[ i ] shall be 0 if tileHeight <= 1");
          }
    
    Karsten Suehring's avatar
    Karsten Suehring committed
          if (pps.getBrickSplitFlag(tileIdx))
          {
    
            if (tileHeight[tileIdx] <= 2)
            {
              CHECK(pps.getUniformBrickSpacingFlag(tileIdx) != 1, "The value of uniform_brick_spacing_flag[ i ] shall be 1 if tileHeight <= 2");
            }
    
    Karsten Suehring's avatar
    Karsten Suehring committed
            if (pps.getUniformBrickSpacingFlag(tileIdx))
            {
    
              CHECK((pps.getBrickHeightMinus1(tileIdx) + 1) >= tileHeight[tileIdx], "Brick height larger than or equal to tile height");
    
    Karsten Suehring's avatar
    Karsten Suehring committed
            }
            else
            {
              int cumulativeHeight=0;
    
              for (int i = 0; i <= pps.getNumBrickRowsMinus2(tileIdx); i++)
    
    Karsten Suehring's avatar
    Karsten Suehring committed
              {
                cumulativeHeight += pps.getBrickRowHeightMinus1(tileIdx, i) + 1;
              }
    
              CHECK(cumulativeHeight >= tileHeight[tileIdx], "Cumulative brick height larger than or equal to tile height");
    
    }
    
    void  EncCfg::xCheckGSParameters()
    {
      int   iWidthInCU = ( m_iSourceWidth%m_maxCUWidth ) ? m_iSourceWidth/m_maxCUWidth + 1 : m_iSourceWidth/m_maxCUWidth;
      int   iHeightInCU = ( m_iSourceHeight%m_maxCUHeight ) ? m_iSourceHeight/m_maxCUHeight + 1 : m_iSourceHeight/m_maxCUHeight;
      uint32_t  uiCummulativeColumnWidth = 0;
      uint32_t  uiCummulativeRowHeight = 0;
    
    
      if (m_tileUniformSpacingFlag && m_uniformTileColsWidthMinus1 == -1)
      {
        EXIT("Uniform tiles specified with unspecified or invalid UniformTileColsWidthMinus1 value");
      }
      if (m_tileUniformSpacingFlag && m_uniformTileRowHeightMinus1 == -1)
      {
        EXIT("Uniform tiles specified with unspecified or invalid UniformTileRowHeightMinus1 value");
      }
      if (m_tileUniformSpacingFlag && m_uniformTileColsWidthMinus1 >= iWidthInCU)
      {
        EXIT("UniformTileColsWidthMinus1 too large");
      }
      if (m_tileUniformSpacingFlag && m_uniformTileRowHeightMinus1 >= iHeightInCU)
      {
        EXIT("UniformTileRowHeightMinus1 too large");
      }
    
    
      //check the column relative parameters
      if( m_iNumColumnsMinus1 >= (1<<(LOG2_MAX_NUM_COLUMNS_MINUS1+1)) )
      {
        EXIT( "The number of columns is larger than the maximum allowed number of columns." );
      }
    
      if( m_iNumColumnsMinus1 >= iWidthInCU )
      {
        EXIT( "The current picture can not have so many columns." );
      }
    
      if( m_iNumColumnsMinus1 && !m_tileUniformSpacingFlag )
      {
        for(int i=0; i<m_iNumColumnsMinus1; i++)
        {
          uiCummulativeColumnWidth += m_tileColumnWidth[i];
        }
    
        if( uiCummulativeColumnWidth >= iWidthInCU )
        {
          EXIT( "The width of the column is too large." );
        }
      }
    
      //check the row relative parameters
      if( m_iNumRowsMinus1 >= (1<<(LOG2_MAX_NUM_ROWS_MINUS1+1)) )
      {
        EXIT( "The number of rows is larger than the maximum allowed number of rows." );
      }
    
      if( m_iNumRowsMinus1 >= iHeightInCU )
      {
        EXIT( "The current picture can not have so many rows." );
      }
    
      if( m_iNumRowsMinus1 && !m_tileUniformSpacingFlag )
      {
        for(int i=0; i<m_iNumRowsMinus1; i++)
        {
          uiCummulativeRowHeight += m_tileRowHeight[i];
        }
    
        if( uiCummulativeRowHeight >= iHeightInCU )
        {
          EXIT( "The height of the row is too large." );
        }
      }
    }
    
    #endif
    
    void EncLib::setParamSetChanged(int spsId, int ppsId)
    {
      m_ppsMap.setChangedFlag(ppsId);
      m_spsMap.setChangedFlag(spsId);
    }
    
    Hendry's avatar
    Hendry committed
    bool EncLib::APSNeedsWriting(int apsId)
    {
    
      bool isChanged = m_apsMap.getChangedFlag(apsId);
    
    Hendry's avatar
    Hendry committed
      m_apsMap.clearChangedFlag(apsId);
    
    Hendry's avatar
    Hendry committed
    }
    
    bool EncLib::PPSNeedsWriting(int ppsId)
    {
      bool bChanged=m_ppsMap.getChangedFlag(ppsId);
      m_ppsMap.clearChangedFlag(ppsId);
      return bChanged;
    }
    
    bool EncLib::SPSNeedsWriting(int spsId)
    {
      bool bChanged=m_spsMap.getChangedFlag(spsId);
      m_spsMap.clearChangedFlag(spsId);
      return bChanged;
    }
    
    
    void EncLib::checkPltStats( Picture* pic )
    {
      int totalArea = 0;
      int pltArea = 0;
      for (auto apu : pic->cs->pus)
      {
        for (int i = 0; i < MAX_NUM_TBLOCKS; ++i)
        {
          int puArea = apu->blocks[i].width * apu->blocks[i].height;
          if (apu->blocks[i].width > 0 && apu->blocks[i].height > 0)
          {
            totalArea += puArea;
            if (CU::isPLT(*apu->cu) || CU::isIBC(*apu->cu))
            {
              pltArea += puArea;
            }
            break;
          }
    
        }
      }
      if (pltArea * PLT_FAST_RATIO < totalArea)
      {
        m_doPlt = false;
      }
      else
      {
        m_doPlt = true;
      }
    }
    
    
    #if X0038_LAMBDA_FROM_QP_CAPABILITY
    int EncCfg::getQPForPicture(const uint32_t gopIndex, const Slice *pSlice) const
    {
      const int lumaQpBDOffset = pSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA);
      int qp;
    
      if (getCostMode()==COST_LOSSLESS_CODING)
      {
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #if JVET_AHG14_LOSSLESS
        qp = LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP - ( ( pSlice->getSPS()->getBitDepth( CHANNEL_TYPE_LUMA ) - 8 ) * 6 );
    #else
    
        qp=LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP;
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #endif
    
      }
      else
      {
        const SliceType sliceType=pSlice->getSliceType();
    
        qp = getBaseQP();
    
        // switch at specific qp and keep this qp offset
        static int appliedSwitchDQQ = 0; /* TODO: MT */
        if( pSlice->getPOC() == getSwitchPOC() )
        {
          appliedSwitchDQQ = getSwitchDQP();
        }
        qp += appliedSwitchDQQ;
    
    #if QP_SWITCHING_FOR_PARALLEL
        const int* pdQPs = getdQPs();
        if ( pdQPs )
        {
    
          qp += pdQPs[pSlice->getPOC() / (m_compositeRefEnabled ? 2 : 1)];
    
        }
    #endif
    
        if(sliceType==I_SLICE)
        {
          qp += getIntraQPOffset();
        }
        else
        {
    #if SHARP_LUMA_DELTA_QP
          // Only adjust QP when not lossless
          if (!(( getMaxDeltaQP() == 0 ) && (!getLumaLevelToDeltaQPMapping().isEnabled()) && (qp == -lumaQpBDOffset ) && (pSlice->getPPS()->getTransquantBypassEnabledFlag())))
    #else
          if (!(( getMaxDeltaQP() == 0 ) && (qp == -lumaQpBDOffset ) && (pSlice->getPPS()->getTransquantBypassEnabledFlag())))
    #endif
    
          {
            const GOPEntry &gopEntry=getGOPEntry(gopIndex);
            // adjust QP according to the QP offset for the GOP entry.
            qp +=gopEntry.m_QPOffset;
    
            // adjust QP according to QPOffsetModel for the GOP entry.
            double dqpOffset=qp*gopEntry.m_QPOffsetModelScale+gopEntry.m_QPOffsetModelOffset+0.5;
            int qpOffset = (int)floor(Clip3<double>(0.0, 3.0, dqpOffset));
            qp += qpOffset ;
          }
        }
    
    #if !QP_SWITCHING_FOR_PARALLEL
        // modify QP if a fractional QP was originally specified, cause dQPs to be 0 or 1.
        const int* pdQPs = getdQPs();
        if ( pdQPs )
        {
          qp += pdQPs[ pSlice->getPOC() ];
        }
    #endif
      }
      qp = Clip3( -lumaQpBDOffset, MAX_QP, qp );
      return qp;
    }
    #endif