Skip to content
Snippets Groups Projects
EncLib.cpp 66.2 KiB
Newer Older
  • Learn to ignore specific revisions
  •   sps.setUseLFNST                            ( m_LFNST );
    
      sps.setSBTMVPEnabledFlag                  ( m_SubPuMvpMode );
    
      sps.setAMVREnabledFlag                ( m_ImvMode != IMV_OFF );
    
      sps.setBDOFEnabledFlag                    ( m_BIO );
    
      sps.setUseAffine             ( m_Affine );
      sps.setUseAffineType         ( m_AffineType );
    
      sps.setUseLMChroma           ( m_LMChroma ? true : false );
      sps.setCclmCollocatedChromaFlag( m_cclmCollocatedChromaFlag );
      sps.setUseMTS                ( m_IntraMTS || m_InterMTS || m_ImplicitMTS );
      sps.setUseIntraMTS           ( m_IntraMTS );
      sps.setUseInterMTS           ( m_InterMTS );
    
        sps.setMaxSbtSize                       ( std::min((int)(1 << m_log2MaxTbSize), m_iSourceWidth >= 1920 ? 64 : 32) );
    
      sps.setUseSMVD                ( m_SMVD );
    
      sps.setUseGBi                ( m_GBi );
    
    #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET
    
      sps.setLadfEnabled           ( m_LadfEnabled );
    
        sps.setLadfNumIntervals    ( m_LadfNumIntervals );
    
        for ( int k = 0; k < m_LadfNumIntervals; k++ )
        {
    
          sps.setLadfQpOffset( m_LadfQpOffset[k], k );
          sps.setLadfIntervalLowerBound( m_LadfIntervalLowerBound[k], k );
    
        }
        CHECK( m_LadfIntervalLowerBound[0] != 0, "abnormal value set to LadfIntervalLowerBound[0]" );
      }
    #endif
    
    
      sps.setUseMHIntra            ( m_MHIntra );
      sps.setUseTriangle           ( m_Triangle );
    
    Seungsoo Jeong's avatar
    Seungsoo Jeong committed
      sps.setUseMMVD               ( m_MMVD );
    
      sps.setFpelMmvdEnabledFlag   (( m_MMVD ) ? m_allowDisFracMMVD : false);
    
      sps.setBdofDmvrSlicePresentFlag(m_DMVR || m_BIO);
    
      sps.setAffineAmvrEnabledFlag              ( m_AffineAmvr );
    
      sps.setUseDMVR                            ( m_DMVR );
    
    Yu Han's avatar
    Yu Han committed
      sps.setIBCFlag                            ( m_IBCMode);
    
      sps.setWrapAroundEnabledFlag                      ( m_wrapAround );
    
      sps.setWrapAroundOffset                   ( m_wrapAroundOffset );
    
      // ADD_NEW_TOOL : (encoder lib) set tool enabling flags and associated parameters here
    
      sps.setUseISP                             ( m_ISP );
    
    Taoran Lu's avatar
    Taoran Lu committed
      sps.setUseReshaper                        ( m_lumaReshapeEnable );
    
      sps.setUseMIP                ( m_MIP );
    
    Karsten Suehring's avatar
    Karsten Suehring committed
      int minCUSize =  sps.getMaxCUWidth() >> sps.getLog2DiffMaxMinCodingBlockSize();
    
      int log2MinCUSize = 0;
      while(minCUSize > 1)
      {
        minCUSize >>= 1;
        log2MinCUSize++;
      }
    
      sps.setLog2MinCodingBlockSize(log2MinCUSize);
    
    
    
      sps.setTransformSkipEnabledFlag(m_useTransformSkip);
      sps.setBDPCMEnabledFlag(m_useBDPCM);
    
    
      sps.setSPSTemporalMVPEnabledFlag((getTMVPModeId() == 2 || getTMVPModeId() == 1));
    
    
      sps.setLog2MaxTbSize   ( m_log2MaxTbSize );
    
    
      for (uint32_t channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++)
      {
        sps.setBitDepth      (ChannelType(channelType), m_bitDepth[channelType] );
        sps.setQpBDOffset  (ChannelType(channelType), (6 * (m_bitDepth[channelType] - 8)));
    
    Hongtao Wang's avatar
    Hongtao Wang committed
        sps.setMinQpPrimeTsMinus4(ChannelType(channelType), (6 * (m_bitDepth[channelType] - m_inputBitDepth[channelType])));
    
      sps.setUseWP( m_useWeightedPred );
      sps.setUseWPBiPred( m_useWeightedBiPred );
    
    
      sps.setSAOEnabledFlag( m_bUseSAO );
    
      sps.setJointCbCrEnabledFlag( m_JointCbCrMode );
    
      sps.setMaxTLayers( m_maxTempLayer );
      sps.setTemporalIdNestingFlag( ( m_maxTempLayer == 1 ) ? true : false );
    
    
      for (int i = 0; i < std::min(sps.getMaxTLayers(), (uint32_t) MAX_TLAYER); i++ )
    
      {
        sps.setMaxDecPicBuffering(m_maxDecPicBuffering[i], i);
        sps.setNumReorderPics(m_numReorderPics[i], i);
      }
    
      sps.setScalingListFlag ( (m_useScalingListId == SCALING_LIST_OFF) ? 0 : 1 );
    
      sps.setALFEnabledFlag( m_alf );
    
      sps.setVuiParametersPresentFlag(getVuiParametersPresentFlag());
    
    
    Virginie Drugeon's avatar
    Virginie Drugeon committed
      if (sps.getVuiParametersPresentFlag())
      {
        VUI* pcVUI = sps.getVuiParameters();
        pcVUI->setAspectRatioInfoPresentFlag(getAspectRatioInfoPresentFlag());
        pcVUI->setAspectRatioIdc(getAspectRatioIdc());
        pcVUI->setSarWidth(getSarWidth());
        pcVUI->setSarHeight(getSarHeight());
        pcVUI->setColourDescriptionPresentFlag(getColourDescriptionPresentFlag());
        pcVUI->setColourPrimaries(getColourPrimaries());
        pcVUI->setTransferCharacteristics(getTransferCharacteristics());
        pcVUI->setMatrixCoefficients(getMatrixCoefficients());
        pcVUI->setFieldSeqFlag(false);
        pcVUI->setChromaLocInfoPresentFlag(getChromaLocInfoPresentFlag());
        pcVUI->setChromaSampleLocTypeTopField(getChromaSampleLocTypeTopField());
        pcVUI->setChromaSampleLocTypeBottomField(getChromaSampleLocTypeBottomField());
        pcVUI->setChromaSampleLocType(getChromaSampleLocType());
        pcVUI->setOverscanInfoPresentFlag(getOverscanInfoPresentFlag());
        pcVUI->setOverscanAppropriateFlag(getOverscanAppropriateFlag());
        pcVUI->setVideoSignalTypePresentFlag(getVideoSignalTypePresentFlag());
        pcVUI->setVideoFullRangeFlag(getVideoFullRangeFlag());
      }
    
    
      sps.setNumLongTermRefPicSPS(NUM_LONG_TERM_REF_PIC_SPS);
      CHECK(!(NUM_LONG_TERM_REF_PIC_SPS <= MAX_NUM_LONG_TERM_REF_PICS), "Unspecified error");
      for (int k = 0; k < NUM_LONG_TERM_REF_PIC_SPS; k++)
      {
        sps.setLtRefPicPocLsbSps(k, 0);
        sps.setUsedByCurrPicLtSPSFlag(k, 0);
      }
    
      sps.setChromaQpMappingTableFromParams(m_chromaQpMappingTableParams, sps.getQpBDOffset(CHANNEL_TYPE_CHROMA));
    
    
    #if U0132_TARGET_BITS_SATURATION
      if( getPictureTimingSEIEnabled() || getDecodingUnitInfoSEIEnabled() || getCpbSaturationEnabled() )
    #else
      if( getPictureTimingSEIEnabled() || getDecodingUnitInfoSEIEnabled() )
    #endif
      {
        xInitHrdParameters(sps);
      }
      if( getBufferingPeriodSEIEnabled() || getPictureTimingSEIEnabled() || getDecodingUnitInfoSEIEnabled() )
      {
    
    Virginie Drugeon's avatar
    Virginie Drugeon committed
        sps.setHrdParametersPresentFlag( true );
    
      }
    
      // Set up SPS range extension settings
      sps.getSpsRangeExtension().setTransformSkipRotationEnabledFlag(m_transformSkipRotationEnabledFlag);
      sps.getSpsRangeExtension().setTransformSkipContextEnabledFlag(m_transformSkipContextEnabledFlag);
      for (uint32_t signallingModeIndex = 0; signallingModeIndex < NUMBER_OF_RDPCM_SIGNALLING_MODES; signallingModeIndex++)
      {
        sps.getSpsRangeExtension().setRdpcmEnabledFlag(RDPCMSignallingMode(signallingModeIndex), m_rdpcmEnabledFlag[signallingModeIndex]);
      }
      sps.getSpsRangeExtension().setExtendedPrecisionProcessingFlag(m_extendedPrecisionProcessingFlag);
      sps.getSpsRangeExtension().setIntraSmoothingDisabledFlag( m_intraSmoothingDisabledFlag );
      sps.getSpsRangeExtension().setHighPrecisionOffsetsEnabledFlag(m_highPrecisionOffsetsEnabledFlag);
      sps.getSpsRangeExtension().setPersistentRiceAdaptationEnabledFlag(m_persistentRiceAdaptationEnabledFlag);
      sps.getSpsRangeExtension().setCabacBypassAlignmentEnabledFlag(m_cabacBypassAlignmentEnabledFlag);
    
    Hendry's avatar
    Hendry committed
    
      if (m_uiIntraPeriod < 0)
        sps.setRPL1CopyFromRPL0Flag(true);
    
      m_encHRD.initHRDParameters((EncCfg*) this);
    
    Virginie Drugeon's avatar
    Virginie Drugeon committed
      HRDParameters *hrdParams = sps.getHrdParameters();
      *hrdParams = m_encHRD.getHRDParameters();
    
      TimingInfo *timingInfo = sps.getTimingInfo();
      *timingInfo = m_encHRD.getTimingInfo();
    
    }
    
    void EncLib::xInitPPS(PPS &pps, const SPS &sps)
    {
      // pps ID already initialised.
      pps.setSPSId(sps.getSPSId());
    
    
      pps.setConstantSliceHeaderParamsEnabledFlag(getConstantSliceHeaderParamsEnabledFlag());
      pps.setPPSDepQuantEnabledIdc(getPPSDepQuantEnabledIdc());
      pps.setPPSRefPicListSPSIdc0(getPPSRefPicListSPSIdc0());
      pps.setPPSRefPicListSPSIdc1(getPPSRefPicListSPSIdc1());
      pps.setPPSTemporalMVPEnabledIdc(getPPSTemporalMVPEnabledIdc());
      pps.setPPSMvdL1ZeroIdc(getPPSMvdL1ZeroIdc());
      pps.setPPSCollocatedFromL0Idc(getPPSCollocatedFromL0Idc());
      pps.setPPSSixMinusMaxNumMergeCandPlus1(getPPSSixMinusMaxNumMergeCandPlus1());
    
      pps.setPPSFiveMinusMaxNumSubblockMergeCandPlus1(getPPSFiveMinusMaxNumSubblockMergeCandPlus1());
    
      pps.setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1());
    
    
      pps.setConstrainedIntraPred( m_bUseConstrainedIntraPred );
    
      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 )
      {
        pps.setUseDQP(true);
    
        pps.setCuQpDeltaSubdiv( 0 );
    
        pps.setCuQpDeltaSubdiv( m_cuQpDeltaSubdiv );
    
        pps.setCuQpDeltaSubdiv( 0 );
    
      if ( m_cuChromaQpOffsetSubdiv >= 0 )
      {
    
        pps.setCuChromaQpOffsetSubdiv(m_cuChromaQpOffsetSubdiv);
        pps.clearChromaQpOffsetList();
        pps.setChromaQpOffsetListEntry(1, 6, 6, 6);
    
        /* todo, insert table entries from command line (NB, 0 should not be touched) */
      }
      else
      {
    
        pps.setCuChromaQpOffsetSubdiv(0);
        pps.clearChromaQpOffsetList();
    
      }
      pps.getPpsRangeExtension().setCrossComponentPredictionEnabledFlag(m_crossComponentPredictionEnabledFlag);
      pps.getPpsRangeExtension().setLog2SaoOffsetScale(CHANNEL_TYPE_LUMA,   m_log2SaoOffsetScale[CHANNEL_TYPE_LUMA  ]);
      pps.getPpsRangeExtension().setLog2SaoOffsetScale(CHANNEL_TYPE_CHROMA, m_log2SaoOffsetScale[CHANNEL_TYPE_CHROMA]);
    
      {
        int baseQp = 26;
        if( 16 == getGOPSize() )
        {
          baseQp = getBaseQP()-24;
        }
        else
        {
          baseQp = getBaseQP()-26;
        }
    
        const int minDQP = -26 + sps.getQpBDOffset(CHANNEL_TYPE_LUMA);
    
        pps.setPicInitQPMinus26( std::min( maxDQP, std::max( minDQP, baseQp ) ));
      }
    
    #if ER_CHROMA_QP_WCG_PPS
      if (getWCGChromaQPControl().isEnabled())
      {
        const int baseQp=m_iQP+pps.getPPSId();
        const double chromaQp = m_wcgChromaQpControl.chromaQpScale * baseQp + m_wcgChromaQpControl.chromaQpOffset;
        const double dcbQP = m_wcgChromaQpControl.chromaCbQpScale * chromaQp;
        const double dcrQP = m_wcgChromaQpControl.chromaCrQpScale * chromaQp;
        const int cbQP =(int)(dcbQP + ( dcbQP < 0 ? -0.5 : 0.5) );
        const int crQP =(int)(dcrQP + ( dcrQP < 0 ? -0.5 : 0.5) );
        pps.setQpOffset(COMPONENT_Cb, Clip3( -12, 12, min(0, cbQP) + m_chromaCbQpOffset ));
        pps.setQpOffset(COMPONENT_Cr, Clip3( -12, 12, min(0, crQP) + m_chromaCrQpOffset));
    
        pps.setQpOffset(JOINT_CbCr,   Clip3( -12, 12, ( min(0, cbQP) + min(0, crQP) ) / 2 + m_chromaCbCrQpOffset));
    
      }
      else
      {
    #endif
      pps.setQpOffset(COMPONENT_Cb, m_chromaCbQpOffset );
      pps.setQpOffset(COMPONENT_Cr, m_chromaCrQpOffset );
    
      pps.setQpOffset(JOINT_CbCr, m_chromaCbCrQpOffset );
    
    #if ER_CHROMA_QP_WCG_PPS
      }
    #endif
    #if W0038_CQP_ADJ
      bool bChromaDeltaQPEnabled = false;
      {
        bChromaDeltaQPEnabled = ( m_sliceChromaQpOffsetIntraOrPeriodic[0] || m_sliceChromaQpOffsetIntraOrPeriodic[1] );
        if( !bChromaDeltaQPEnabled )
        {
          for( int i=0; i<m_iGOPSize; i++ )
          {
            if( m_GOPList[i].m_CbQPoffset || m_GOPList[i].m_CrQPoffset )
            {
              bChromaDeltaQPEnabled = true;
              break;
            }
          }
        }
      }
    
     #if ENABLE_QPA
      if ((getUsePerceptQPA() || getSliceChromaOffsetQpPeriodicity() > 0) && (getChromaFormatIdc() != CHROMA_400))
      {
        bChromaDeltaQPEnabled = true;
      }
     #endif
    
      pps.setSliceChromaQpFlag(bChromaDeltaQPEnabled);
    #endif
    
        !pps.getSliceChromaQpFlag() && sps.getUseDualITree()
    
        && (getChromaFormatIdc() != CHROMA_400))
    
        pps.setSliceChromaQpFlag(m_chromaCbQpOffsetDualTree != 0 || m_chromaCrQpOffsetDualTree != 0 || m_chromaCbCrQpOffsetDualTree != 0);
    
      }
    
      pps.setEntropyCodingSyncEnabledFlag( m_entropyCodingSyncEnabledFlag );
    
    Karsten Suehring's avatar
    Karsten Suehring committed
    
      pps.setSingleTileInPicFlag((m_iNumColumnsMinus1 == 0 && m_iNumRowsMinus1 == 0));
    
    
      pps.setUseWP( m_useWeightedPred );
      pps.setWPBiPred( m_useWeightedBiPred );
      pps.setOutputFlagPresentFlag( false );
    
      if ( getDeblockingFilterMetric() )
      {
        pps.setDeblockingFilterOverrideEnabledFlag(true);
        pps.setPPSDeblockingFilterDisabledFlag(false);
      }
      else
      {
        pps.setDeblockingFilterOverrideEnabledFlag( !getLoopFilterOffsetInPPS() );
        pps.setPPSDeblockingFilterDisabledFlag( getLoopFilterDisable() );
      }
    
      if (! pps.getPPSDeblockingFilterDisabledFlag())
      {
        pps.setDeblockingFilterBetaOffsetDiv2( getLoopFilterBetaOffset() );
        pps.setDeblockingFilterTcOffsetDiv2( getLoopFilterTcOffset() );
      }
      else
      {
        pps.setDeblockingFilterBetaOffsetDiv2(0);
        pps.setDeblockingFilterTcOffsetDiv2(0);
      }
    
      // deblockingFilterControlPresentFlag is true if any of the settings differ from the inferred values:
      const bool deblockingFilterControlPresentFlag = pps.getDeblockingFilterOverrideEnabledFlag() ||
                                                      pps.getPPSDeblockingFilterDisabledFlag()     ||
                                                      pps.getDeblockingFilterBetaOffsetDiv2() != 0 ||
                                                      pps.getDeblockingFilterTcOffsetDiv2() != 0;
    
      pps.setDeblockingFilterControlPresentFlag(deblockingFilterControlPresentFlag);
    
      pps.setLog2ParallelMergeLevelMinus2   (m_log2ParallelMergeLevelMinus2 );
      pps.setCabacInitPresentFlag(CABAC_INIT_PRESENT_FLAG);
      pps.setLoopFilterAcrossSlicesEnabledFlag( m_bLFCrossSliceBoundaryFlag );
    
    
      int histogram[MAX_NUM_REF + 1];
      for( int i = 0; i <= MAX_NUM_REF; i++ )
      {
        histogram[i]=0;
      }
      for( int i = 0; i < getGOPSize(); i++)
      {
    
    Hendry's avatar
    Hendry committed
        CHECK(!(getRPLEntry(0, i).m_numRefPicsActive >= 0 && getRPLEntry(0, i).m_numRefPicsActive <= MAX_NUM_REF), "Unspecified error");
        histogram[getRPLEntry(0, i).m_numRefPicsActive]++;
    
      }
    
      int maxHist=-1;
      int bestPos=0;
      for( int i = 0; i <= MAX_NUM_REF; i++ )
      {
        if(histogram[i]>maxHist)
        {
          maxHist=histogram[i];
          bestPos=i;
        }
      }
      CHECK(!(bestPos <= 15), "Unspecified error");
    
        pps.setNumRefIdxL0DefaultActive(bestPos);
    
      pps.setNumRefIdxL1DefaultActive(bestPos);
      pps.setTransquantBypassEnabledFlag(getTransquantBypassEnabledFlag());
    
      pps.setLog2MaxTransformSkipBlockSize(m_log2MaxTransformSkipBlockSize);
    
      pps.setLoopFilterAcrossVirtualBoundariesDisabledFlag( m_loopFilterAcrossVirtualBoundariesDisabledFlag );
      pps.setNumVerVirtualBoundaries            ( m_numVerVirtualBoundaries );
      pps.setNumHorVirtualBoundaries            ( m_numHorVirtualBoundaries );
      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 );
      }
    
    
      pps.pcv = new PreCalcValues( sps, pps, true );
    
    Hendry's avatar
    Hendry committed
      pps.setRpl1IdxPresentFlag(sps.getRPL1IdxPresentFlag());
    
    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)
      {
        if (POCCurr < 10)
        {
          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 (POCCurr < 10)
        {
          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);
    }
    
    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." );
        }
      }
    }
    
    
    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)
      {
        qp=LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP;
      }
      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