Newer
Older

Karsten Suehring
committed
std::deque<DUData> duData;
EfficientFieldIRAPMapping effFieldIRAPMap;
if (m_pcCfg->getEfficientFieldIRAPEnabled())
{
effFieldIRAPMap.initialize(isField, m_iGopSize, iPOCLast, iNumPicRcvd, m_iLastIDR, this, m_pcCfg);
}
if( isField && picIdInGOP == 0 )
{
for( int iGOPid = 0; iGOPid < max(2, m_iGopSize); iGOPid++ )
{
m_pcCfg->setEncodedFlag( iGOPid, false );
}
}
for( int iGOPid = picIdInGOP; iGOPid <= picIdInGOP; iGOPid++ )
{
// reset flag indicating whether pictures have been encoded
m_pcCfg->setEncodedFlag( iGOPid, false );

Karsten Suehring
committed
if (m_pcCfg->getEfficientFieldIRAPEnabled())
{
iGOPid=effFieldIRAPMap.adjustGOPid(iGOPid);
}
//-- For time output for each slice
auto beforeTime = std::chrono::steady_clock::now();
#if !X0038_LAMBDA_FROM_QP_CAPABILITY
uint32_t uiColDir = calculateCollocatedFromL1Flag(m_pcCfg, iGOPid, m_iGopSize);
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////// Initial to start encoding
int iTimeOffset;
int pocCurr;
int multipleFactor = m_pcCfg->getUseCompositeRef() ? 2 : 1;

Karsten Suehring
committed
if(iPOCLast == 0) //case first frame or first top field
{
pocCurr=0;
iTimeOffset = multipleFactor;

Karsten Suehring
committed
}
else if(iPOCLast == 1 && isField) //case first bottom field, just like the first frame, the poc computation is not right anymore, we set the right value
{
pocCurr = 1;
iTimeOffset = 1;
}
else
{
pocCurr = iPOCLast - iNumPicRcvd * multipleFactor + m_pcCfg->getGOPEntry(iGOPid).m_POC - ((isField && m_iGopSize>1) ? 1 : 0);

Karsten Suehring
committed
iTimeOffset = m_pcCfg->getGOPEntry(iGOPid).m_POC;
}
if (m_pcCfg->getUseCompositeRef() && isEncodeLtRef)
{
pocCurr++;
iTimeOffset--;
}
if (pocCurr / multipleFactor >= m_pcCfg->getFramesToBeEncoded())

Karsten Suehring
committed
{
if (m_pcCfg->getEfficientFieldIRAPEnabled())
{
iGOPid=effFieldIRAPMap.restoreGOPid(iGOPid);
}
continue;
}
if( getNalUnitType(pocCurr, m_iLastIDR, isField) == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType(pocCurr, m_iLastIDR, isField) == NAL_UNIT_CODED_SLICE_IDR_N_LP )
{
m_iLastIDR = pocCurr;
}
// start a new access unit: create an entry in the list of output access units
AccessUnit accessUnit;
Vadim Seregin
committed
accessUnit.temporalId = m_pcCfg->getGOPEntry( iGOPid ).m_temporalId;

Karsten Suehring
committed
xGetBuffer( rcListPic, rcListPicYuvRecOut,
iNumPicRcvd, iTimeOffset, pcPic, pocCurr, isField );
picHeader->setSPSId( pcPic->cs->pps->getSPSId() );
picHeader->setPPSId( pcPic->cs->pps->getPPSId() );
#if JVET_Q0819_PH_CHANGES
// initial two flags to be false
picHeader->setPicInterSliceAllowedFlag(false);
picHeader->setPicIntraSliceAllowedFlag(false);
#endif
#if ER_CHROMA_QP_WCG_PPS

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

Karsten Suehring
committed
// 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();
#if JVET_Q0468_Q0469_MIN_LUMA_CB_AND_MIN_QT_FIX
const int maxTotalCUDepth = floorLog2(maxCUWidth) - pcPic->cs->sps->getLog2MinCodingBlockSize();
#else
const int maxTotalCUDepth = pcPic->cs->sps->getMaxCodingDepth();
#endif
m_pcSliceEncoder->create( picWidth, picHeight, chromaFormatIDC, maxCUWidth, maxCUHeight, maxTotalCUDepth );

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

Karsten Suehring
committed
// Slice data initialization
pcPic->clearSliceBuffer();
pcPic->allocateNewSlice();
m_pcSliceEncoder->setSliceSegmentIdx(0);
m_pcSliceEncoder->initEncSlice(pcPic, iPOCLast, pocCurr, iGOPid, pcSlice, isField
, isEncodeLtRef
);

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

Karsten Suehring
committed
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);
}
#if JVET_Q0819_PH_CHANGES
// 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());
#endif

