Skip to content
Snippets Groups Projects
EncGOP.cpp 267 KiB
Newer Older
  • Learn to ignore specific revisions
  • Yao-Jen Chang's avatar
    Yao-Jen Chang committed
                          if (abs(1.0 - (abs(currPOC - currRefPOC) * 1.0 / abs(colPOC - colRefPOC) * 1.0)) < bestDistScale)
                          {
                            bestDistScale = abs(1.0 - (abs(currPOC - currRefPOC) * 1.0 / abs(colPOC - colRefPOC) * 1.0));
                            targetRefIdx = curRefIdx;
                          }
                        }
                      } // curRefIdx
                        //printf("sliceIdx:%d, colRefPicListIdx:%d, curRefPicListIdx:%d, colRefIdx:%d, targetRefIdx:%d\n", sliceIdx, colRefPicListIdx, curRefPicListIdx, colRefIdx, targetRefIdx);
    
    #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
                      pcSlice->setImRefIdx(sliceIdx, RefPicList(colRefPicListIdx), RefPicList(curRefPicListIdx), colRefIdx, targetRefIdx, colFrameIdx);
    #else
    
    Yao-Jen Chang's avatar
    Yao-Jen Chang committed
                      pcSlice->setImRefIdx(sliceIdx, RefPicList(colRefPicListIdx), RefPicList(curRefPicListIdx), colRefIdx, targetRefIdx);
    
    Yao-Jen Chang's avatar
    Yao-Jen Chang committed
                    } // curRefPicListIdx
                  }
                }
              }
            }
    
    #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
            }
    #endif
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #if JVET_Z0118_GDR // scaleRefPicList
    
    Seungwook Hong's avatar
    Seungwook Hong committed
        bool  bDisableTMVP;
        if (pcPic->cs->isGdrEnabled())
        {
          PicHeader *picHeader = new PicHeader;
          *picHeader = *pcPic->cs->picHeader;
          bDisableTMVP = pcSlice->scaleRefPicList(scaledRefPic, picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false);
        }
        else
        {
          bDisableTMVP = pcSlice->scaleRefPicList(scaledRefPic, pcPic->cs->picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false);
        }
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #else
    
        bool  bDisableTMVP = pcSlice->scaleRefPicList( scaledRefPic, pcPic->cs->picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false );
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #endif
    
        if ( picHeader->getEnableTMVPFlag() && bDisableTMVP )
        {
          picHeader->setEnableTMVPFlag( 0 );
        }
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #else
    #if JVET_Z0118_GDR
        PicHeader *picHeader = new PicHeader;
        *picHeader = *pcPic->cs->picHeader;
        pcSlice->scaleRefPicList( scaledRefPic, picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false );
        picHeader = pcPic->cs->picHeader;
    
    Brian Heng's avatar
    Brian Heng committed
        pcSlice->scaleRefPicList( scaledRefPic, pcPic->cs->picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false );
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #endif
    
        // set adaptive search range for non-intra-slices
    
        if (m_pcCfg->getUseASR() && !pcSlice->isIntra())
    
        {
          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 );
        }
    
    #if JVET_Y0128_NON_CTC
        pcSlice->checkBMAvailability(pcSlice);
        pcSlice->checkAmvpMergeModeAvailability(pcSlice);
    #endif
    
    #if JVET_Z0054_BLK_REF_PIC_REORDER
        if (pcSlice->getSPS()->getUseARL())
        {
          pcSlice->generateCombinedList();
          pcSlice->generateRefPicPairList();
        }
    #endif
    
    #if JVET_AF0159_AFFINE_SUBPU_BDOF_REFINEMENT
        pcSlice->generateEqualPocDist();
    #endif
    
    
        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 JVET_V0094_BILATERAL_FILTER
    
    #if JVET_X0071_CHROMA_BILATERAL_FILTER
    
        if (pcSlice->getSPS()->getSAOEnabledFlag() || pcSlice->getPPS()->getUseBIF() || pcSlice->getPPS()->getUseChromaBIF())
    
    Vadim Seregin's avatar
    Vadim Seregin committed
        // BIF happens in SAO code so this needs to be done
        // even if SAO=0 if BIF=1.
        if (pcSlice->getSPS()->getSAOEnabledFlag() || pcSlice->getPPS()->getUseBIF() )
    
    #endif
    #else
    #if JVET_X0071_CHROMA_BILATERAL_FILTER
    
        if (pcSlice->getSPS()->getSAOEnabledFlag() || pcSlice->getPPS()->getUseChromaBIF())
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #else
    
        if (pcSlice->getSPS()->getSAOEnabledFlag())
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
        {
          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, m_pcEncLib->getApsMap() );
    
    #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
    
    #if JVET_AC0096
          if (!(pcSlice->getPPS()->getPPSId() == ENC_PPS_ID_RPR || pcSlice->getPPS()->getPPSId() == ENC_PPS_ID_RPR2 || pcSlice->getPPS()->getPPSId() == ENC_PPS_ID_RPR3))
    
    Fangdong Chen's avatar
    Fangdong Chen committed
          {
    
    #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())
            {
              pcSlice->setSliceChromaQpDelta(JOINT_CbCr, m_pcCfg->getChromaCbCrQpOffsetDualTree());
            }
            m_pcSliceEncoder->setUpLambda(pcSlice, pcSlice->getLambdas()[0], pcSlice->getSliceQp());
    #if JVET_AC0096
    
    Fangdong Chen's avatar
    Fangdong Chen committed
          }
    
    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 ) ) );
    
          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
    
    Vadim Seregin's avatar
    Vadim Seregin committed
                if( m_pcCfg->getGopBasedTemporalFilterEnabled() )
                {
                  pcPic->getOrigBuf().copyFrom( pcPic->getFilteredOrigBuf() );
                }
                else
                {
                  pcPic->getOrigBuf().copyFrom( pcPic->getTrueOrigBuf() );
                }
    
    
                if (pcSlice->getLmcsEnabledFlag())
                {
                  pcPic->getOrigBuf(COMPONENT_Y).rspSignal(m_pcReshaper->getFwdLUT());
                  m_pcReshaper->setSrcReshaped(true);
                  m_pcReshaper->setRecReshaped(true);
                }
                else
                {
                  m_pcReshaper->setSrcReshaped(false);
                  m_pcReshaper->setRecReshaped(false);
                }
              }
            }
    
    
            bool isLossless = false;
            if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
            {
    
              isLossless = pcPic->losslessSlice(sliceIdx);
    
            }
            m_pcSliceEncoder->setLosslessSlice(pcPic, isLossless);
    
    
    #if JVET_S0258_SUBPIC_CONSTRAINTS
            if( pcSlice->getSliceType() != I_SLICE && pcSlice->getRefPic( REF_PIC_LIST_0, 0 )->subPictures.size() > 1 )
    #else
    
            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();
    
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if DUMP_BEFORE_INLOOP
          if( m_pcEncLib->getDumpBeforeInloop() )
          {
            static VideoIOYuv ioBeforeInLoop;
    
            if( pcPic )
            {
              if( !ioBeforeInLoop.isOpen() )
              {
                std::string reconFileName = m_pcEncLib->m_reconFileName;
                size_t pos = reconFileName.find_last_of( '.' );
                if( pos != string::npos )
                {
                  reconFileName.insert( pos, "beforeInloop" );
                }
                else
                {
                  reconFileName.append( "beforeInloop" );
                }
                const BitDepths &bitDepths = pcPic->cs->sps->getBitDepths();
    
                ioBeforeInLoop.open( reconFileName, true, bitDepths.recon, bitDepths.recon, bitDepths.recon );
              }
    
              const Window &conf = pcPic->getConformanceWindow();
              const SPS* sps = pcPic->cs->sps;
              ChromaFormat chromaFormatIDC = sps->getChromaFormatIdc();
    
              InputColourSpaceConversion outputColourSpaceConvert = IPCOLOURSPACE_UNCHANGED;
              bool packedYUVMode = false;
              bool clipOutputVideoToRec709Range = false;
              if( m_pcCfg->getUpscaledOutput() )
              {
    
    #if JVET_AB0082
                ioBeforeInLoop.writeUpscaledPicture(*sps, *pcPic->cs->pps, pcPic->getRecoBuf(), outputColourSpaceConvert, packedYUVMode, m_pcCfg->getUpscaledOutput(), NUM_CHROMA_FORMAT, clipOutputVideoToRec709Range, m_pcCfg->getUpscaleFilerForDisplay());
    #else
    
    Vadim Seregin's avatar
    Vadim Seregin committed
                ioBeforeInLoop.writeUpscaledPicture( *sps, *pcPic->cs->pps, pcPic->getRecoBuf(), outputColourSpaceConvert, packedYUVMode, m_pcCfg->getUpscaledOutput(), NUM_CHROMA_FORMAT, clipOutputVideoToRec709Range );
    
    Vadim Seregin's avatar
    Vadim Seregin committed
              }
              else
              {
                ioBeforeInLoop.write( pcPic->getRecoBuf().get( COMPONENT_Y ).width, pcPic->getRecoBuf().get( COMPONENT_Y ).height, pcPic->getRecoBuf(),
                  outputColourSpaceConvert,
                  packedYUVMode,
                  conf.getWindowLeftOffset() * SPS::getWinUnitX( chromaFormatIDC ),
                  conf.getWindowRightOffset() * SPS::getWinUnitX( chromaFormatIDC ),
                  conf.getWindowTopOffset() * SPS::getWinUnitY( chromaFormatIDC ),
                  conf.getWindowBottomOffset() * SPS::getWinUnitY( chromaFormatIDC ),
                  NUM_CHROMA_FORMAT, clipOutputVideoToRec709Range );
              }
            }
          }
    #endif
    
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #if JVET_Z0118_GDR
          pcPic->setCleanDirty(false); 
    #endif
    
    
          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);
    
    Vadim Seregin's avatar
    Vadim Seregin committed
            if( m_pcCfg->getGopBasedTemporalFilterEnabled() )
            {
              pcPic->getOrigBuf().copyFrom( pcPic->getFilteredOrigBuf() );
            }
            else
            {
              pcPic->getOrigBuf().copyFrom( pcPic->getTrueOrigBuf() );
            }
    
    #if JVET_AA0095_ALF_WITH_SAMPLES_BEFORE_DBF
          if (pcSlice->getSPS()->getALFEnabledFlag())
          {
    
            // create ALF object based on the picture size
            Size alfSize = m_pcALF->getAlfSize();
            if (alfSize.width != picWidth || alfSize.height != picHeight)
            {
              m_pcALF->destroy();
              m_pcALF->create(m_pcCfg, picWidth, picHeight, chromaFormatIDC, maxCUWidth, maxCUHeight, maxTotalCUDepth, m_pcCfg->getBitDepth(), m_pcCfg->getInputBitDepth());
            }
    
    
    #if JVET_AC0162_ALF_RESIDUAL_SAMPLES_INPUT
          if (pcSlice->getSPS()->getALFEnabledFlag())
          {
            // create ALF object based on the picture size
            Size alfSize = m_pcALF->getAlfSize();
            if (alfSize.width != picWidth || alfSize.height != picHeight)
            {
              m_pcALF->destroy();
              m_pcALF->create(m_pcCfg, picWidth, picHeight, chromaFormatIDC, maxCUWidth, maxCUHeight, maxTotalCUDepth,
                              m_pcCfg->getBitDepth(), m_pcCfg->getInputBitDepth());
            }
    
            m_pcALF->copyResiData(cs);
          }
    #endif
    
    Philippe Bordes's avatar
    Philippe Bordes committed
          // create SAO object based on the picture size
    
    Vadim Seregin's avatar
    Vadim Seregin committed
          if( pcSlice->getSPS()->getSAOEnabledFlag()
    
    #if JVET_W0066_CCSAO
              || pcSlice->getSPS()->getCCSAOEnabledFlag()
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if JVET_V0094_BILATERAL_FILTER
              || pcSlice->getPPS()->getUseBIF()
    
    #endif
    #if JVET_X0071_CHROMA_BILATERAL_FILTER
              || pcSlice->getPPS()->getUseChromaBIF()
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
              )
    
    Philippe Bordes's avatar
    Philippe Bordes committed
          {
            Size saoSize = m_pcSAO->getSaoSize();
    
            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);
    
            if ( saoSize.width != picWidth || saoSize.height != picHeight ) 
            {
    
    Philippe Bordes's avatar
    Philippe Bordes committed
              m_pcSAO->create(picWidth, picHeight, chromaFormatIDC, maxCUWidth, maxCUHeight, maxTotalCUDepth, log2SaoOffsetScaleLuma, log2SaoOffsetScaleChroma);
              m_pcSAO->setReshaper(m_pcReshaper);
            }
    
    
            // create SAO encoder data based on the picture size
            m_pcSAO->destroyEncData();
            m_pcSAO->createEncData(m_pcCfg->getSaoCtuBoundary(), numCtuInFrame);
    
          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() )
    
    Vadim Seregin's avatar
    Vadim Seregin committed
            // This is fine to skip even if SAO=0 and BIF=1.
    
            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
          }
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if DB_PARAM_TID
          else
          {
            applyDeblockingFilterParameterSelection( pcPic, pcSlice, uiNumSliceSegments, iGOPid );
          }
    #endif
    
    
          if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING) 
          {
            for (int s = 0; s < uiNumSliceSegments; s++)
            {
              if (pcPic->slices[s]->isLossless())
              {
                pcPic->slices[s]->setDeblockingFilterDisable(true);
              }
            }
          }
    
    #if JVET_AB0171_ASYMMETRIC_DB_FOR_GDR
          if (m_pcCfg->getAsymmetricILF() && (pcPic->cs->picHeader->getInGdrInterval() || pcPic->cs->picHeader->getIsGdrRecoveryPocPic()))
          {
            m_pcLoopFilter->setAsymmetricDB(true);
          }
          else
          {
            m_pcLoopFilter->setAsymmetricDB(false);
          }
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if !MULTI_PASS_DMVR
    
          CS::setRefinedMotionField(cs);
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    #if JVET_AE0043_CCP_MERGE_TEMPORAL
          if ((pcPic->temporalId == 0) || (pcPic->temporalId < pcSlice->getSPS()->getMaxTLayers() - 1))
          {
            CS::saveTemporalCcpModel(cs);
          }
    #endif
    
    
    Xiaoyu Xiu's avatar
    Xiaoyu Xiu committed
    #if JVET_W0066_CCSAO
          if ( cs.sps->getCCSAOEnabledFlag() )
          {
            m_pcSAO->getCcSaoBuf().copyFrom( cs.getRecoBuf() );
          }
    #endif
    
    
    #if JVET_V0094_BILATERAL_FILTER
    
    #if JVET_X0071_CHROMA_BILATERAL_FILTER
    
          if( pcSlice->getSPS()->getSAOEnabledFlag() || pcSlice->getPPS()->getUseBIF() || pcSlice->getPPS()->getUseChromaBIF())
    
    Vadim Seregin's avatar
    Vadim Seregin committed
          // We need to do this step if at least one of BIF or SAO are enabled.
          if( pcSlice->getSPS()->getSAOEnabledFlag() || pcSlice->getPPS()->getUseBIF())
    
    #endif
    #else
    #if JVET_X0071_CHROMA_BILATERAL_FILTER
    
          if( pcSlice->getSPS()->getSAOEnabledFlag() || pcSlice->getPPS()->getUseChromaBIF())
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #else
    
          if( pcSlice->getSPS()->getSAOEnabledFlag() )
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
          {
            bool sliceEnabled[MAX_NUM_COMPONENT];
            m_pcSAO->initCABACEstimator( m_pcEncLib->getCABACEncoder(), m_pcEncLib->getCtxCache(), pcSlice );
    
    #if JVET_V0094_BILATERAL_FILTER
    
    Vadim Seregin's avatar
    Vadim Seregin committed
            BIFCabacEstImp est(m_pcEncLib->getCABACEncoder()->getCABACEstimator(cs.slice->getSPS()));
    
            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
    
    Vadim Seregin's avatar
    Vadim Seregin committed
                                 m_pcCfg->getTestSAODisableAtPictureLevel(), m_pcCfg->getSaoEncodingRate(), m_pcCfg->getSaoEncodingRateChroma(), m_pcCfg->getSaoCtuBoundary(), m_pcCfg->getSaoGreedyMergeEnc()
    
    #if JVET_V0094_BILATERAL_FILTER
    
    Vadim Seregin's avatar
    Vadim Seregin committed
                                  , &est
    #endif
                                );
    
    #if JVET_V0094_BILATERAL_FILTER || JVET_X0071_CHROMA_BILATERAL_FILTER
    
    Vadim Seregin's avatar
    Vadim Seregin committed
            if( pcSlice->getSPS()->getSAOEnabledFlag() )
            {
    #endif
    
            for (int s = 0; s < uiNumSliceSegments; s++)
    
    
              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
              {
                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_V0094_BILATERAL_FILTER || JVET_X0071_CHROMA_BILATERAL_FILTER
    
    Vadim Seregin's avatar
    Vadim Seregin committed
          }
    #endif
    
    Xiaoyu Xiu's avatar
    Xiaoyu Xiu committed
    #if JVET_W0066_CCSAO
          if ( pcSlice->getSPS()->getCCSAOEnabledFlag() )
          {
            m_pcSAO->initCABACEstimator( m_pcEncLib->getCABACEncoder(), m_pcEncLib->getCtxCache(), pcSlice );
            m_pcSAO->CCSAOProcess( cs, pcSlice->getLambdas(), m_pcCfg->getIntraPeriod() );
    
            //assign CCSAO slice header
            for (int s = 0; s < uiNumSliceSegments; s++)
            {
              pcPic->slices[s]->m_ccSaoComParam              = m_pcSAO->getCcSaoComParam();
              pcPic->slices[s]->m_ccSaoControl[COMPONENT_Y]  = m_pcSAO->getCcSaoControlIdc(COMPONENT_Y);
              pcPic->slices[s]->m_ccSaoControl[COMPONENT_Cb] = m_pcSAO->getCcSaoControlIdc(COMPONENT_Cb);
              pcPic->slices[s]->m_ccSaoControl[COMPONENT_Cr] = m_pcSAO->getCcSaoControlIdc(COMPONENT_Cr);
            }
          }
          m_pcSAO->jointClipSaoBifCcSao( cs );
    #endif
    
    
          if( pcSlice->getSPS()->getSAOEnabledFlag()
    #if JVET_W0066_CCSAO
           || pcSlice->getSPS()->getCCSAOEnabledFlag()
    #endif
            )
          {
            m_pcSAO->destroyEncData();
          }
    
    
    #if RPR_ENABLE && !JVET_AA0095_ALF_WITH_SAMPLES_BEFORE_DBF
    
    Philippe Bordes's avatar
    Philippe Bordes committed
          // create ALF object based on the picture size
          if ( pcSlice->getSPS()->getALFEnabledFlag() )
          {
            Size alfSize = m_pcALF->getAlfSize();
    
    Vadim Seregin's avatar
    Vadim Seregin committed
            if ( alfSize.width != picWidth || alfSize.height != picHeight )
            {
    
    Philippe Bordes's avatar
    Philippe Bordes committed
              m_pcALF->destroy();
              m_pcALF->create( m_pcCfg, picWidth, picHeight, chromaFormatIDC, maxCUWidth, maxCUHeight, maxTotalCUDepth, m_pcCfg->getBitDepth(), m_pcCfg->getInputBitDepth() );
            }
          }
    #endif
    
    
          if( pcSlice->getSPS()->getALFEnabledFlag() )
    
            // create ALF encoder data based on the picture size
    
            m_pcALF->create(m_pcCfg, picWidth, picHeight, chromaFormatIDC, maxCUWidth, maxCUHeight, maxTotalCUDepth, m_pcCfg->getBitDepth(), m_pcCfg->getInputBitDepth(), true);
    
    
            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
              , pcPic, uiNumSliceSegments
    
    #if JVET_AC0162_ALF_RESIDUAL_SAMPLES_INPUT
              , m_pcCfg->getIntraPeriod()
    #endif
    
            //assign ALF slice header
            for (int s = 0; s < uiNumSliceSegments; s++)
            {
    
               //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
              {
                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 (pcPic->slices[s]->getTileGroupAlfEnabledFlag(COMPONENT_Y))
              {
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if ALF_IMPROVEMENT
    
    #if JVET_AG0157_ALF_CHROMA_FIXED_FILTER
                pcPic->slices[s]->setTileGroupAlfFixedFilterSetIdx(COMPONENT_Y, cs.slice->getTileGroupAlfFixedFilterSetIdx(COMPONENT_Y));
    #else
    
    Vadim Seregin's avatar
    Vadim Seregin committed
                pcPic->slices[s]->setTileGroupAlfFixedFilterSetIdx(cs.slice->getTileGroupAlfFixedFilterSetIdx());
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
                pcPic->slices[s]->setTileGroupNumAps(cs.slice->getTileGroupNumAps());
    
                pcPic->slices[s]->setAlfAPSs(cs.slice->getTileGroupApsIdLuma());
    
              if( s < uiNumSliceSegments - 1 )
              {
                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());
    
    #if JVET_AG0157_ALF_CHROMA_FIXED_FILTER
              pcPic->slices[s]->setTileGroupAlfFixedFilterSetIdx(COMPONENT_Cb, cs.slice->getTileGroupAlfFixedFilterSetIdx(COMPONENT_Cb));
              pcPic->slices[s]->setTileGroupAlfFixedFilterSetIdx(COMPONENT_Cr, cs.slice->getTileGroupAlfFixedFilterSetIdx(COMPONENT_Cr));
    #endif
    
              pcPic->slices[s]->m_ccAlfFilterParam      = m_pcALF->getCcAlfFilterParam();
              pcPic->slices[s]->m_ccAlfFilterControl[0] = m_pcALF->getCcAlfControlIdc(COMPONENT_Cb);
              pcPic->slices[s]->m_ccAlfFilterControl[1] = m_pcALF->getCcAlfControlIdc(COMPONENT_Cr);
    
          DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "final", 1 ) ) );
    
          if (m_pcCfg->getUseCompositeRef() && getPrepareLTRef())
    
          {
            updateCompositeReference(pcSlice, rcListPic, pocCurr);
          }
    
        }
        else // skip enc picture
        {
          pcSlice->setSliceQpBase( pcSlice->getSliceQp() );
    
    
    #if JVET_Z0135_TEMP_CABAC_WIN_WEIGHT 
          m_pcSliceEncoder->getCABACDataStore()->updateBufferState( pcSlice );
    #endif
    
    #if JVET_AG0098_AMVP_WITH_SBTMVP
          m_pcSliceEncoder->clearAmvpSbTmvpStatArea(pcSlice);
    #endif
    
    #if ENABLE_QPA
          if (m_pcCfg->getUsePerceptQPA() && !m_pcCfg->getUseRateCtrl() && pcSlice->getPPS()->getUseDQP())
          {
            const double picLambda = pcSlice->getLambdas()[0];
    
            for (uint32_t ctuRsAddr = 0; ctuRsAddr < numberOfCtusInFrame; ctuRsAddr++)
            {
              pcPic->m_uEnerHpCtu[ctuRsAddr] = picLambda;  // initialize to slice lambda (just for safety)
            }
          }
    #endif
    
          if( pcSlice->getSPS()->getSAOEnabledFlag() )
    
    Vadim Seregin's avatar
    Vadim Seregin committed
            // This does not need to be run even if BIF=1.
    
            m_pcSAO->disabledRate( *pcPic->cs, pcPic->getSAO(1), m_pcCfg->getSaoEncodingRate(), m_pcCfg->getSaoEncodingRateChroma());
          }
    
          if (pcSlice->getSPS()->getALFEnabledFlag() && (pcSlice->getTileGroupAlfEnabledFlag(COMPONENT_Y) || pcSlice->getTileGroupCcAlfCbEnabledFlag() || pcSlice->getTileGroupCcAlfCrEnabledFlag()))
          {
            // IRAP AU: reset APS map
            {
              int layerIdx = pcSlice->getVPS() == nullptr ? 0 : pcSlice->getVPS()->getGeneralLayerIdx( pcSlice->getPic()->layerId );
              if( !layerIdx && ( pcSlice->getPendingRasInit() || pcSlice->isIDRorBLA() ) )
              {
                // We have to reset all APS on IRAP, but in not encoding case we have to keep the parsed APS of current slice
                // Get active ALF APSs from picture/slice header
                const std::vector<int> sliceApsIdsLuma = pcSlice->getTileGroupApsIdLuma();
    
                m_pcALF->setApsIdStart( ALF_CTB_MAX_NUM_APS );
    
                ParameterSetMap<APS>* apsMap = m_pcEncLib->getApsMap();
                apsMap->clear();
    
                for( int apsId = 0; apsId < ALF_CTB_MAX_NUM_APS; apsId++ )
                {
                  int psId = ( apsId << NUM_APS_TYPE_LEN ) + ALF_APS;
                  APS* aps = apsMap->getPS( psId );
                  if( aps )
                  {
                    // Check if this APS is currently the active one (used in current slice)
                    bool activeAps = false;
                    bool activeApsCcAlf = false;
                    // Luma
                    for( int i = 0; i < sliceApsIdsLuma.size(); i++ )
                    {
                      if( aps->getAPSId() == sliceApsIdsLuma[i] )
                      {
                        activeAps = true;
                        break;
                      }
                    }
                    // Chroma
                    activeAps |= aps->getAPSId() == pcSlice->getTileGroupApsIdChroma();
                    // CC-ALF
                    activeApsCcAlf |= pcSlice->getTileGroupCcAlfCbEnabledFlag() && aps->getAPSId() == pcSlice->getTileGroupCcAlfCbApsId();
                    activeApsCcAlf |= pcSlice->getTileGroupCcAlfCrEnabledFlag() && aps->getAPSId() == pcSlice->getTileGroupCcAlfCrApsId();
                    if( !activeAps && !activeApsCcAlf )
                    {
                      apsMap->clearChangedFlag( psId );
                    }
                    if( !activeAps  )
                    {
                      aps->getAlfAPSParam().reset();
                    }
                    if( !activeApsCcAlf )
                    {
                      aps->getCcAlfAPSParam().reset();
                    }
                  }
                }
              }
            }
    
            // Assign tne correct APS to slice and emulate the setting of ALF start APS ID
            int changedApsId = -1;
            for( int apsId = ALF_CTB_MAX_NUM_APS - 1; apsId >= 0; apsId-- )
            {
              ParameterSetMap<APS>* apsMap = m_pcEncLib->getApsMap();
              int psId = ( apsId << NUM_APS_TYPE_LEN ) + ALF_APS;
              APS* aps = apsMap->getPS( psId );
              if( aps )
              {
                // In slice, replace the old APS (from decoder map) with the APS from encoder map due to later checks while bitstream writing
                if( pcSlice->getAlfAPSs() && pcSlice->getAlfAPSs()[apsId] )
                {
                  pcSlice->getAlfAPSs()[apsId] = aps;
                }
                if( apsMap->getChangedFlag( psId ) )
                  changedApsId = apsId;
              }
            }
            if( changedApsId >= 0 )
              m_pcALF->setApsIdStart( changedApsId );
          }
    
        pcSlice->freeScaledRefPicList( scaledRefPic );
    
    
        if( m_pcCfg->getUseAMaxBT() )
        {
          for( const CodingUnit *cu : pcPic->cs->cus )
          {
    
            {
              m_uiBlkSize[pcSlice->getDepth()] += cu->Y().area();
              m_uiNumBlk [pcSlice->getDepth()]++;
            }
          }
        }
    
        if( encPic || decPic )
        {
          pcSlice = pcPic->slices[0];
    
          /////////////////////////////////////////////////////////////////////////////////////////////////// File writing
    
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if EMBEDDED_APS
          m_aps.clear();
    #endif
    
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if JVET_Z0118_GDR // note : insert SPS/PPS at every GDR picture
    
    Seungwook Hong's avatar
    Seungwook Hong committed
          bool writePS = m_bSeqFirst || (m_pcCfg->getReWriteParamSets() && (pcSlice->isIRAP())) || pcSlice->isInterGDR();
    #else
    
          bool writePS = m_bSeqFirst || (m_pcCfg->getReWriteParamSets() && (pcSlice->isIRAP()));
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #endif
    
          if (writePS)
          {
            m_pcEncLib->setParamSetChanged(pcSlice->getSPS()->getSPSId(), pcSlice->getPPS()->getPPSId());
          }
    
          int layerIdx = m_pcEncLib->getVPS() == nullptr ? 0 : m_pcEncLib->getVPS()->getGeneralLayerIdx( m_pcEncLib->getLayerId() );
    
          // it is assumed that layerIdx equal to 0 is always present
          m_audIrapOrGdrAuFlag = pcSlice->getPicHeader()->getGdrPicFlag() || (pcSlice->isIRAP() && !pcSlice->getPPS()->getMixedNaluTypesInPicFlag());
          if ((( m_pcEncLib->getVPS()->getMaxLayers() > 1 && m_audIrapOrGdrAuFlag) || m_pcCfg->getAccessUnitDelimiter()) && !layerIdx )
          {
            xWriteAccessUnitDelimiter(accessUnit, pcSlice);
          }
    
    
          // it is assumed that layerIdx equal to 0 is always present
    
    BDChoi's avatar
    BDChoi committed
          actualTotalBits += xWriteParameterSets(accessUnit, pcSlice, writePS, layerIdx);
    
          {
            // create prefix SEI messages at the beginning of the sequence
            CHECK(!(leadingSeiMessages.empty()), "Unspecified error");
            xCreateIRAPLeadingSEIMessages(leadingSeiMessages, pcSlice->getSPS(), pcSlice->getPPS());
    
            m_bSeqFirst = false;
          }
    
    
          //send LMCS APS when LMCSModel is updated. It can be updated even current slice does not enable reshaper.
          //For example, in RA, update is on intra slice, but intra slice may not use reshaper
    
          if (pcSlice->getSPS()->getUseLmcs())
    
          {
            //only 1 LMCS data for 1 picture
    
    Brian Heng's avatar
    Brian Heng committed
            int apsId = picHeader->getLmcsAPSId();
    
            ParameterSetMap<APS> *apsMap = m_pcEncLib->getApsMap();
            APS* aps = apsMap->getPS((apsId << NUM_APS_TYPE_LEN) + LMCS_APS);
            bool writeAPS = aps && apsMap->getChangedFlag((apsId << NUM_APS_TYPE_LEN) + LMCS_APS);
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #if JVET_Z0118_GDR // note : insert APS at every GDR picture
            if (aps && apsId >= 0)
            {
              writeAPS |= pcSlice->isInterGDR();
            }
    #endif
    
    #if JVET_R0433
              aps->chromaPresentFlag = pcSlice->getSPS()->getChromaFormatIdc() != CHROMA_400;
    #endif
    
              actualTotalBits += xWriteAPS( accessUnit, aps, m_pcEncLib->getLayerId(), true );
    
              apsMap->clearChangedFlag((apsId << NUM_APS_TYPE_LEN) + LMCS_APS);
    
    Seungwook Hong's avatar
    Seungwook Hong committed
    #if JVET_Z0118_GDR
              if (!pcSlice->isInterGDR())