Newer
Older

Karsten Suehring
committed
iNumPicRcvd, iTimeOffset, pcPic, pocCurr, isField );
picHeader->setSPSId( pcPic->cs->pps->getSPSId() );
picHeader->setPPSId( pcPic->cs->pps->getPPSId() );
// initial two flags to be false
picHeader->setPicInterSliceAllowedFlag(false);
picHeader->setPicIntraSliceAllowedFlag(false);
#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();
const int maxTotalCUDepth = floorLog2(maxCUWidth) - pcPic->cs->sps->getLog2MinCodingBlockSize();
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);
}
pcSlice->setTLayer(m_pcCfg->getGOPEntry(iGOPid).m_temporalId);
// Set the nal unit type
pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField));
// set two flags according to slice type presented in the picture
if (pcSlice->getSliceType() != I_SLICE)
picHeader->setPicInterSliceAllowedFlag(true);
if (pcSlice->getSliceType() == I_SLICE)
picHeader->setPicIntraSliceAllowedFlag(true);
picHeader->setGdrOrIrapPicFlag(picHeader->getGdrPicFlag() || pcSlice->isIRAP());

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->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() );
Jonatan Samuelsson-Allendes
committed
pcSlice->applyReferencePictureListBasedMarking( rcListPic, pcSlice->getRPL0(), pcSlice->getRPL1(), pcSlice->getPic()->layerId, *(pcSlice->getPPS()));

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;
for(int ii=0;(ii<m_pcCfg->getGOPSize() && isSTSA==true);ii++)

