Skip to content
Snippets Groups Projects
EncLib.cpp 94 KiB
Newer Older
  • Learn to ignore specific revisions
  •                                                   pps.getDeblockingFilterCrTcOffsetDiv2() != 0;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    
      pps.setDeblockingFilterControlPresentFlag(deblockingFilterControlPresentFlag);
    
      pps.setCabacInitPresentFlag(CABAC_INIT_PRESENT_FLAG);
      pps.setLoopFilterAcrossSlicesEnabledFlag( m_bLFCrossSliceBoundaryFlag );
    
    
      bool chromaQPOffsetNotZero = false;
    
      if( pps.getQpOffset(COMPONENT_Cb) != 0 || pps.getQpOffset(COMPONENT_Cr) != 0 || pps.getJointCbCrQpOffsetPresentFlag() || pps.getSliceChromaQpFlag() || pps.getCuChromaQpOffsetListEnabledFlag() )
      {
    
        chromaQPOffsetNotZero = true;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    
    
      bool chromaDbfOffsetNotSameAsLuma = true;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if !DB_PARAM_TID 
    
      if( pps.getDeblockingFilterCbBetaOffsetDiv2() == pps.getDeblockingFilterBetaOffsetDiv2() && pps.getDeblockingFilterCrBetaOffsetDiv2() == pps.getDeblockingFilterBetaOffsetDiv2()
         && pps.getDeblockingFilterCbTcOffsetDiv2() == pps.getDeblockingFilterTcOffsetDiv2() && pps.getDeblockingFilterCrTcOffsetDiv2() == pps.getDeblockingFilterTcOffsetDiv2() )
      {
    
        chromaDbfOffsetNotSameAsLuma = false;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    
    Zhipin Deng's avatar
    Zhipin Deng committed
    #if !JVET_S0052_RM_SEPARATE_COLOUR_PLANE
    
      const uint32_t chromaArrayType = (int)sps.getSeparateColourPlaneFlag() ? 0 : sps.getChromaFormatIdc();
    
      if( ( chromaArrayType != CHROMA_400 ) && ( chromaQPOffsetNotZero || chromaDbfOffsetNotSameAsLuma ) )
    
      if ((sps.getChromaFormatIdc() != CHROMA_400) && (chromaQPOffsetNotZero || chromaDbfOffsetNotSameAsLuma))
    
    
      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);
    
    Brian Heng's avatar
    Brian Heng committed
      pps.setPictureHeaderExtensionPresentFlag(false);
    
    Hendry's avatar
    Hendry committed
      pps.setRplInfoInPhFlag(getSliceLevelRpl() ? false : true);
      pps.setDbfInfoInPhFlag(getSliceLevelDblk() ? false : true);
      pps.setSaoInfoInPhFlag(getSliceLevelSao() ? false : true);
      pps.setAlfInfoInPhFlag(getSliceLevelAlf() ? false : true);
      pps.setWpInfoInPhFlag(getSliceLevelWp() ? false : true);
      pps.setQpDeltaInfoInPhFlag(getSliceLevelDeltaQp() ? false : true);
    
    
      pps.pcv = new PreCalcValues( sps, pps, true );
    
    Hendry's avatar
    Hendry committed
      pps.setRpl1IdxPresentFlag(sps.getRPL1IdxPresentFlag());
    
    Brian Heng's avatar
    Brian Heng committed
    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() );
    
    
    Brian Heng's avatar
    Brian Heng committed
      // merge list sizes
    
    Ling Li's avatar
    Ling Li committed
      picHeader.setMaxNumAffineMergeCand(getMaxNumAffineMergeCand());
    
    Brian Heng's avatar
    Brian Heng committed
      // copy partitioning constraints from SPS
      picHeader.setSplitConsOverrideFlag(false);
      picHeader.setMinQTSizes( sps.getMinQTSizes() );
      picHeader.setMaxMTTHierarchyDepths( sps.getMaxMTTHierarchyDepths() );
      picHeader.setMaxBTSizes( sps.getMaxBTSizes() );
      picHeader.setMaxTTSizes( sps.getMaxTTSizes() );
    
      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);
      }
    
    Brian Heng's avatar
    Brian Heng committed
    
      // virtual boundaries
    
      if( sps.getVirtualBoundariesEnabledFlag() )
      {
        picHeader.setVirtualBoundariesPresentFlag( sps.getVirtualBoundariesPresentFlag() );
        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);
        }
    
    Brian Heng's avatar
    Brian Heng committed
      }
    
      // gradual decoder refresh flag
      picHeader.setGdrPicFlag(false);
    
    Brian Heng's avatar
    Brian Heng committed
      // BDOF / DMVR / PROF
    
      picHeader.setDisBdofFlag(false);
      picHeader.setDisDmvrFlag(false);
      picHeader.setDisProfFlag(false);
    
    #if JVET_W0097_GPM_MMVD_TM
      if (sps.getUseGeo())
      {
    #if TOOLS
        if (getIntraPeriod() > 0)
        {
          if ((getSourceWidth() * getSourceHeight()) > (1920 * 1080))
          {
            picHeader.setGPMMMVDTableFlag(false);
          }
          else
          {
            picHeader.setGPMMMVDTableFlag(true);
          }
        }
        else
        {
          picHeader.setGPMMMVDTableFlag(true);
        }
    #else
      picHeader.setGPMMMVDTableFlag(false);
    #endif
      }
    #endif
    
    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);
    
      // To allocate one additional memory for RPL of POC1 (first bottom field) which is not specified in cfg file
      sps.createRPLList0(numRPLCandidates + (isFieldCoding ? 1 : 0));
      sps.createRPLList1(numRPLCandidates + (isFieldCoding ? 1 : 0));
    
    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);
    
          rpl->setInterLayerPresentFlag( sps.getInterLayerPresentFlag() );
          // inter-layer reference picture is not signaled in SPS RPL, SPS is shared currently
          rpl->setNumberOfInterLayerPictures( 0 );
    
    Hendry's avatar
    Hendry committed
    
          for (int k = 0; k < ge.m_numRefPics; k++)
          {
    
    #if JVET_S0045_SIGN
            rpl->setRefPicIdentifier(k, -ge.m_deltaRefPics[k], 0, false, 0);
    #else
    
            rpl->setRefPicIdentifier( k, ge.m_deltaRefPics[k], 0, false, 0 );
    
      if (isFieldCoding)
      {
        // To set RPL of POC1 (first bottom field) which is not specified in cfg file
        for (int i = 0; i < 2; i++)
        {
          rplList = (i == 0) ? sps.getRPLList0() : sps.getRPLList1();
          rpl = rplList->getReferencePictureList(numRPLCandidates);
          rpl->setNumberOfShorttermPictures(1);
          rpl->setNumberOfLongtermPictures(0);
          rpl->setNumberOfActivePictures(1);
          rpl->setLtrpInSliceHeaderFlag(0);
    
    #if JVET_S0045_SIGN
          rpl->setRefPicIdentifier(0, -1, 0, false, 0);
    #else
    
          rpl->setRefPicIdentifier(0, 1, 0, false, 0);
    
    Hendry's avatar
    Hendry committed
      bool isRpl1CopiedFromRpl0 = true;
      for( int i = 0; isRpl1CopiedFromRpl0 && i < numRPLCandidates; i++)
      {
        if( sps.getRPLList0()->getReferencePictureList(i)->getNumRefEntries() == sps.getRPLList1()->getReferencePictureList(i)->getNumRefEntries() )
        {
          for( int j = 0; isRpl1CopiedFromRpl0 && j < sps.getRPLList0()->getReferencePictureList(i)->getNumRefEntries(); j++ )
          {
            if( sps.getRPLList0()->getReferencePictureList(i)->getRefPicIdentifier(j) != sps.getRPLList1()->getReferencePictureList(i)->getRefPicIdentifier(j) )
            {
              isRpl1CopiedFromRpl0 = false;
            }
          }
        }
        else
        {
          isRpl1CopiedFromRpl0 = false;
        }
      }
      sps.setRPL1CopyFromRPL0Flag(isRpl1CopiedFromRpl0);
    
    
      //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_intraPeriod < 0)  //Only for RA
    
    Hendry's avatar
    Hendry committed
      {
        *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_intraPeriod < 0)
    
    Fabrice Le Léannec's avatar
    Fabrice Le Léannec committed
        if (POCCurr < (2 * m_iGOPSize + 2))
    
          int candidateIdx = (POCCurr + m_iGOPSize - 1 >= fullListNum + partialListNum) ? GOPid : POCCurr + m_iGOPSize - 1;
          rpl0Idx = candidateIdx;
          rpl1Idx = candidateIdx;
    
    Hendry's avatar
    Hendry committed
        }
        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_intraPeriod > 0 && getDecodingRefreshType() > 0)
    
          int POCIndex = POCCurr % m_intraPeriod;
    
    Hendry's avatar
    Hendry committed
          if (POCIndex == 0)
    
          {
            POCIndex = m_intraPeriod;
          }
    
    Hendry's avatar
    Hendry committed
          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;
    
      int rplPeriod = m_intraPeriod;
    
      if( rplPeriod < 0 )  //Need to check if it is low delay or RA but with no RAP
      {
        if( slice->getSPS()->getRPLList0()->getReferencePictureList(1)->getRefPicIdentifier(0) * slice->getSPS()->getRPLList1()->getReferencePictureList(1)->getRefPicIdentifier(0) < 0)
        {
          rplPeriod = m_iGOPSize * 2;
        }
      }
    
      if (rplPeriod < 0)
    
    Fabrice Le Léannec's avatar
    Fabrice Le Léannec committed
        if (POCCurr < (2 * m_iGOPSize + 2))
    
          int candidateIdx = (POCCurr + m_iGOPSize - 1 >= fullListNum + partialListNum) ? GOPid : POCCurr + m_iGOPSize - 1;
          slice->setRPL0idx(candidateIdx);
          slice->setRPL1idx(candidateIdx);
    
    Hendry's avatar
    Hendry committed
        }
        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( rplPeriod > 0 )
    
          int POCIndex = POCCurr % rplPeriod;
    
    Hendry's avatar
    Hendry committed
          if (POCIndex == 0)
    
            POCIndex = rplPeriod;
    
    Hendry's avatar
    Hendry committed
          if (POCIndex == m_RPLList0[extraNum].m_POC)
          {
            slice->setRPL0idx(extraNum);
            slice->setRPL1idx(extraNum);
            extraNum++;
          }
        }
      }
    
    
      if (slice->getPic()->fieldPic)
      {
        // To set RPL index of POC1 (first bottom field)
        if (POCCurr == 1)
        {
          slice->setRPL0idx(getRPLCandidateSize(0));
          slice->setRPL1idx(getRPLCandidateSize(0));
        }
    
        else if( rplPeriod < 0 )
    
        {
          // To set RPL indexes for LD
          int numRPLCandidates = getRPLCandidateSize(0);
          if (POCCurr < numRPLCandidates - m_iGOPSize + 2)
          {
            slice->setRPL0idx(POCCurr + m_iGOPSize - 2);
            slice->setRPL1idx(POCCurr + m_iGOPSize - 2);
          }
          else
          {
            if (POCCurr%m_iGOPSize == 0)
            {
              slice->setRPL0idx(m_iGOPSize - 2);
              slice->setRPL1idx(m_iGOPSize - 2);
            }
            else if (POCCurr%m_iGOPSize == 1)
            {
              slice->setRPL0idx(m_iGOPSize - 1);
              slice->setRPL1idx(m_iGOPSize - 1);
            }
            else
            {
              slice->setRPL0idx(POCCurr % m_iGOPSize - 2);
              slice->setRPL1idx(POCCurr % m_iGOPSize - 2);
            }
          }
        }
      }
    
    
    Hendry's avatar
    Hendry committed
      const ReferencePictureList *rpl0 = (slice->getSPS()->getRPLList0()->getReferencePictureList(slice->getRPL0idx()));
      const ReferencePictureList *rpl1 = (slice->getSPS()->getRPLList1()->getReferencePictureList(slice->getRPL1idx()));
      slice->setRPL0(rpl0);
      slice->setRPL1(rpl1);
    }
    
    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)
      {
    
      }
      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
        {
            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