Newer
Older
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
pcSlice->setImRefIdx(sliceIdx, RefPicList(colRefPicListIdx), RefPicList(curRefPicListIdx), colRefIdx, targetRefIdx);
} // curRefPicListIdx
}
}
}
}
#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
}
#endif
}
#if JVET_Y0128_NON_CTC
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);
}
bool bDisableTMVP = pcSlice->scaleRefPicList( scaledRefPic, pcPic->cs->picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false );
if ( picHeader->getEnableTMVPFlag() && bDisableTMVP )
{
picHeader->setEnableTMVPFlag( 0 );
}
#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;
#else
pcSlice->scaleRefPicList( scaledRefPic, pcPic->cs->picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false );
#endif

Karsten Suehring
committed
// set adaptive search range for non-intra-slices
if (m_pcCfg->getUseASR() && !pcSlice->isIntra())

Karsten Suehring
committed
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
{
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)
{

Karsten Suehring
committed
}
else
{

Karsten Suehring
committed
}
if ( pcSlice->getSPS()->getUseSMVD() && pcSlice->getCheckLDC() == false
{
int currPOC = pcSlice->getPOC();
int forwardPOC = 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 )
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 )
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 )
{
forwardPOC = poc;
refIdx1 = ref;
}
}
}
{
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

Karsten Suehring
committed
double lambda = 0.0;
int actualHeadBits = 0;
int actualTotalBits = 0;
int estimatedBits = 0;
int tmpBitsBeforeWriting = 0;

Karsten Suehring
committed
xPicInitRateControl(estimatedBits, iGOPid, lambda, pcPic, pcSlice);

Karsten Suehring
committed
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();
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());

Karsten Suehring
committed
std::vector<OutputBitstream> substreamsOut(numSubstreams);
#if ENABLE_QPA

Christian Helmrich
committed
pcPic->m_uEnerHpCtu.resize (numberOfCtusInFrame);
pcPic->m_iOffsetCtu.resize (numberOfCtusInFrame);
if (pcSlice->getPPS()->getUseDQP() && pcSlice->getCuQpDeltaSubdiv() > 0)

Christian Helmrich
committed
{
const PreCalcValues &pcv = *pcPic->cs->pcv;
const unsigned mtsLog2 = (unsigned)floorLog2(std::min (pcPic->cs->sps->getMaxTbSize(), pcv.maxCUWidth));

Christian Helmrich
committed
pcPic->m_subCtuQP.resize ((pcv.maxCUWidth >> mtsLog2) * (pcv.maxCUHeight >> mtsLog2));
}

Karsten Suehring
committed
#endif
#if JVET_X0071_CHROMA_BILATERAL_FILTER
if (pcSlice->getSPS()->getSAOEnabledFlag() || pcSlice->getPPS()->getUseBIF() || pcSlice->getPPS()->getUseChromaBIF())
// 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())
if (pcSlice->getSPS()->getSAOEnabledFlag())
#endif

Karsten Suehring
committed
{
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() )

Karsten Suehring
committed
{
pcPic->resizeAlfCtuEnableFlag( numberOfCtusInFrame );
pcPic->resizeAlfCtuAlternative( numberOfCtusInFrame );
pcPic->resizeAlfCtbFilterIndex(numberOfCtusInFrame);

Karsten Suehring
committed
}
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() );

Karsten Suehring
committed
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