Karsten Suehring
committed
{
int lTid = m_pcCfg->getRPLEntry(0, ii).m_temporalId;
if (lTid == pcSlice->getTLayer())
{
const ReferencePictureList* rpl0 = pcSlice->getSPS()->getRPLList0()->getReferencePictureList(ii);
for (int jj = 0; jj < pcSlice->getRPL0()->getNumberOfActivePictures(); jj++)
{
int tPoc = pcSlice->getPOC() - rpl0->getRefPicIdentifier(jj);
int kk = 0;
for (kk = 0; kk<m_pcCfg->getGOPSize(); kk++)
{
if (m_pcCfg->getRPLEntry(0, kk).m_POC == tPoc)
{
break;
}
}
int tTid = m_pcCfg->getRPLEntry(0, kk).m_temporalId;
if (tTid >= pcSlice->getTLayer())
{
isSTSA = false;
break;
}
}
const ReferencePictureList* rpl1 = pcSlice->getSPS()->getRPLList1()->getReferencePictureList(ii);
for (int jj = 0; jj < pcSlice->getRPL1()->getNumberOfActivePictures(); jj++)
{
int tPoc = pcSlice->getPOC() - rpl1->getRefPicIdentifier(jj);
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
#if JVET_R0058
// store sub-picture numbers, sizes, and locations with a picture
if (pcPic->cs->sps->getSubPicInfoPresentFlag() && pcPic->cs->pps->getNumSubPics() > 1)
{
pcSlice->getPic()->numSubpics = pcPic->cs->pps->getNumSubPics();
pcSlice->getPic()->subpicWidthInCTUs.clear();
pcSlice->getPic()->subpicHeightInCTUs.clear();
pcSlice->getPic()->subpicCtuTopLeftX.clear();
pcSlice->getPic()->subpicCtuTopLeftY.clear();
for (int subPicIdx = 0; subPicIdx < pcPic->cs->pps->getNumSubPics(); subPicIdx++)
{
pcSlice->getPic()->subpicWidthInCTUs.push_back(pcPic->cs->pps->getSubPic(subPicIdx).getSubPicWidthInCTUs());
pcSlice->getPic()->subpicHeightInCTUs.push_back(pcPic->cs->pps->getSubPic(subPicIdx).getSubPicHeightInCTUs());
pcSlice->getPic()->subpicCtuTopLeftX.push_back(pcPic->cs->pps->getSubPic(subPicIdx).getSubPicCtuTopLeftX());
pcSlice->getPic()->subpicCtuTopLeftY.push_back(pcPic->cs->pps->getSubPic(subPicIdx).getSubPicCtuTopLeftY());
}
}
const VPS* vps = pcPic->cs->vps;
int layerIdx = vps == nullptr ? 0 : vps->getGeneralLayerIdx(pcPic->layerId);
if (vps && !vps->getIndependentLayerFlag(layerIdx) && pcPic->cs->pps->getNumSubPics() > 1)
{
}
#endif
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 )
{
picHeader->setSplitConsOverrideFlag(true);
double dBlkSize = sqrt( ( double ) m_uiBlkSize[refLayer] / m_uiNumBlk[refLayer] );
unsigned int newMaxBtSize = picHeader->getMaxBTSize(pcSlice->getSliceType(), CHANNEL_TYPE_LUMA);
if( dBlkSize < AMAXBT_TH32 )
else if( dBlkSize < AMAXBT_TH64 )
newMaxBtSize = Clip3(picHeader->getMinQTSize(pcSlice->getSliceType()), pcPic->cs->sps->getCTUSize(), newMaxBtSize);
picHeader->setMaxBTSize(1, newMaxBtSize);

Karsten Suehring
committed
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
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 );
}

Karsten Suehring
committed
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
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
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( pcSlice->getRefPic( REF_PIC_LIST_0, refIdx )->isRefScaled( pcSlice->getPPS() ) == false )
{
colRefIdxL0 = refIdx;
break;
}
}
if( pcSlice->getSliceType() == B_SLICE )
{
for( int refIdx = 0; refIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); refIdx++ )
{
if( pcSlice->getRefPic( REF_PIC_LIST_1, refIdx )->isRefScaled( pcSlice->getPPS() ) == false )
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
{
colRefIdxL1 = refIdx;
break;
}
}
}
if( colRefIdxL0 >= 0 && colRefIdxL1 >= 0 )
{
const Picture *refPicL0 = pcSlice->getRefPic( REF_PIC_LIST_0, colRefIdxL0 );
if( !refPicL0->slices.size() )
{
refPicL0 = refPicL0->unscaledPic;
}
const Picture *refPicL1 = pcSlice->getRefPic( REF_PIC_LIST_1, colRefIdxL1 );
if( !refPicL1->slices.size() )
{
refPicL1 = refPicL1->unscaledPic;
}
const uint32_t uiColFromL0 = refPicL0->slices[0]->getSliceQp() > refPicL1->slices[0]->getSliceQp();
picHeader->setPicColFromL0Flag( uiColFromL0 );
pcSlice->setColFromL0Flag( uiColFromL0 );
pcSlice->setColRefIdx( uiColFromL0 ? colRefIdxL0 : colRefIdxL1 );
Jonatan Samuelsson-Allendes
committed
picHeader->setColRefIdx( uiColFromL0 ? colRefIdxL0 : colRefIdxL1 );
}
else if( colRefIdxL0 < 0 && colRefIdxL1 >= 0 )
{
picHeader->setPicColFromL0Flag( false );
pcSlice->setColFromL0Flag( false );
pcSlice->setColRefIdx( colRefIdxL1 );
Jonatan Samuelsson-Allendes
committed
picHeader->setColRefIdx( colRefIdxL1 );
}
else if( colRefIdxL0 >= 0 && colRefIdxL1 < 0 )
{
picHeader->setPicColFromL0Flag( true );
pcSlice->setColFromL0Flag( true );
pcSlice->setColRefIdx( colRefIdxL0 );
Jonatan Samuelsson-Allendes
committed
picHeader->setColRefIdx( colRefIdxL0 );
}
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
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
{
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();
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 (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 )
{
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 ) ) );
#if JVET_R0110_MIXED_LOSSLESS
const std::vector<uint16_t> sliceLosslessArray = *(m_pcCfg->getSliceLosslessArray());
bool mixedLossyLossless = m_pcCfg->getMixedLossyLossless();
if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
{
pcPic->fillSliceLossyLosslessArray(sliceLosslessArray, mixedLossyLossless);
}
for(uint32_t sliceIdx = 0; sliceIdx < pcPic->cs->pps->getNumSlicesInPic(); sliceIdx++ )
{
pcSlice->setSliceMap( pcPic->cs->pps->getSliceMap( sliceIdx ) );
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 (pcSlice->getLmcsEnabledFlag())
{
pcPic->getOrigBuf(COMPONENT_Y).rspSignal(m_pcReshaper->getFwdLUT());
m_pcReshaper->setSrcReshaped(true);
m_pcReshaper->setRecReshaped(true);
}
else
{
pcPic->getOrigBuf().copyFrom(pcPic->getTrueOrigBuf());
m_pcReshaper->setSrcReshaped(false);
m_pcReshaper->setRecReshaped(false);
}
}
}
#if JVET_R0110_MIXED_LOSSLESS
bool isLossless = false;
if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
{
isLossless = pcPic->losslessSlice(sliceIdx);
}
m_pcSliceEncoder->setLosslessSlice(pcPic, isLossless);
#endif
#if JVET_R0058
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);
}
#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];
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
if (cs.sps->getUseLmcs() && m_pcReshaper->getSliceReshaperInfo().getUseSliceReshaper())
{
picHeader->setLmcsEnabledFlag(true);
int apsId = std::min<int>(3, m_pcEncLib->getVPS() == nullptr ? 0 : m_pcEncLib->getVPS()->getGeneralLayerIdx(m_pcEncLib->getLayerId()));
picHeader->setLmcsAPSId(apsId);
const PreCalcValues& pcv = *cs.pcv;
for (uint32_t yPos = 0; yPos < pcv.lumaHeight; yPos += pcv.maxCUHeight)
{
for (uint32_t xPos = 0; xPos < pcv.lumaWidth; xPos += pcv.maxCUWidth)
{
const CodingUnit* cu = cs.getCU(Position(xPos, yPos), CHANNEL_TYPE_LUMA);
if (cu->slice->getLmcsEnabledFlag())
{
const uint32_t width = (xPos + pcv.maxCUWidth > pcv.lumaWidth) ? (pcv.lumaWidth - xPos) : pcv.maxCUWidth;
const uint32_t height = (yPos + pcv.maxCUHeight > pcv.lumaHeight) ? (pcv.lumaHeight - yPos) : pcv.maxCUHeight;
const UnitArea area(cs.area.chromaFormat, Area(xPos, yPos, width, height));
cs.getRecoBuf(area).get(COMPONENT_Y).rspSignal(m_pcReshaper->getInvLUT());
}
}
}
m_pcReshaper->setRecReshaped(false);
pcPic->getOrigBuf().copyFrom(pcPic->getTrueOrigBuf());
}
// create SAO object based on the picture size
if( pcSlice->getSPS()->getSAOEnabledFlag() )
{
const uint32_t widthInCtus = ( picWidth + maxCUWidth - 1 ) / maxCUWidth;
const uint32_t heightInCtus = ( picHeight + maxCUHeight - 1 ) / maxCUHeight;
const uint32_t numCtuInFrame = widthInCtus * heightInCtus;
const uint32_t log2SaoOffsetScaleLuma = (uint32_t) std::max(0, pcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA ) - MAX_SAO_TRUNCATED_BITDEPTH);
const uint32_t log2SaoOffsetScaleChroma = (uint32_t) std::max(0, pcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_CHROMA) - MAX_SAO_TRUNCATED_BITDEPTH);
m_pcSAO->create( picWidth, picHeight, chromaFormatIDC, maxCUWidth, maxCUHeight, maxTotalCUDepth, log2SaoOffsetScaleLuma, log2SaoOffsetScaleChroma );
m_pcSAO->destroyEncData();
m_pcSAO->createEncData( m_pcCfg->getSaoCtuBoundary(), numCtuInFrame );
m_pcSAO->setReshaper( m_pcReshaper );
}
if( pcSlice->getSPS()->getScalingListFlag() && m_pcCfg->getUseScalingListId() == SCALING_LIST_FILE_READ )
{
picHeader->setExplicitScalingListEnabledFlag(true);
pcSlice->setExplicitScalingListUsed(true);
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
{
m_pcSAO->getPreDBFStatistics( cs );
}
//-- Loop filter
if ( m_pcCfg->getDeblockingFilterMetric() )
{
#if W0038_DB_OPT
if ( m_pcCfg->getDeblockingFilterMetric()==2 )
{
applyDeblockingFilterParameterSelection(pcPic, uiNumSliceSegments, iGOPid);
}
else
{
#endif
applyDeblockingFilterMetric(pcPic, uiNumSliceSegments);
#if W0038_DB_OPT
}
#endif
}
#if JVET_R0110_MIXED_LOSSLESS
if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
{
for (int s = 0; s < uiNumSliceSegments; s++)
{
if (pcPic->slices[s]->isLossless())
{
pcPic->slices[s]->setDeblockingFilterDisable(true);
}
}
}
#endif

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

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++)

