Newer
Older
bool isField, bool isTff, const InputColourSpaceConversion snr_conversion, const bool printFrameMSE
, bool isEncodeLtRef

Karsten Suehring
committed
{
// TODO: Split this function up.
Picture* pcPic = NULL;

Karsten Suehring
committed
Slice* pcSlice;
OutputBitstream *pcBitstreamRedirect;
pcBitstreamRedirect = new OutputBitstream;
AccessUnit::iterator itLocationToPushSliceHeaderNALU; // used to store location where NALU containing slice header is to be inserted

Karsten Suehring
committed
xInitGOP( iPOCLast, iNumPicRcvd, isField, isEncodeLtRef );

Karsten Suehring
committed
m_iNumPicCoded = 0;
SEIMessages leadingSeiMessages;
SEIMessages nestedSeiMessages;
SEIMessages duInfoSeiMessages;
SEIMessages trailingSeiMessages;
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;

Haiwei Sun
committed
iTimeOffset = isField ? (1 - multipleFactor) : 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;

Haiwei Sun
committed
iTimeOffset = multipleFactor + 1;

Karsten Suehring
committed
}
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() );
picHeader->setMinQTSizes(pcPic->cs->sps->getMinQTSizes());
picHeader->setMaxMTTHierarchyDepths(pcPic->cs->sps->getMaxMTTHierarchyDepths());
picHeader->setMaxBTSizes(pcPic->cs->sps->getMaxBTSizes());
picHeader->setMaxTTSizes(pcPic->cs->sps->getMaxTTSizes());
// 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, m_pcEncLib->getLayerId() );

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[pcPic->layerId] = pcSlice->getNalUnitType();
m_associatedIRAPPOC[pcPic->layerId] = pocCurr;

Karsten Suehring
committed
}
pcSlice->setAssociatedIRAPType(m_associatedIRAPType[pcPic->layerId]);
pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC[pcPic->layerId]);

Karsten Suehring
committed
}
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[pcPic->layerId] = pcSlice->getNalUnitType();
m_associatedIRAPPOC[pcPic->layerId] = pocCurr;

Karsten Suehring
committed
}
pcSlice->setAssociatedIRAPType(m_associatedIRAPType[pcPic->layerId]);
pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC[pcPic->layerId]);