Karsten Suehring
committed
{
#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))
#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

Karsten Suehring
committed
if( pcSlice->getSPS()->getScalingListFlag() && m_pcCfg->getUseScalingListId() == SCALING_LIST_FILE_READ )
{
picHeader->setExplicitScalingListEnabledFlag( true );
pcSlice->setExplicitScalingListUsed( true );
int apsId = std::min<int>( 7, m_pcEncLib->getVPS() == nullptr ? 0 : m_pcEncLib->getVPS()->getGeneralLayerIdx( m_pcEncLib->getLayerId() ) );
ParameterSetMap<APS> *apsMap = m_pcEncLib->getApsMap();
APS* scalingListAPS = apsMap->getPS( ( apsId << NUM_APS_TYPE_LEN ) + SCALING_LIST_APS );
assert( scalingListAPS != NULL );
picHeader->setScalingListAPS( scalingListAPS );
}
pcPic->cs->picHeader->setPic(pcPic);
pcPic->cs->picHeader->setValid();
if(pcPic->cs->sps->getFpelMmvdEnabledFlag())
Jonatan Samuelsson-Allendes
committed
// cannot set ph_fpel_mmvd_enabled_flag at slice level - need new picture-level version of checkDisFracMmvd algorithm?
// 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 ) );
Vadim Seregin
committed
if( pcPic->cs->pps->getRectSliceFlag() )
{
Position firstCtu;
firstCtu.x = pcSlice->getFirstCtuRsAddrInSlice() % pcPic->cs->pps->getPicWidthInCtu();
firstCtu.y = pcSlice->getFirstCtuRsAddrInSlice() / pcPic->cs->pps->getPicWidthInCtu();
Vadim Seregin
committed
int subPicIdx = NOT_VALID;
for( int sp = 0; sp < pcPic->cs->pps->getNumSubPics(); sp++ )
Vadim Seregin
committed
if( pcPic->cs->pps->getSubPic( sp ).containsCtu( firstCtu ) )
Vadim Seregin
committed
break;
Vadim Seregin
committed
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( 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)
{
clipMv = clipMvInSubpic;
m_pcEncLib->getInterSearch()->setClipMvInSubPic(true);
}
else
{
clipMv = clipMvInPic;
m_pcEncLib->getInterSearch()->setClipMvInSubPic(false);

Karsten Suehring
committed
m_pcSliceEncoder->precompressSlice( pcPic );
m_pcSliceEncoder->compressSlice ( pcPic, false, false );
if(sliceIdx < pcPic->cs->pps->getNumSlicesInPic() - 1)

Karsten Suehring
committed
{
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();
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
#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() )
{
Kenneth Andersson
committed
#if JVET_AB0082
ioBeforeInLoop.writeUpscaledPicture(*sps, *pcPic->cs->pps, pcPic->getRecoBuf(), outputColourSpaceConvert, packedYUVMode, m_pcCfg->getUpscaledOutput(), NUM_CHROMA_FORMAT, clipOutputVideoToRec709Range, m_pcCfg->getUpscaleFilerForDisplay());
#else
ioBeforeInLoop.writeUpscaledPicture( *sps, *pcPic->cs->pps, pcPic->getRecoBuf(), outputColourSpaceConvert, packedYUVMode, m_pcCfg->getUpscaledOutput(), NUM_CHROMA_FORMAT, clipOutputVideoToRec709Range );
Kenneth Andersson
committed
#endif
}
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
#if JVET_Z0118_GDR
pcPic->setCleanDirty(false);
#endif

Karsten Suehring
committed
CodingStructure& cs = *pcPic->cs;
pcSlice = pcPic->slices[0];
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
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);
if( m_pcCfg->getGopBasedTemporalFilterEnabled() )
{
pcPic->getOrigBuf().copyFrom( pcPic->getFilteredOrigBuf() );
}
else
{
pcPic->getOrigBuf().copyFrom( pcPic->getTrueOrigBuf() );
}
Nan Hu
committed
}
Nan Hu
committed
#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());
}
Nan Hu
committed
m_pcALF->copyDbData(cs);
Nan Hu
committed
#endif
#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
#if JVET_W0066_CCSAO
|| pcSlice->getSPS()->getCCSAOEnabledFlag()
#endif
#if JVET_V0094_BILATERAL_FILTER
|| pcSlice->getPPS()->getUseBIF()
#endif
#if JVET_X0071_CHROMA_BILATERAL_FILTER
|| pcSlice->getPPS()->getUseChromaBIF()
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 )
{
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);
int apsId = 0;
picHeader->setScalingListAPSId( apsId );
}

Karsten Suehring
committed
// SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas
if( pcSlice->getSPS()->getSAOEnabledFlag() && m_pcCfg->getSaoCtuBoundary() )