Karsten Suehring
committed
{
#if JVET_R0110_MIXED_LOSSLESS
if (pcPic->slices[s]->isLossless() && m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
{
pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, false);
pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, false);
}
else
{
#endif
pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, sliceEnabled[COMPONENT_Y]);
CHECK(!(sliceEnabled[COMPONENT_Cb] == sliceEnabled[COMPONENT_Cr]), "Unspecified error");
pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, sliceEnabled[COMPONENT_Cb]);
#if JVET_R0110_MIXED_LOSSLESS
}
#endif

Karsten Suehring
committed
}
}
if( pcSlice->getSPS()->getALFEnabledFlag() )
m_pcALF->destroy();
m_pcALF->create( m_pcCfg, picWidth, picHeight, chromaFormatIDC, maxCUWidth, maxCUHeight, maxTotalCUDepth, m_pcCfg->getBitDepth(), m_pcCfg->getInputBitDepth() );
for (int s = 0; s < uiNumSliceSegments; s++)
{
pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Y, false);
}
m_pcALF->initCABACEstimator(m_pcEncLib->getCABACEncoder(), m_pcEncLib->getCtxCache(), pcSlice, m_pcEncLib->getApsMap());
m_pcALF->ALFProcess(cs, pcSlice->getLambdas()
#if ENABLE_QPA
, (m_pcCfg->getUsePerceptQPA() && !m_pcCfg->getUseRateCtrl() && pcSlice->getPPS()->getUseDQP() ? m_pcEncLib->getRdCost(PARL_PARAM0(0))->getChromaWeight() : 0.0)
#endif
#if JVET_R0110_MIXED_LOSSLESS
, pcPic, uiNumSliceSegments
#endif
);

Christian Helmrich
committed
//assign ALF slice header
for (int s = 0; s < uiNumSliceSegments; s++)
{
#if JVET_R0110_MIXED_LOSSLESS
//For the first slice, even if it is lossless, slice level ALF is not disabled and ALF-APS is signaled so that the later lossy slices can use APS of the first slice.
//However, if the first slice is lossless, the ALF process is disabled for all of the CTUs ( m_ctuEnableFlag == 0) of that slice which is implemented in the function void EncAdaptiveLoopFilter::ALFProcess.
if (pcPic->slices[s]->isLossless() && s && m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
{
pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Y, false);
pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cb, false);
pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cr, false);
}
else
{
#endif
pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Y, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Y));
pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cb, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cb));
pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cr, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cr));
#if JVET_R0110_MIXED_LOSSLESS
}
#endif
if (pcPic->slices[s]->getTileGroupAlfEnabledFlag(COMPONENT_Y))
{
pcPic->slices[s]->setTileGroupNumAps(cs.slice->getTileGroupNumAps());
pcPic->slices[s]->setAlfAPSs(cs.slice->getTileGroupApsIdLuma());
}
else
{
pcPic->slices[s]->setTileGroupNumAps(0);
}
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());

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

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