Skip to content
Snippets Groups Projects
EncGOP.cpp 205 KiB
Newer Older
  • Learn to ignore specific revisions
  •     {
          m_iLastIDR = pocCurr;
        }
    
        // start a new access unit: create an entry in the list of output access units
        AccessUnit accessUnit;
    
        accessUnit.temporalId = m_pcCfg->getGOPEntry( iGOPid ).m_temporalId;
    
        xGetBuffer( rcListPic, rcListPicYuvRecOut,
                    iNumPicRcvd, iTimeOffset, pcPic, pocCurr, isField );
    
    Brian Heng's avatar
    Brian Heng committed
        picHeader = pcPic->cs->picHeader;
    
        picHeader->setSPSId( pcPic->cs->pps->getSPSId() );
        picHeader->setPPSId( pcPic->cs->pps->getPPSId() );
    
    Brian Heng's avatar
    Brian Heng committed
        picHeader->setSplitConsOverrideFlag(false);
    
        // initial two flags to be false
        picHeader->setPicInterSliceAllowedFlag(false);
        picHeader->setPicIntraSliceAllowedFlag(false);
    
    #if ER_CHROMA_QP_WCG_PPS
    
        // th this is a hot fix for the choma qp control
        if( m_pcEncLib->getWCGChromaQPControl().isEnabled() && m_pcEncLib->getSwitchPOC() != -1 )
        {
          static int usePPS = 0; /* TODO: MT */
          if( pocCurr == m_pcEncLib->getSwitchPOC() )
          {
            usePPS = 1;
          }
          const PPS *pPPS = m_pcEncLib->getPPS(usePPS);
          // replace the pps with a more appropriated one
          pcPic->cs->pps = pPPS;
        }
    
        // create objects based on the picture size
        const int picWidth = pcPic->cs->pps->getPicWidthInLumaSamples();
        const int picHeight = pcPic->cs->pps->getPicHeightInLumaSamples();
        const int maxCUWidth = pcPic->cs->sps->getMaxCUWidth();
        const int maxCUHeight = pcPic->cs->sps->getMaxCUHeight();
        const ChromaFormat chromaFormatIDC = pcPic->cs->sps->getChromaFormatIdc();
    
        const int maxTotalCUDepth = floorLog2(maxCUWidth) - pcPic->cs->sps->getLog2MinCodingBlockSize();
    
    
        m_pcSliceEncoder->create( picWidth, picHeight, chromaFormatIDC, maxCUWidth, maxCUHeight, maxTotalCUDepth );
    
    
    #if ENABLE_SPLIT_PARALLELISM
    
        pcPic->scheduler.init( pcPic->cs->pcv->heightInCtus, pcPic->cs->pcv->widthInCtus, 1                          , 0                             , m_pcCfg->getNumSplitThreads() );
    #endif
        pcPic->createTempBuffers( pcPic->cs->pps->pcv->maxCUWidth );
    
        pcPic->cs->createCoeffs((bool)pcPic->cs->sps->getPLTMode());
    
    
        //  Slice data initialization
        pcPic->clearSliceBuffer();
        pcPic->allocateNewSlice();
        m_pcSliceEncoder->setSliceSegmentIdx(0);
    
    
        m_pcSliceEncoder->initEncSlice(pcPic, iPOCLast, pocCurr, iGOPid, pcSlice, isField
          , isEncodeLtRef
        );
    
    
        DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "poc", pocCurr ) ) );
        DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "final", 0 ) ) );
    
    #if !SHARP_LUMA_DELTA_QP
        //Set Frame/Field coding
        pcPic->fieldPic = isField;
    #endif
    
    
        pcSlice->setLastIDR(m_iLastIDR);
    
        pcSlice->setIndependentSliceIdx(0);
    
        if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='P')
        {
          pcSlice->setSliceType(P_SLICE);
        }
        if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='I')
        {
          pcSlice->setSliceType(I_SLICE);
        }
    
        pcSlice->setTLayer(m_pcCfg->getGOPEntry(iGOPid).m_temporalId);
    
        // Set the nal unit type
        pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField));
    
        // set two flags according to slice type presented in the picture
        if (pcSlice->getSliceType() != I_SLICE)
    
          picHeader->setPicInterSliceAllowedFlag(true);
    
        if (pcSlice->getSliceType() == I_SLICE)
    
          picHeader->setPicIntraSliceAllowedFlag(true);
    
        picHeader->setGdrOrIrapPicFlag(picHeader->getGdrPicFlag() || pcSlice->isIRAP());
    
          if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL
            || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP
            || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)  // IRAP picture
    
    #if JVET_R0041
            m_associatedIRAPType[pcPic->layerId] = pcSlice->getNalUnitType();
            m_associatedIRAPPOC[pcPic->layerId] = pocCurr;
    #else
    
            m_associatedIRAPType = pcSlice->getNalUnitType();
            m_associatedIRAPPOC = pocCurr;
    
    #if JVET_R0041
          pcSlice->setAssociatedIRAPType(m_associatedIRAPType[pcPic->layerId]);
          pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC[pcPic->layerId]);
    #else
    
          pcSlice->setAssociatedIRAPType(m_associatedIRAPType);
          pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC);
    
        }
    
        pcSlice->decodingRefreshMarking(m_pocCRA, m_bRefreshPending, rcListPic, m_pcCfg->getEfficientFieldIRAPEnabled());
    
        if (m_pcCfg->getUseCompositeRef() && isEncodeLtRef)
        {
          setUseLTRef(true);
          setPrepareLTRef(false);
          setNewestBgPOC(pocCurr);
          setLastLTRefPoc(pocCurr);
        }
    
        else if (m_pcCfg->getUseCompositeRef() && getLastLTRefPoc() >= 0 && getEncodedLTRef()==false && !getPicBg()->getSpliceFull() && (pocCurr - getLastLTRefPoc()) > (m_pcCfg->getFrameRate() * 2))
    
        {
          setUseLTRef(false);
          setPrepareLTRef(false);
          setEncodedLTRef(true);
          setNewestBgPOC(-1);
          setLastLTRefPoc(-1);
        }
    
    
    Hendry's avatar
    Hendry committed
        if (m_pcCfg->getUseCompositeRef() && m_picBg->getSpliceFull() && getUseLTRef())
        {
          m_pcEncLib->selectReferencePictureList(pcSlice, pocCurr, iGOPid, m_bgPOC);
        }
        else
        {
          m_pcEncLib->selectReferencePictureList(pcSlice, pocCurr, iGOPid, -1);
        }
    
          if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL
            || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP
            || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)  // IRAP picture
    
    #if JVET_R0041
            m_associatedIRAPType[pcPic->layerId] = pcSlice->getNalUnitType();
            m_associatedIRAPPOC[pcPic->layerId] = pocCurr;
    #else
    
            m_associatedIRAPType = pcSlice->getNalUnitType();
            m_associatedIRAPPOC = pocCurr;
    
    #if JVET_R0041
          pcSlice->setAssociatedIRAPType(m_associatedIRAPType[pcPic->layerId]);
          pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC[pcPic->layerId]);
    #else
    
          pcSlice->setAssociatedIRAPType(m_associatedIRAPType);
          pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC);
    
        pcSlice->setEnableDRAPSEI(m_pcEncLib->getDependentRAPIndicationSEIEnabled());
    
        if (m_pcEncLib->getDependentRAPIndicationSEIEnabled())
    
        {
          // Only mark the picture as DRAP if all of the following applies:
          //  1) DRAP indication SEI messages are enabled
          //  2) The current picture is not an intra picture
          //  3) The current picture is in the DRAP period
          //  4) The current picture is a trailing picture
    
          pcSlice->setDRAP(m_pcEncLib->getDependentRAPIndicationSEIEnabled() && m_pcEncLib->getDrapPeriod() > 0 && !pcSlice->isIntra() &&
                  pocCurr % m_pcEncLib->getDrapPeriod() == 0 && pocCurr > pcSlice->getAssociatedIRAPPOC());
    
          if (pcSlice->isDRAP())
          {
            int pocCycle = 1 << (pcSlice->getSPS()->getBitsForPOC());
    
            int deltaPOC = pocCurr > pcSlice->getAssociatedIRAPPOC() ? pocCurr - pcSlice->getAssociatedIRAPPOC() : pocCurr - ( pcSlice->getAssociatedIRAPPOC() & (pocCycle -1) );
    
            CHECK(deltaPOC > (pocCycle >> 1), "Use a greater value for POC wraparound to enable a POC distance between IRAP and DRAP of " << deltaPOC << ".");
    
            m_latestDRAPPOC = pocCurr;
    
            pcSlice->setTLayer(0); // Force DRAP picture to have temporal layer 0
          }
    
          pcSlice->setLatestDRAPPOC(m_latestDRAPPOC);
    
          pcSlice->setUseLTforDRAP(false); // When set, sets the associated IRAP as long-term in RPL0 at slice level, unless the associated IRAP is already included in RPL0 or RPL1 defined in SPS
    
          PicList::iterator iterPic = rcListPic.begin();
          Picture *rpcPic;
          while (iterPic != rcListPic.end())
          {
            rpcPic = *(iterPic++);
            if ( pcSlice->isDRAP() && rpcPic->getPOC() != pocCurr )
            {
                rpcPic->precedingDRAP = true;
            }
            else if ( !pcSlice->isDRAP() && rpcPic->getPOC() == pocCurr )
            {
              rpcPic->precedingDRAP = false;
            }
          }
        }
    
    
        if (pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPL0(), 0, false) != 0 || pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPL1(), 1, false) != 0 ||
    
            (m_pcEncLib->getDependentRAPIndicationSEIEnabled() && !pcSlice->isIRAP() && ( pcSlice->isDRAP() || !pcSlice->isPOCInRefPicList(pcSlice->getRPL0(), pcSlice->getAssociatedIRAPPOC())) )
    
          || (!pcSlice->isIRAP() && pcSlice->getPic()->cs->vps && m_pcEncLib->getNumRefLayers(pcSlice->getPic()->cs->vps->getGeneralLayerIdx(m_pcEncLib->getLayerId())))
    
          xCreateExplicitReferencePictureSetFromReference( pcSlice, rcListPic, pcSlice->getRPL0(), pcSlice->getRPL1() );
    
        pcSlice->applyReferencePictureListBasedMarking( rcListPic, pcSlice->getRPL0(), pcSlice->getRPL1(), pcSlice->getPic()->layerId, *(pcSlice->getPPS()));
    
          && !(pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL     // Check if not a leading picture
            || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL)
    
        if (pcSlice->isStepwiseTemporalLayerSwitchingPointCandidate(rcListPic))
    
            for(int ii=0;(ii<m_pcCfg->getGOPSize() && isSTSA==true);ii++)
    
    Hendry's avatar
    Hendry committed
              int lTid = m_pcCfg->getRPLEntry(0, ii).m_temporalId;
    
              if (lTid == pcSlice->getTLayer())
              {
                const ReferencePictureList* rpl0 = pcSlice->getSPS()->getRPLList0()->getReferencePictureList(ii);
                for (int jj = 0; jj < pcSlice->getRPL0()->getNumberOfActivePictures(); jj++)
                {
    
                  int tPoc = pcSlice->getPOC() - rpl0->getRefPicIdentifier(jj);
    
    Hendry's avatar
    Hendry committed
                  int kk = 0;
                  for (kk = 0; kk<m_pcCfg->getGOPSize(); kk++)
                  {
                    if (m_pcCfg->getRPLEntry(0, kk).m_POC == tPoc)
                    {
                      break;
                    }
                  }
                  int tTid = m_pcCfg->getRPLEntry(0, kk).m_temporalId;
                  if (tTid >= pcSlice->getTLayer())
                  {
                    isSTSA = false;
                    break;
                  }
                }
                const ReferencePictureList* rpl1 = pcSlice->getSPS()->getRPLList1()->getReferencePictureList(ii);
                for (int jj = 0; jj < pcSlice->getRPL1()->getNumberOfActivePictures(); jj++)
                {
    
                  int tPoc = pcSlice->getPOC() - rpl1->getRefPicIdentifier(jj);
    
    Hendry's avatar
    Hendry committed
                  int kk = 0;
                  for (kk = 0; kk<m_pcCfg->getGOPSize(); kk++)
                  {
                    if (m_pcCfg->getRPLEntry(1, kk).m_POC == tPoc)
                    {
                      break;
                    }
                  }
                  int tTid = m_pcCfg->getRPLEntry(1, kk).m_temporalId;
                  if (tTid >= pcSlice->getTLayer())
                  {
                    isSTSA = false;
                    break;
                  }
                }
              }
    
              pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA);
    
    Hendry's avatar
    Hendry committed
        if (m_pcCfg->getUseCompositeRef() && getUseLTRef() && (pocCurr > getLastLTRefPoc()))
        {
          pcSlice->setNumRefIdx(REF_PIC_LIST_0, (pcSlice->isIntra()) ? 0 : min(m_pcCfg->getRPLEntry(0, iGOPid).m_numRefPicsActive + 1, pcSlice->getRPL0()->getNumberOfActivePictures()));
          pcSlice->setNumRefIdx(REF_PIC_LIST_1, (!pcSlice->isInterB()) ? 0 : min(m_pcCfg->getRPLEntry(1, iGOPid).m_numRefPicsActive + 1, pcSlice->getRPL1()->getNumberOfActivePictures()));
        }
        else
        {
          pcSlice->setNumRefIdx(REF_PIC_LIST_0, (pcSlice->isIntra()) ? 0 : pcSlice->getRPL0()->getNumberOfActivePictures());
          pcSlice->setNumRefIdx(REF_PIC_LIST_1, (!pcSlice->isInterB()) ? 0 : pcSlice->getRPL1()->getNumberOfActivePictures());
        }
    
        if (m_pcCfg->getUseCompositeRef() && getPrepareLTRef()) {
    
          arrangeCompositeReference(pcSlice, rcListPic, pocCurr);
        }
    
    Hendry's avatar
    Hendry committed
        pcSlice->constructRefPicList(rcListPic);
    
        // store sub-picture numbers, sizes, and locations with a picture
    
        pcSlice->getPic()->numSubpics = pcPic->cs->pps->getNumSubPics();
        pcSlice->getPic()->subpicWidthInCTUs.clear();
        pcSlice->getPic()->subpicHeightInCTUs.clear();
        pcSlice->getPic()->subpicCtuTopLeftX.clear();
        pcSlice->getPic()->subpicCtuTopLeftY.clear();
        for (int subPicIdx = 0; subPicIdx < pcPic->cs->pps->getNumSubPics(); subPicIdx++)
        {
          pcSlice->getPic()->subpicWidthInCTUs.push_back(pcPic->cs->pps->getSubPic(subPicIdx).getSubPicWidthInCTUs());
          pcSlice->getPic()->subpicHeightInCTUs.push_back(pcPic->cs->pps->getSubPic(subPicIdx).getSubPicHeightInCTUs());
          pcSlice->getPic()->subpicCtuTopLeftX.push_back(pcPic->cs->pps->getSubPic(subPicIdx).getSubPicCtuTopLeftX());
          pcSlice->getPic()->subpicCtuTopLeftY.push_back(pcPic->cs->pps->getSubPic(subPicIdx).getSubPicCtuTopLeftY());
    
        const VPS* vps = pcPic->cs->vps;
        int layerIdx = vps == nullptr ? 0 : vps->getGeneralLayerIdx(pcPic->layerId);
        if (vps && !vps->getIndependentLayerFlag(layerIdx) && pcPic->cs->pps->getNumSubPics() > 1)
        {
    
          CU::checkConformanceILRP(pcSlice);
    
        xPicInitHashME( pcPic, pcSlice->getPPS(), rcListPic );
    
          if( !pcSlice->isIRAP() )
    
          {
            int refLayer = pcSlice->getDepth();
            if( refLayer > 9 ) refLayer = 9; // Max layer is 10
    
            if( m_bInitAMaxBT && pcSlice->getPOC() > m_uiPrevISlicePOC )
            {
              ::memset( m_uiBlkSize, 0, sizeof( m_uiBlkSize ) );
              ::memset( m_uiNumBlk,  0, sizeof( m_uiNumBlk ) );
              m_bInitAMaxBT = false;
            }
    
            if( refLayer >= 0 && m_uiNumBlk[refLayer] != 0 )
            {
    
    Brian Heng's avatar
    Brian Heng committed
              picHeader->setSplitConsOverrideFlag(true);
              double dBlkSize = sqrt( ( double ) m_uiBlkSize[refLayer] / m_uiNumBlk[refLayer] );
    
              unsigned int newMaxBtSize = picHeader->getMaxBTSize(pcSlice->getSliceType(), CHANNEL_TYPE_LUMA);
              if( dBlkSize < AMAXBT_TH32 )
    
              else if( dBlkSize < AMAXBT_TH64 )
    
              newMaxBtSize = Clip3(picHeader->getMinQTSize(pcSlice->getSliceType()), pcPic->cs->sps->getCTUSize(), newMaxBtSize);
              picHeader->setMaxBTSize(1, newMaxBtSize);
    
    
              m_uiBlkSize[refLayer] = 0;
              m_uiNumBlk [refLayer] = 0;
            }
          }
          else
          {
            if( m_bInitAMaxBT )
            {
              ::memset( m_uiBlkSize, 0, sizeof( m_uiBlkSize ) );
              ::memset( m_uiNumBlk,  0, sizeof( m_uiNumBlk ) );
            }
    
            m_uiPrevISlicePOC = pcSlice->getPOC();
            m_bInitAMaxBT = true;
          }
        }
    
        //  Slice info. refinement
        if ( (pcSlice->getSliceType() == B_SLICE) && (pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0) )
        {
          pcSlice->setSliceType ( P_SLICE );
        }
    
        xUpdateRasInit( pcSlice );
    
        if ( pcSlice->getPendingRasInit() )
        {
          // this ensures that independently encoded bitstream chunks can be combined to bit-equal
          pcSlice->setEncCABACTableIdx( pcSlice->getSliceType() );
        }
        else
        {
          pcSlice->setEncCABACTableIdx( m_pcSliceEncoder->getEncCABACTableIdx() );
        }
    
        if (pcSlice->getSliceType() == B_SLICE)
        {
    
          bool bLowDelay = true;
          int  iCurrPOC  = pcSlice->getPOC();
          int iRefIdx = 0;
    
          for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0) && bLowDelay; iRefIdx++)
          {
            if ( pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() > iCurrPOC )
            {
              bLowDelay = false;
            }
          }
          for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1) && bLowDelay; iRefIdx++)
          {
            if ( pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() > iCurrPOC )
            {
              bLowDelay = false;
            }
          }
    
          pcSlice->setCheckLDC(bLowDelay);
        }
        else
        {
          pcSlice->setCheckLDC(true);
        }
    
    
        //-------------------------------------------------------------
        pcSlice->setRefPOCList();
    
    
        pcSlice->setList1IdxToList0Idx();
    
        if (m_pcEncLib->getTMVPModeId() == 2)
        {
          if (iGOPid == 0) // first picture in SOP (i.e. forward B)
          {
    
    Brian Heng's avatar
    Brian Heng committed
            picHeader->setEnableTMVPFlag(0);
    
          }
          else
          {
            // Note: pcSlice->getColFromL0Flag() is assumed to be always 0 and getcolRefIdx() is always 0.
    
    Brian Heng's avatar
    Brian Heng committed
            picHeader->setEnableTMVPFlag(1);
    
        else if (m_pcEncLib->getTMVPModeId() == 1)
    
    Brian Heng's avatar
    Brian Heng committed
          picHeader->setEnableTMVPFlag(1);
    
    Brian Heng's avatar
    Brian Heng committed
          picHeader->setEnableTMVPFlag(0);
    
        // disable TMVP when current picture is the only ref picture
    
    Yu Han's avatar
    Yu Han committed
        if (pcSlice->isIRAP() && pcSlice->getSPS()->getIBCFlag())
    
    Brian Heng's avatar
    Brian Heng committed
          picHeader->setEnableTMVPFlag(0);
    
    Brian Heng's avatar
    Brian Heng committed
        if( pcSlice->getSliceType() != I_SLICE && picHeader->getEnableTMVPFlag() )
    
        {
          int colRefIdxL0 = -1, colRefIdxL1 = -1;
    
          for( int refIdx = 0; refIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); refIdx++ )
          {
    
            if( pcSlice->getRefPic( REF_PIC_LIST_0, refIdx )->isRefScaled( pcSlice->getPPS() ) == false )
    
            {
              colRefIdxL0 = refIdx;
              break;
            }
          }
    
          if( pcSlice->getSliceType() == B_SLICE )
          {
            for( int refIdx = 0; refIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); refIdx++ )
            {
    
              if( pcSlice->getRefPic( REF_PIC_LIST_1, refIdx )->isRefScaled( pcSlice->getPPS() ) == false )
    
              {
                colRefIdxL1 = refIdx;
                break;
              }
            }
          }
    
          if( colRefIdxL0 >= 0 && colRefIdxL1 >= 0 )
          {
            const Picture *refPicL0 = pcSlice->getRefPic( REF_PIC_LIST_0, colRefIdxL0 );
            if( !refPicL0->slices.size() )
            {
              refPicL0 = refPicL0->unscaledPic;
            }
    
            const Picture *refPicL1 = pcSlice->getRefPic( REF_PIC_LIST_1, colRefIdxL1 );
            if( !refPicL1->slices.size() )
            {
              refPicL1 = refPicL1->unscaledPic;
            }
    
            const uint32_t uiColFromL0 = refPicL0->slices[0]->getSliceQp() > refPicL1->slices[0]->getSliceQp();
    
            picHeader->setPicColFromL0Flag( uiColFromL0 );
    
            pcSlice->setColFromL0Flag( uiColFromL0 );
            pcSlice->setColRefIdx( uiColFromL0 ? colRefIdxL0 : colRefIdxL1 );
    
            picHeader->setColRefIdx( uiColFromL0 ? colRefIdxL0 : colRefIdxL1 );
    
          }
          else if( colRefIdxL0 < 0 && colRefIdxL1 >= 0 )
          {
    
            picHeader->setPicColFromL0Flag( false );
    
            pcSlice->setColFromL0Flag( false );
            pcSlice->setColRefIdx( colRefIdxL1 );
    
          }
          else if( colRefIdxL0 >= 0 && colRefIdxL1 < 0 )
          {
    
            picHeader->setPicColFromL0Flag( true );
    
            pcSlice->setColFromL0Flag( true );
            pcSlice->setColRefIdx( colRefIdxL0 );
    
    Brian Heng's avatar
    Brian Heng committed
            picHeader->setEnableTMVPFlag( 0 );
    
    Brian Heng's avatar
    Brian Heng committed
        pcSlice->scaleRefPicList( scaledRefPic, pcPic->cs->picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false );
    
        // set adaptive search range for non-intra-slices
    
        if (m_pcCfg->getUseASR() && !pcSlice->isIRAP())
    
        {
          m_pcSliceEncoder->setSearchRange(pcSlice);
        }
    
        bool bGPBcheck=false;
        if ( pcSlice->getSliceType() == B_SLICE)
        {
          if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) )
          {
            bGPBcheck=true;
            int i;
            for ( i=0; i < pcSlice->getNumRefIdx(RefPicList( 1 ) ); i++ )
            {
              if ( pcSlice->getRefPOC(RefPicList(1), i) != pcSlice->getRefPOC(RefPicList(0), i) )
              {
                bGPBcheck=false;
                break;
              }
            }
          }
        }
        if(bGPBcheck)
        {
    
    Brian Heng's avatar
    Brian Heng committed
          picHeader->setMvdL1ZeroFlag(true);
    
    Brian Heng's avatar
    Brian Heng committed
          picHeader->setMvdL1ZeroFlag(false);
    
        if ( pcSlice->getSPS()->getUseSMVD() && pcSlice->getCheckLDC() == false
    
    Brian Heng's avatar
    Brian Heng committed
          && picHeader->getMvdL1ZeroFlag() == false
    
        {
          int currPOC = pcSlice->getPOC();
    
          int forwardPOC = currPOC;
    
    Daniel's avatar
    Daniel committed
          int backwardPOC = currPOC;
    
          int ref = 0, refIdx0 = -1, refIdx1 = -1;
    
          // search nearest forward POC in List 0
          for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ )
          {
            int poc = pcSlice->getRefPic( REF_PIC_LIST_0, ref )->getPOC();
    
            const bool isRefLongTerm = pcSlice->getRefPic(REF_PIC_LIST_0, ref)->longTerm;
            if ( poc < currPOC && (poc > forwardPOC || refIdx0 == -1) && !isRefLongTerm )
    
            {
              forwardPOC = poc;
              refIdx0 = ref;
            }
          }
    
          // search nearest backward POC in List 1
          for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ )
          {
            int poc = pcSlice->getRefPic( REF_PIC_LIST_1, ref )->getPOC();
    
            const bool isRefLongTerm = pcSlice->getRefPic(REF_PIC_LIST_1, ref)->longTerm;
            if ( poc > currPOC && (poc < backwardPOC || refIdx1 == -1) && !isRefLongTerm )
    
    Daniel's avatar
    Daniel committed
              backwardPOC = poc;
    
    Daniel's avatar
    Daniel committed
          if ( !(forwardPOC < currPOC && backwardPOC > currPOC) )
    
          {
            forwardPOC = currPOC;
    
    Daniel's avatar
    Daniel committed
            backwardPOC = currPOC;
    
            refIdx0 = -1;
            refIdx1 = -1;
    
            // search nearest backward POC in List 0
            for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ )
            {
              int poc = pcSlice->getRefPic( REF_PIC_LIST_0, ref )->getPOC();
    
              const bool isRefLongTerm = pcSlice->getRefPic(REF_PIC_LIST_0, ref)->longTerm;
              if ( poc > currPOC && (poc < backwardPOC || refIdx0 == -1) && !isRefLongTerm )
    
    Daniel's avatar
    Daniel committed
                backwardPOC = poc;
    
                refIdx0 = ref;
              }
            }
    
            // search nearest forward POC in List 1
            for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ )
            {
              int poc = pcSlice->getRefPic( REF_PIC_LIST_1, ref )->getPOC();
    
              const bool isRefLongTerm = pcSlice->getRefPic(REF_PIC_LIST_1, ref)->longTerm;
              if ( poc < currPOC && (poc > forwardPOC || refIdx1 == -1) && !isRefLongTerm )
    
    Daniel's avatar
    Daniel committed
          if ( forwardPOC < currPOC && backwardPOC > currPOC )
    
          {
            pcSlice->setBiDirPred( true, refIdx0, refIdx1 );
          }
          else
          {
            pcSlice->setBiDirPred( false, -1, -1 );
          }
        }
        else
        {
          pcSlice->setBiDirPred( false, -1, -1 );
        }
    
    
        double lambda            = 0.0;
        int actualHeadBits       = 0;
        int actualTotalBits      = 0;
        int estimatedBits        = 0;
        int tmpBitsBeforeWriting = 0;
    
        xPicInitRateControl(estimatedBits, iGOPid, lambda, pcPic, pcSlice);
    
    
        uint32_t uiNumSliceSegments = 1;
    
        {
          pcSlice->setDefaultClpRng( *pcSlice->getSPS() );
        }
    
        // Allocate some coders, now the number of tiles are known.
        const uint32_t numberOfCtusInFrame = pcPic->cs->pcv->sizeInCtus;
    
        const int numSubstreamsColumns = pcSlice->getPPS()->getNumTileColumns();
    
    Hendry's avatar
    Hendry committed
        const int numSubstreamRows     = pcSlice->getSPS()->getEntropyCodingSyncEnabledFlag() ? pcPic->cs->pcv->heightInCtus : (pcSlice->getPPS()->getNumTileRows());
    
        const int numSubstreams        = std::max<int> (numSubstreamRows * numSubstreamsColumns, (int) pcPic->cs->pps->getNumSlicesInPic());
    
        std::vector<OutputBitstream> substreamsOut(numSubstreams);
    
    #if ENABLE_QPA
    
        pcPic->m_uEnerHpCtu.resize (numberOfCtusInFrame);
        pcPic->m_iOffsetCtu.resize (numberOfCtusInFrame);
    
    #if ENABLE_QPA_SUB_CTU
    
    Brian Heng's avatar
    Brian Heng committed
        if (pcSlice->getPPS()->getUseDQP() && pcSlice->getCuQpDeltaSubdiv() > 0)
    
          const unsigned   mtsLog2 = (unsigned)floorLog2(std::min (pcPic->cs->sps->getMaxTbSize(), pcv.maxCUWidth));
    
          pcPic->m_subCtuQP.resize ((pcv.maxCUWidth >> mtsLog2) * (pcv.maxCUHeight >> mtsLog2));
        }
    
        if (pcSlice->getSPS()->getSAOEnabledFlag())
    
        {
          pcPic->resizeSAO( numberOfCtusInFrame, 0 );
          pcPic->resizeSAO( numberOfCtusInFrame, 1 );
        }
    
        // it is used for signalling during CTU mode decision, i.e. before ALF processing
    
        if( pcSlice->getSPS()->getALFEnabledFlag() )
    
        {
          pcPic->resizeAlfCtuEnableFlag( numberOfCtusInFrame );
    
          pcPic->resizeAlfCtuAlternative( numberOfCtusInFrame );
    
          pcPic->resizeAlfCtbFilterIndex(numberOfCtusInFrame);
    
        }
    
        bool decPic = false;
        bool encPic = false;
        // test if we can skip the picture entirely or decode instead of encoding
        trySkipOrDecodePicture( decPic, encPic, *m_pcCfg, pcPic );
    
        pcPic->cs->slice = pcSlice; // please keep this
    
    #if ENABLE_QPA
        if (pcSlice->getPPS()->getSliceChromaQpFlag() && CS::isDualITree (*pcSlice->getPic()->cs) && !m_pcCfg->getUsePerceptQPA() && (m_pcCfg->getSliceChromaOffsetQpPeriodicity() == 0))
    #else
        if (pcSlice->getPPS()->getSliceChromaQpFlag() && CS::isDualITree (*pcSlice->getPic()->cs))
    #endif
    
        {
          // overwrite chroma qp offset for dual tree
          pcSlice->setSliceChromaQpDelta(COMPONENT_Cb, m_pcCfg->getChromaCbQpOffsetDualTree());
          pcSlice->setSliceChromaQpDelta(COMPONENT_Cr, m_pcCfg->getChromaCrQpOffsetDualTree());
    
          if (pcSlice->getSPS()->getJointCbCrEnabledFlag())
    
    Fangdong Chen's avatar
    Fangdong Chen committed
          {
    
    Vadim Seregin's avatar
    Vadim Seregin committed
            pcSlice->setSliceChromaQpDelta(JOINT_CbCr, m_pcCfg->getChromaCbCrQpOffsetDualTree());
    
    Fangdong Chen's avatar
    Fangdong Chen committed
          }
    
          m_pcSliceEncoder->setUpLambda(pcSlice, pcSlice->getLambdas()[0], pcSlice->getSliceQp());
    
    Vadim Seregin's avatar
    Vadim Seregin committed
        }
    
    Brian Heng's avatar
    Brian Heng committed
        xPicInitLMCS(pcPic, picHeader, pcSlice);
    
        if( pcSlice->getSPS()->getScalingListFlag() && m_pcCfg->getUseScalingListId() == SCALING_LIST_FILE_READ )
        {
    
          picHeader->setExplicitScalingListEnabledFlag( true );
          pcSlice->setExplicitScalingListUsed( true );
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    
    
          int apsId = std::min<int>( 7, m_pcEncLib->getVPS() == nullptr ? 0 : m_pcEncLib->getVPS()->getGeneralLayerIdx( m_pcEncLib->getLayerId() ) );
    
    Brian Heng's avatar
    Brian Heng committed
          picHeader->setScalingListAPSId( apsId );
    
    
          ParameterSetMap<APS> *apsMap = m_pcEncLib->getApsMap();
          APS*  scalingListAPS = apsMap->getPS( ( apsId << NUM_APS_TYPE_LEN ) + SCALING_LIST_APS );
          assert( scalingListAPS != NULL );
    
    Brian Heng's avatar
    Brian Heng committed
          picHeader->setScalingListAPS( scalingListAPS );
    
    Brian Heng's avatar
    Brian Heng committed
        pcPic->cs->picHeader->setPic(pcPic);
        pcPic->cs->picHeader->setValid();
    
        if(pcPic->cs->sps->getFpelMmvdEnabledFlag())
    
          // cannot set ph_fpel_mmvd_enabled_flag at slice level - need new picture-level version of checkDisFracMmvd algorithm?
    
    Brian Heng's avatar
    Brian Heng committed
          // m_pcSliceEncoder->checkDisFracMmvd( pcPic, 0, numberOfCtusInFrame );
          bool useIntegerMVD = (pcPic->lwidth()*pcPic->lheight() > 1920 * 1080);
          pcPic->cs->picHeader->setDisFracMMVD( useIntegerMVD );
        }
        if (pcSlice->getSPS()->getJointCbCrEnabledFlag())
        {
          m_pcSliceEncoder->setJointCbCrModes(*pcPic->cs, Position(0, 0), pcPic->cs->area.lumaSize());
        }
    
        if( encPic )
        // now compress (trial encode) the various slice segments (slices, and dependent slices)
        {
          DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "poc", pocCurr ) ) );
    
    #if JVET_R0110_MIXED_LOSSLESS
    
          const std::vector<uint16_t> sliceLosslessArray = *(m_pcCfg->getSliceLosslessArray());
          bool mixedLossyLossless = m_pcCfg->getMixedLossyLossless();
          if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
          {
            pcPic->fillSliceLossyLosslessArray(sliceLosslessArray, mixedLossyLossless);
          }
    
          for(uint32_t sliceIdx = 0; sliceIdx < pcPic->cs->pps->getNumSlicesInPic(); sliceIdx++ )
          {
            pcSlice->setSliceMap( pcPic->cs->pps->getSliceMap( sliceIdx ) );
    
              Position firstCtu;
              firstCtu.x = pcSlice->getFirstCtuRsAddrInSlice() % pcPic->cs->pps->getPicWidthInCtu();
              firstCtu.y = pcSlice->getFirstCtuRsAddrInSlice() / pcPic->cs->pps->getPicWidthInCtu();
    
              int subPicIdx = NOT_VALID;
              for( int sp = 0; sp < pcPic->cs->pps->getNumSubPics(); sp++ )
    
                if( pcPic->cs->pps->getSubPic( sp ).containsCtu( firstCtu ) )
    
              CHECK( subPicIdx == NOT_VALID, "Sub-picture was not found" );
    
              pcSlice->setSliceSubPicId( pcPic->cs->pps->getSubPic( subPicIdx ).getSubPicID() );
            }
    
            if (pcPic->cs->sps->getUseLmcs())
            {
              pcSlice->setLmcsEnabledFlag(picHeader->getLmcsEnabledFlag());
              if (pcSlice->getSliceType() == I_SLICE)
              {
                //reshape original signal
                if (pcSlice->getLmcsEnabledFlag())
                {
                  pcPic->getOrigBuf(COMPONENT_Y).rspSignal(m_pcReshaper->getFwdLUT());
                  m_pcReshaper->setSrcReshaped(true);
                  m_pcReshaper->setRecReshaped(true);
                }
                else
                {
                  pcPic->getOrigBuf().copyFrom(pcPic->getTrueOrigBuf());
                  m_pcReshaper->setSrcReshaped(false);
                  m_pcReshaper->setRecReshaped(false);
                }
              }
            }
    
    
    #if JVET_R0110_MIXED_LOSSLESS
            bool isLossless = false;
            if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
            {
    
              isLossless = pcPic->losslessSlice(sliceIdx);
    
            }
            m_pcSliceEncoder->setLosslessSlice(pcPic, isLossless);
    #endif
    
    
            if (pcSlice->getSliceType() != I_SLICE && pcSlice->getRefPic(REF_PIC_LIST_0, 0)->numSubpics > 1)
    
              m_pcEncLib->getInterSearch()->setClipMvInSubPic(true);
    
              m_pcEncLib->getInterSearch()->setClipMvInSubPic(false);
    
            m_pcSliceEncoder->precompressSlice( pcPic );
            m_pcSliceEncoder->compressSlice   ( pcPic, false, false );
    
    
            if(sliceIdx < pcPic->cs->pps->getNumSlicesInPic() - 1)
    
            {
              uint32_t independentSliceIdx = pcSlice->getIndependentSliceIdx();
              pcPic->allocateNewSlice();
              m_pcSliceEncoder->setSliceSegmentIdx      (uiNumSliceSegments);
              // prepare for next slice
              pcSlice = pcPic->slices[uiNumSliceSegments];
              CHECK(!(pcSlice->getPPS() != 0), "Unspecified error");
              pcSlice->copySliceInfo(pcPic->slices[uiNumSliceSegments - 1]);
              pcSlice->setSliceBits(0);
              independentSliceIdx++;
              pcSlice->setIndependentSliceIdx(independentSliceIdx);
              uiNumSliceSegments++;
            }
          }
    
          duData.clear();
    
          CodingStructure& cs = *pcPic->cs;
          pcSlice = pcPic->slices[0];
    
    
          if (cs.sps->getUseLmcs() && m_pcReshaper->getSliceReshaperInfo().getUseSliceReshaper())
          {
            picHeader->setLmcsEnabledFlag(true);
            int apsId = std::min<int>(3, m_pcEncLib->getVPS() == nullptr ? 0 : m_pcEncLib->getVPS()->getGeneralLayerIdx(m_pcEncLib->getLayerId()));
            picHeader->setLmcsAPSId(apsId);
    
            const PreCalcValues& pcv = *cs.pcv;
            for (uint32_t yPos = 0; yPos < pcv.lumaHeight; yPos += pcv.maxCUHeight)
            {
              for (uint32_t xPos = 0; xPos < pcv.lumaWidth; xPos += pcv.maxCUWidth)
              {
                const CodingUnit* cu = cs.getCU(Position(xPos, yPos), CHANNEL_TYPE_LUMA);
                if (cu->slice->getLmcsEnabledFlag())
                {
                  const uint32_t width = (xPos + pcv.maxCUWidth > pcv.lumaWidth) ? (pcv.lumaWidth - xPos) : pcv.maxCUWidth;
                  const uint32_t height = (yPos + pcv.maxCUHeight > pcv.lumaHeight) ? (pcv.lumaHeight - yPos) : pcv.maxCUHeight;
                  const UnitArea area(cs.area.chromaFormat, Area(xPos, yPos, width, height));
                  cs.getRecoBuf(area).get(COMPONENT_Y).rspSignal(m_pcReshaper->getInvLUT());
                }
              }
            }
            m_pcReshaper->setRecReshaped(false);
            pcPic->getOrigBuf().copyFrom(pcPic->getTrueOrigBuf());
          }
    
          // create SAO object based on the picture size
          if( pcSlice->getSPS()->getSAOEnabledFlag() )
          {
            const uint32_t widthInCtus = ( picWidth + maxCUWidth - 1 ) / maxCUWidth;
            const uint32_t heightInCtus = ( picHeight + maxCUHeight - 1 ) / maxCUHeight;
            const uint32_t numCtuInFrame = widthInCtus * heightInCtus;
    
            const uint32_t  log2SaoOffsetScaleLuma   = (uint32_t) std::max(0, pcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA  ) - MAX_SAO_TRUNCATED_BITDEPTH);
            const uint32_t  log2SaoOffsetScaleChroma = (uint32_t) std::max(0, pcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_CHROMA) - MAX_SAO_TRUNCATED_BITDEPTH);
    
    
            m_pcSAO->create( picWidth, picHeight, chromaFormatIDC, maxCUWidth, maxCUHeight, maxTotalCUDepth, log2SaoOffsetScaleLuma, log2SaoOffsetScaleChroma );
            m_pcSAO->destroyEncData();
            m_pcSAO->createEncData( m_pcCfg->getSaoCtuBoundary(), numCtuInFrame );
            m_pcSAO->setReshaper( m_pcReshaper );
          }
    
    
          if( pcSlice->getSPS()->getScalingListFlag() && m_pcCfg->getUseScalingListId() == SCALING_LIST_FILE_READ )
          {
    
            picHeader->setExplicitScalingListEnabledFlag(true);
            pcSlice->setExplicitScalingListUsed(true);
    
    Brian Heng's avatar
    Brian Heng committed
            int apsId = 0;
            picHeader->setScalingListAPSId( apsId );
    
          // SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas
    
          if( pcSlice->getSPS()->getSAOEnabledFlag() && m_pcCfg->getSaoCtuBoundary() )
    
          {
            m_pcSAO->getPreDBFStatistics( cs );
          }
    
          //-- Loop filter
          if ( m_pcCfg->getDeblockingFilterMetric() )
          {
      #if W0038_DB_OPT
            if ( m_pcCfg->getDeblockingFilterMetric()==2 )
            {
              applyDeblockingFilterParameterSelection(pcPic, uiNumSliceSegments, iGOPid);
            }
            else
            {
      #endif
              applyDeblockingFilterMetric(pcPic, uiNumSliceSegments);
      #if W0038_DB_OPT
            }
      #endif
          }
    
    #if JVET_R0110_MIXED_LOSSLESS
          if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING) 
          {
            for (int s = 0; s < uiNumSliceSegments; s++)
            {
              if (pcPic->slices[s]->isLossless())
              {
                pcPic->slices[s]->setDeblockingFilterDisable(true);
              }
            }
          }
    #endif
    
          CS::setRefinedMotionField(cs);
    
          if( pcSlice->getSPS()->getSAOEnabledFlag() )
    
          {
            bool sliceEnabled[MAX_NUM_COMPONENT];
            m_pcSAO->initCABACEstimator( m_pcEncLib->getCABACEncoder(), m_pcEncLib->getCtxCache(), pcSlice );
    
    
            m_pcSAO->SAOProcess( cs, sliceEnabled, pcSlice->getLambdas(),
    #if ENABLE_QPA
                                 (m_pcCfg->getUsePerceptQPA() && !m_pcCfg->getUseRateCtrl() && pcSlice->getPPS()->getUseDQP() ? m_pcEncLib->getRdCost (PARL_PARAM0 (0))->getChromaWeight() : 0.0),
    #endif
                                 m_pcCfg->getTestSAODisableAtPictureLevel(), m_pcCfg->getSaoEncodingRate(), m_pcCfg->getSaoEncodingRateChroma(), m_pcCfg->getSaoCtuBoundary(), m_pcCfg->getSaoGreedyMergeEnc() );
    
            for (int s = 0; s < uiNumSliceSegments; s++)
    
    
    #if  JVET_R0110_MIXED_LOSSLESS
              if (pcPic->slices[s]->isLossless() && m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
              {
                pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, false);
                pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, false);
              }
              else
              {
    #endif          
                pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, sliceEnabled[COMPONENT_Y]);
                CHECK(!(sliceEnabled[COMPONENT_Cb] == sliceEnabled[COMPONENT_Cr]), "Unspecified error");
                pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, sliceEnabled[COMPONENT_Cb]);
    
    #if  JVET_R0110_MIXED_LOSSLESS
            }
    #endif
    
    
          if( pcSlice->getSPS()->getALFEnabledFlag() )
    
            m_pcALF->destroy();
            m_pcALF->create( m_pcCfg, picWidth, picHeight, chromaFormatIDC, maxCUWidth, maxCUHeight, maxTotalCUDepth, m_pcCfg->getBitDepth(), m_pcCfg->getInputBitDepth() );
    
    
            for (int s = 0; s < uiNumSliceSegments; s++)
            {
              pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Y, false);
            }
            m_pcALF->initCABACEstimator(m_pcEncLib->getCABACEncoder(), m_pcEncLib->getCtxCache(), pcSlice, m_pcEncLib->getApsMap());
            m_pcALF->ALFProcess(cs, pcSlice->getLambdas()
    #if ENABLE_QPA
              , (m_pcCfg->getUsePerceptQPA() && !m_pcCfg->getUseRateCtrl() && pcSlice->getPPS()->getUseDQP() ? m_pcEncLib->getRdCost(PARL_PARAM0(0))->getChromaWeight() : 0.0)
    
    #endif
    #if JVET_R0110_MIXED_LOSSLESS
              , pcPic, uiNumSliceSegments
    
            //assign ALF slice header
            for (int s = 0; s < uiNumSliceSegments; s++)
            {
    
    #if JVET_R0110_MIXED_LOSSLESS
               //For the first slice, even if it is lossless, slice level ALF is not disabled and ALF-APS is signaled so that the later lossy slices can use APS of the first slice. 
               //However, if the first slice is lossless, the ALF process is disabled for all of the CTUs ( m_ctuEnableFlag == 0) of that slice which is implemented in the function void EncAdaptiveLoopFilter::ALFProcess.         
          
              if (pcPic->slices[s]->isLossless() && s && m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
              {
                pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Y, false);
                pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cb, false);
                pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cr, false);
              }
              else
              {
    #endif          
                pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Y, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Y));
                pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cb, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cb));
                pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cr, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cr));
    
    #if JVET_R0110_MIXED_LOSSLESS
              }
    #endif
    
              if (pcPic->slices[s]->getTileGroupAlfEnabledFlag(COMPONENT_Y))
              {
                pcPic->slices[s]->setTileGroupNumAps(cs.slice->getTileGroupNumAps());
    
                pcPic->slices[s]->setAlfAPSs(cs.slice->getTileGroupApsIdLuma());
    
              pcPic->slices[s]->setAlfAPSs(cs.slice->getAlfAPSs());
              pcPic->slices[s]->setTileGroupApsIdChroma(cs.slice->getTileGroupApsIdChroma());
    
              pcPic->slices[s]->setTileGroupCcAlfCbApsId(cs.slice->getTileGroupCcAlfCbApsId());
              pcPic->slices[s]->setTileGroupCcAlfCrApsId(cs.slice->getTileGroupCcAlfCrApsId());