Karsten Suehring
committed
{

Karsten Suehring
committed
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 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

Karsten Suehring
committed
m_pcLoopFilter->loopFilterPic( cs );
CS::setRefinedMotionField(cs);

Karsten Suehring
committed
#if JVET_AE0043_CCP_MERGE_TEMPORAL
if ((pcPic->temporalId == 0) || (pcPic->temporalId < pcSlice->getSPS()->getMaxTLayers() - 1))
{
CS::saveTemporalCcpModel(cs);
}
#endif
#if JVET_W0066_CCSAO
if ( cs.sps->getCCSAOEnabledFlag() )
{
m_pcSAO->getCcSaoBuf().copyFrom( cs.getRecoBuf() );
}
#endif
#if JVET_X0071_CHROMA_BILATERAL_FILTER
if( pcSlice->getSPS()->getSAOEnabledFlag() || pcSlice->getPPS()->getUseBIF() || pcSlice->getPPS()->getUseChromaBIF())
// 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())
if( pcSlice->getSPS()->getSAOEnabledFlag() )
#endif

Karsten Suehring
committed
{
bool sliceEnabled[MAX_NUM_COMPONENT];
m_pcSAO->initCABACEstimator( m_pcEncLib->getCABACEncoder(), m_pcEncLib->getCtxCache(), pcSlice );
BIFCabacEstImp est(m_pcEncLib->getCABACEncoder()->getCABACEstimator(cs.slice->getSPS()));

Christian Helmrich
committed
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()

Karsten Suehring
committed
//assign SAO slice header
#if JVET_V0094_BILATERAL_FILTER || JVET_X0071_CHROMA_BILATERAL_FILTER
if( pcSlice->getSPS()->getSAOEnabledFlag() )
{
#endif
for (int s = 0; s < uiNumSliceSegments; s++)

Karsten Suehring
committed
{
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]);
}

Karsten Suehring
committed
}
#if JVET_V0094_BILATERAL_FILTER || JVET_X0071_CHROMA_BILATERAL_FILTER

Karsten Suehring
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
// create ALF object based on the picture size
if ( pcSlice->getSPS()->getALFEnabledFlag() )
{
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() );
}
}
#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
);

Christian Helmrich
committed
//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))
{
#if JVET_AG0157_ALF_CHROMA_FIXED_FILTER
pcPic->slices[s]->setTileGroupAlfFixedFilterSetIdx(COMPONENT_Y, cs.slice->getTileGroupAlfFixedFilterSetIdx(COMPONENT_Y));
#else
pcPic->slices[s]->setTileGroupAlfFixedFilterSetIdx(cs.slice->getTileGroupAlfFixedFilterSetIdx());
pcPic->slices[s]->setTileGroupNumAps(cs.slice->getTileGroupNumAps());
pcPic->slices[s]->setAlfAPSs(cs.slice->getTileGroupApsIdLuma());
}
else
{
pcPic->slices[s]->setTileGroupNumAps(0);
}
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);
m_pcALF->destroy(true);

Karsten Suehring
committed
}
DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "final", 1 ) ) );
if (m_pcCfg->getUseCompositeRef() && getPrepareLTRef())
{
updateCompositeReference(pcSlice, rcListPic, pocCurr);
}

Karsten Suehring
committed
}
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

Christian Helmrich
committed
#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() )

Karsten Suehring
committed
{

Karsten Suehring
committed
m_pcSAO->disabledRate( *pcPic->cs, pcPic->getSAO(1), m_pcCfg->getSaoEncodingRate(), m_pcCfg->getSaoEncodingRateChroma());
}
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
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 );
}

Karsten Suehring
committed
}
pcSlice->freeScaledRefPicList( scaledRefPic );

Karsten Suehring
committed
if( m_pcCfg->getUseAMaxBT() )
{
for( const CodingUnit *cu : pcPic->cs->cus )
{
if( !pcSlice->isIntra() )

Karsten Suehring
committed
{
m_uiBlkSize[pcSlice->getDepth()] += cu->Y().area();
m_uiNumBlk [pcSlice->getDepth()]++;
}
}
}
if( encPic || decPic )
{
pcSlice = pcPic->slices[0];
/////////////////////////////////////////////////////////////////////////////////////////////////// File writing

Karsten Suehring
committed
// write various parameter sets
#if JVET_Z0118_GDR // note : insert SPS/PPS at every GDR picture
bool writePS = m_bSeqFirst || (m_pcCfg->getReWriteParamSets() && (pcSlice->isIRAP())) || pcSlice->isInterGDR();
#else
bool writePS = m_bSeqFirst || (m_pcCfg->getReWriteParamSets() && (pcSlice->isIRAP()));
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() );
Zhipin Deng
committed
// 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
actualTotalBits += xWriteParameterSets(accessUnit, pcSlice, writePS, layerIdx);

Karsten Suehring
committed
{
// 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
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);
#if JVET_Z0118_GDR // note : insert APS at every GDR picture
if (aps && apsId >= 0)
{
writeAPS |= pcSlice->isInterGDR();
}
#endif
if (writeAPS)
{
#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);
#if JVET_Z0118_GDR
if (!pcSlice->isInterGDR())