Karsten Suehring
committed
// Set the nal unit type
pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField));
if (m_pcCfg->getEfficientFieldIRAPEnabled())
{
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

Karsten Suehring
committed
{
m_associatedIRAPType = pcSlice->getNalUnitType();
m_associatedIRAPPOC = pocCurr;
}
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);
}
if (m_pcCfg->getUseCompositeRef() && m_picBg->getSpliceFull() && getUseLTRef())
{
m_pcEncLib->selectReferencePictureList(pcSlice, pocCurr, iGOPid, m_bgPOC);
}
else
{
m_pcEncLib->selectReferencePictureList(pcSlice, pocCurr, iGOPid, -1);
}

Karsten Suehring
committed
if (!m_pcCfg->getEfficientFieldIRAPEnabled())
{
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

Karsten Suehring
committed
{
m_associatedIRAPType = pcSlice->getNalUnitType();
m_associatedIRAPPOC = pocCurr;
}
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 << ".");
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 );

Karsten Suehring
committed
if(pcSlice->getTLayer() > 0
&& !(pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL // Check if not a leading picture
|| pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL)

Karsten Suehring
committed
)
{
if (pcSlice->isStepwiseTemporalLayerSwitchingPointCandidate(rcListPic))

Karsten Suehring
committed
{
bool isSTSA=true;
#if !JVET_Q0156_STSA
if( !m_pcEncLib->getVPS()->getAllIndependentLayersFlag() && m_pcEncLib->getVPS()->getGeneralLayerIdx( m_pcEncLib->getLayerId() ) )
{
isSTSA = false;
}
#endif

Karsten Suehring
committed
for(int ii=iGOPid+1;(ii<m_pcCfg->getGOPSize() && isSTSA==true);ii++)
{
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
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 = m_pcCfg->getRPLEntry(0, ii).m_POC + rpl0->getRefPicIdentifier(jj);
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 = m_pcCfg->getRPLEntry(1, ii).m_POC + rpl1->getRefPicIdentifier(jj);
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;
}
}
}

Karsten Suehring
committed
}
if(isSTSA==true)
{
pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA);

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

Karsten Suehring
committed
// Set reference list
xPicInitHashME( pcPic, pcSlice->getPPS(), rcListPic );