Karsten Suehring
committed
}
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())) )
|| ((m_pcEncLib->getAvoidIntraInDepLayer() || !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++)
{
#if JVET_S0045_SIGN
int tPoc = pcSlice->getPOC() + rpl0->getRefPicIdentifier(jj);
#else
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++)
{
#if JVET_S0045_SIGN
int tPoc = pcSlice->getPOC() + rpl1->getRefPicIdentifier(jj);
#else
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
// store sub-picture numbers, sizes, and locations with a picture
#if JVET_S0258_SUBPIC_CONSTRAINTS
pcSlice->getPic()->subPictures.clear();
for( int subPicIdx = 0; subPicIdx < pcPic->cs->pps->getNumSubPics(); subPicIdx++ )
{
pcSlice->getPic()->subPictures.push_back( pcPic->cs->pps->getSubPic( subPicIdx ) );
}
#else
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)
{
xPicInitHashME( pcPic, pcSlice->getPPS(), rcListPic );

Karsten Suehring
committed
if( m_pcCfg->getUseAMaxBT() )
{
if( !pcSlice->isIntra() )

Karsten Suehring
committed
{
int refLayer = pcSlice->getDepth();
if( refLayer > 9 ) refLayer = 9; // Max layer is 10
#if JVET_X0144_MAX_MTT_DEPTH_TID
if( m_pcCfg->getMaxMTTHierarchyDepthByTid( refLayer ) != m_pcCfg->getMaxMTTHierarchyDepth() )
{
picHeader->setSplitConsOverrideFlag( true );
picHeader->setMaxMTTHierarchyDepth( P_SLICE, m_pcCfg->getMaxMTTHierarchyDepthByTid( refLayer ) );
}
#endif

Karsten Suehring
committed
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 )
#if CTU_256
else if( dBlkSize < AMAXBT_TH128 )
{
newMaxBtSize = 128;
}
else
{
newMaxBtSize = 256;
}
#else
newMaxBtSize = Clip3(picHeader->getMinQTSize(pcSlice->getSliceType()), pcPic->cs->sps->getCTUSize(), newMaxBtSize);
picHeader->setMaxBTSize(1, newMaxBtSize);

Karsten Suehring
committed
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;
}
#if JVET_S0133_PH_SYNTAX_OVERRIDE_ENC_FIX
bool identicalToSPS=true;
const SPS* sps =pcSlice->getSPS();
if (picHeader->getPicInterSliceAllowedFlag())
{
if (picHeader->getMinQTSize(pcSlice->getSliceType()) != pcSlice->getSPS()->getMinQTSize(pcSlice->getSliceType()) ||
picHeader->getMaxMTTHierarchyDepth(pcSlice->getSliceType()) != pcSlice->getSPS()->getMaxMTTHierarchyDepth() ||
picHeader->getMaxBTSize(pcSlice->getSliceType()) != pcSlice->getSPS()->getMaxBTSize() ||
picHeader->getMaxTTSize(pcSlice->getSliceType()) != pcSlice->getSPS()->getMaxTTSize()
)
{
identicalToSPS=false;
}
}
if (identicalToSPS && picHeader->getPicIntraSliceAllowedFlag())
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
{
if (picHeader->getMinQTSize(I_SLICE) != sps->getMinQTSize(I_SLICE) ||
picHeader->getMaxMTTHierarchyDepth(I_SLICE) != sps->getMaxMTTHierarchyDepthI() ||
picHeader->getMaxBTSize(I_SLICE) != sps->getMaxBTSizeI() ||
picHeader->getMaxTTSize(I_SLICE) != sps->getMaxTTSizeI()
)
{
identicalToSPS=false;
}
if (identicalToSPS && sps->getUseDualITree())
{
if (picHeader->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMinQTSize(I_SLICE, CHANNEL_TYPE_CHROMA) ||
picHeader->getMaxMTTHierarchyDepth(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMaxMTTHierarchyDepthIChroma() ||
picHeader->getMaxBTSize(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMaxBTSizeIChroma() ||
picHeader->getMaxTTSize(I_SLICE, CHANNEL_TYPE_CHROMA) != sps->getMaxTTSizeIChroma()
)
{
identicalToSPS=false;
}
}
}
if (identicalToSPS)
{
picHeader->setSplitConsOverrideFlag(false);
}
#endif

Karsten Suehring
committed
}
// 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
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
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);
}
//-------------------------------------------------------------
#if MULTI_HYP_PRED
pcSlice->setNumMultiHypRefPics(pcSlice->getSPS()->getMaxNumAddHypRefFrames());
#endif

Karsten Suehring
committed
pcSlice->setRefPOCList();
#if MULTI_HYP_PRED
pcSlice->setNumMultiHypRefPics((int)pcSlice->getMultiHypRefPicList().size());
#endif

Karsten Suehring
committed
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;
const bool isResamplingPossible = pcSlice->getSPS()->getRprEnabledFlag();
for( int refIdx = 0; refIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); refIdx++ )
{
CHECK( pcSlice->getRefPic( REF_PIC_LIST_0, refIdx )->unscaledPic == nullptr, "unscaledPic is not set for L0 reference picture" );
if( !isResamplingPossible || !pcSlice->getRefPic( REF_PIC_LIST_0, refIdx )->isRefScaled( pcSlice->getPPS() ) )
{
colRefIdxL0 = refIdx;
break;
}
}
if( pcSlice->getSliceType() == B_SLICE )
{
for( int refIdx = 0; refIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); refIdx++ )
{
CHECK( pcSlice->getRefPic( REF_PIC_LIST_1, refIdx )->unscaledPic == nullptr, "unscaledPic is not set for L1 reference picture" );
if( !isResamplingPossible || !pcSlice->getRefPic( REF_PIC_LIST_1, refIdx )->isRefScaled( pcSlice->getPPS() ) )
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
{
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;
}
CHECK( !refPicL0->slices.size(), "Wrong L0 reference picture" );
CHECK( !refPicL1->slices.size(), "Wrong L1 reference picture" );
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
{
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
if (picHeader->getEnableTMVPFlag())
{
const Picture* const pColPic = pcSlice->getRefPic(RefPicList(pcSlice->isInterB() ? 1 - pcSlice->getColFromL0Flag() : 0), pcSlice->getColRefIdx());
if (pColPic)
{
const int currPOC = pcSlice->getPOC();
const int colPOC = pColPic->getPOC();
pcSlice->resizeImBuf(pColPic->numSlices);
Slice *pColSlice = nullptr;
for (int sliceIdx = 0; sliceIdx < pColPic->numSlices; sliceIdx++)
{
pColSlice = pColPic->slices[sliceIdx];
if (pColSlice->isIntra())
{
continue;
}
for (int colRefPicListIdx = 0; colRefPicListIdx < (pColSlice->isInterB() ? 2 : 1); colRefPicListIdx++)
{
for (int colRefIdx = 0; colRefIdx < pColSlice->getNumRefIdx(RefPicList(colRefPicListIdx)); colRefIdx++)
{
const bool bIsColRefLongTerm = pColSlice->getIsUsedAsLongTerm(RefPicList(colRefPicListIdx), colRefIdx);
const int colRefPOC = pColSlice->getRefPOC(RefPicList(colRefPicListIdx), colRefIdx);
for (int curRefPicListIdx = 0; curRefPicListIdx < (pcSlice->isInterB() ? 2 : 1); curRefPicListIdx++)
{
double bestDistScale = 1000;
int targetRefIdx = -1;
for (int curRefIdx = 0; curRefIdx < pcSlice->getNumRefIdx(RefPicList(curRefPicListIdx)); curRefIdx++)
{
const int currRefPOC = pcSlice->getRefPic(RefPicList(curRefPicListIdx), curRefIdx)->getPOC();
const bool bIsCurrRefLongTerm = pcSlice->getRefPic(RefPicList(curRefPicListIdx), curRefIdx)->longTerm;
if (bIsCurrRefLongTerm != bIsColRefLongTerm)
{
continue;
}
if (bIsCurrRefLongTerm)
{
targetRefIdx = curRefIdx;
bestDistScale = 1;
break;
}
else if (colPOC - colRefPOC == currPOC - currRefPOC)
{
targetRefIdx = curRefIdx;
bestDistScale = 1;
break;
}
else
{
//printf("colRefPicListIdx:%d, curRefPicListIdx:%d, colRefIdx:%d, targetRefIdx:%d, curRefIdx:%d\n", colRefPicListIdx, curRefPicListIdx, colRefIdx, targetRefIdx, curRefIdx);
//printf("currPOC:%d, currRefPOC:%d, colPOC:%d, colRefPOC:%d\n", currPOC, currRefPOC, colPOC, colRefPOC);
//printf("bestDistScale:%.2f %.2f\n", bestDistScale, abs(1.0 - (abs(currPOC - currRefPOC) * 1.0 / abs(colPOC - colRefPOC) * 1.0)));
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);
pcSlice->setImRefIdx(sliceIdx, RefPicList(colRefPicListIdx), RefPicList(curRefPicListIdx), colRefIdx, targetRefIdx);
} // curRefPicListIdx
}
}
}
}
}
#endif
}
#if JVET_Y0128_NON_CTC
bool bDisableTMVP = pcSlice->scaleRefPicList( scaledRefPic, pcPic->cs->picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false );
if ( picHeader->getEnableTMVPFlag() && bDisableTMVP )
{
picHeader->setEnableTMVPFlag( 0 );
}
#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
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
{
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

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