Karsten Suehring
committed
if( m_pcCfg->getUseAMaxBT() )
{

Karsten Suehring
committed
{
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 )
{
#if JVET_Q0330_BLOCK_PARTITION
const int MAX_BT_SIZE_INTER = 128;
#endif
picHeader->setSplitConsOverrideFlag(true);
double dBlkSize = sqrt( ( double ) m_uiBlkSize[refLayer] / m_uiNumBlk[refLayer] );
if( dBlkSize < AMAXBT_TH32 || pcPic->cs->sps->getCTUSize()==32 )
{
picHeader->setMaxBTSize( 1, 32 > MAX_BT_SIZE_INTER ? MAX_BT_SIZE_INTER : 32 );
}
else if( dBlkSize < AMAXBT_TH64 || pcPic->cs->sps->getCTUSize()==64 )
{
picHeader->setMaxBTSize( 1, 64 > MAX_BT_SIZE_INTER ? MAX_BT_SIZE_INTER : 64 );
}
else
{
picHeader->setMaxBTSize( 1, 128 > MAX_BT_SIZE_INTER ? MAX_BT_SIZE_INTER : 128 );
}

Karsten Suehring
committed
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
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)
{

Karsten Suehring
committed
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
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();

Karsten Suehring
committed
if (m_pcEncLib->getTMVPModeId() == 2)
{
if (iGOPid == 0) // first picture in SOP (i.e. forward B)
{

Karsten Suehring
committed
}
else
{
// Note: pcSlice->getColFromL0Flag() is assumed to be always 0 and getcolRefIdx() is always 0.

Karsten Suehring
committed
}
}
else if (m_pcEncLib->getTMVPModeId() == 1)

Karsten Suehring
committed
{

Karsten Suehring
committed
}
else
{

Karsten Suehring
committed
}
// disable TMVP when current picture is the only ref picture
if (pcSlice->isIRAP() && pcSlice->getSPS()->getIBCFlag())
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 JVET_Q0487_SCALING_WINDOW_ISSUES
if( pcSlice->getRefPic( REF_PIC_LIST_0, refIdx )->isRefScaled( pcSlice->getPPS() ) == false )
#else
int refPicWidth = pcSlice->getRefPic( REF_PIC_LIST_0, refIdx )->unscaledPic->cs->pps->getPicWidthInLumaSamples();
int refPicHeight = pcSlice->getRefPic( REF_PIC_LIST_0, refIdx )->unscaledPic->cs->pps->getPicHeightInLumaSamples();
int curPicWidth = pcSlice->getPPS()->getPicWidthInLumaSamples();
int curPicHeight = pcSlice->getPPS()->getPicHeightInLumaSamples();
if( refPicWidth == curPicWidth && refPicHeight == curPicHeight )
{
colRefIdxL0 = refIdx;
break;
}
}
if( pcSlice->getSliceType() == B_SLICE )
{
for( int refIdx = 0; refIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); refIdx++ )
{
#if JVET_Q0487_SCALING_WINDOW_ISSUES
if( pcSlice->getRefPic( REF_PIC_LIST_1, refIdx )->isRefScaled( pcSlice->getPPS() ) == false )
#else
int refPicWidth = pcSlice->getRefPic( REF_PIC_LIST_1, refIdx )->unscaledPic->cs->pps->getPicWidthInLumaSamples();
int refPicHeight = pcSlice->getRefPic( REF_PIC_LIST_1, refIdx )->unscaledPic->cs->pps->getPicHeightInLumaSamples();
int curPicWidth = pcSlice->getPPS()->getPicWidthInLumaSamples();
int curPicHeight = pcSlice->getPPS()->getPicHeightInLumaSamples();
if( refPicWidth == curPicWidth && refPicHeight == curPicHeight )
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
{
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();
#if JVET_Q0482_REMOVE_CONSTANT_PARAMS
picHeader->setPicColFromL0Flag( uiColFromL0 );
#endif
pcSlice->setColFromL0Flag( uiColFromL0 );
pcSlice->setColRefIdx( uiColFromL0 ? colRefIdxL0 : colRefIdxL1 );
Jonatan Samuelsson-Allendes
committed
#if JVET_Q0259_COLLOCATED_PIC_IN_PH
picHeader->setColRefIdx( uiColFromL0 ? colRefIdxL0 : colRefIdxL1 );
#endif
}
else if( colRefIdxL0 < 0 && colRefIdxL1 >= 0 )
{
#if JVET_Q0482_REMOVE_CONSTANT_PARAMS
picHeader->setPicColFromL0Flag( false );
#endif
pcSlice->setColFromL0Flag( false );
pcSlice->setColRefIdx( colRefIdxL1 );
Jonatan Samuelsson-Allendes
committed
#if JVET_Q0259_COLLOCATED_PIC_IN_PH
picHeader->setColRefIdx( colRefIdxL1 );
#endif
}
else if( colRefIdxL0 >= 0 && colRefIdxL1 < 0 )
{
#if JVET_Q0482_REMOVE_CONSTANT_PARAMS
picHeader->setPicColFromL0Flag( true );
#endif
pcSlice->setColFromL0Flag( true );
pcSlice->setColRefIdx( colRefIdxL0 );
Jonatan Samuelsson-Allendes
committed
#if JVET_Q0259_COLLOCATED_PIC_IN_PH
picHeader->setColRefIdx( colRefIdxL0 );
#endif
}
else
{
}
}
pcSlice->scaleRefPicList( scaledRefPic, pcPic->cs->picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false );

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

Karsten Suehring
committed
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
{
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 );
}

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();
#if JVET_Q0151_Q0205_ENTRYPOINTS
const int numSubstreamRows = pcSlice->getSPS()->getEntropyCodingSyncEnabledFlag() ? pcPic->cs->pcv->heightInCtus : (pcSlice->getPPS()->getNumTileRows());
#else
const int numSubstreamRows = pcSlice->getPPS()->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 (pcSlice->getSPS()->getSAOEnabledFlag())

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 );
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
{
// 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());

Karsten Suehring
committed
m_pcSliceEncoder->setUpLambda(pcSlice, pcSlice->getLambdas()[0], pcSlice->getSliceQp());

Karsten Suehring
committed
if( pcSlice->getSPS()->getScalingListFlag() && m_pcCfg->getUseScalingListId() == SCALING_LIST_FILE_READ )
{
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())
{
// cannot set pic_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 ) ) );
for(uint32_t sliceIdx = 0; sliceIdx < pcPic->cs->pps->getNumSlicesInPic(); sliceIdx++ )
{
pcSlice->setSliceMap( pcPic->cs->pps->getSliceMap( sliceIdx ) );
#if JVET_Q0044_SLICE_IDX_WITH_SUBPICS
if( pcPic->cs->pps->getRectSliceFlag() )
{
Position firstCtu;
firstCtu.x = pcSlice->getFirstCtuRsAddrInSlice() % pcPic->cs->pps->getPicWidthInCtu();
firstCtu.y = pcSlice->getFirstCtuRsAddrInSlice() / pcPic->cs->pps->getPicWidthInCtu();
int subPicIdx = 0;
for(int sp = 0; sp < pcPic->cs->pps->getNumSubPics(); sp++)
{
if(pcPic->cs->pps->getSubPic(sp).containsCtu(firstCtu))
{
subPicIdx = sp;
}
}
pcSlice->setSliceSubPicId( pcPic->cs->pps->getSubPic(subPicIdx).getSubPicID() );
}
#endif

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();
CodingStructure& cs = *pcPic->cs;
pcSlice = pcPic->slices[0];
if (pcSlice->getSPS()->getUseLmcs() && m_pcReshaper->getSliceReshaperInfo().getUseSliceReshaper())
int apsId = std::min<int>( 3, m_pcEncLib->getVPS() == nullptr ? 0 : m_pcEncLib->getVPS()->getGeneralLayerIdx( m_pcEncLib->getLayerId() ) );
CHECK((m_pcReshaper->getRecReshaped() == false), "Rec picture is not reshaped!");
pcPic->getRecoBuf(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;
#if JVET_Q0441_SAO_MOD_12_BIT
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);
#else
const uint32_t log2SaoOffsetScaleLuma = pcPic->cs->slice->getPPS()->getPpsRangeExtension().getLog2SaoOffsetScale( CHANNEL_TYPE_LUMA );
const uint32_t log2SaoOffsetScaleChroma = pcPic->cs->slice->getPPS()->getPpsRangeExtension().getLog2SaoOffsetScale( CHANNEL_TYPE_CHROMA );
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->setScalingListPresentFlag(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
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
{
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
}
m_pcLoopFilter->loopFilterPic( cs );
CS::setRefinedMotionField(cs);

Karsten Suehring
committed
DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "final", 1 ) ) );

Karsten Suehring
committed
if( pcSlice->getSPS()->getSAOEnabledFlag() )

Karsten Suehring
committed
{
bool sliceEnabled[MAX_NUM_COMPONENT];
m_pcSAO->initCABACEstimator( m_pcEncLib->getCABACEncoder(), m_pcEncLib->getCtxCache(), pcSlice );

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
for(int s=0; s< uiNumSliceSegments; s++)
{
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( 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
);

Christian Helmrich
committed
//assign ALF slice header
for (int s = 0; s < uiNumSliceSegments; s++)
{
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))
{
pcPic->slices[s]->setTileGroupNumAps(cs.slice->getTileGroupNumAps());
pcPic->slices[s]->setAlfAPSs(cs.slice->getTileGroupApsIdLuma());
}
else
{
pcPic->slices[s]->setTileGroupNumAps(0);
}
pcPic->slices[s]->setAlfAPSs(cs.slice->getAlfAPSs());
pcPic->slices[s]->setTileGroupApsIdChroma(cs.slice->getTileGroupApsIdChroma());
#if JVET_Q0795_CCALF
pcPic->slices[s]->setTileGroupCcAlfCbApsId(cs.slice->getTileGroupCcAlfCbApsId());
pcPic->slices[s]->setTileGroupCcAlfCrApsId(cs.slice->getTileGroupCcAlfCrApsId());
#endif

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

Karsten Suehring
committed
}
else // skip enc picture
{
pcSlice->setSliceQpBase( pcSlice->getSliceQp() );

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
{
m_pcSAO->disabledRate( *pcPic->cs, pcPic->getSAO(1), m_pcCfg->getSaoEncodingRate(), m_pcCfg->getSaoEncodingRateChroma());
}
}
pcSlice->freeScaledRefPicList( scaledRefPic );