Newer
Older

Karsten Suehring
committed
else
{
m_pcReshaper->setCTUFlag(false);
}
}
class BIFCabacEstImp : public BIFCabacEst
{
CABACWriter* CABACEstimator;
public:
BIFCabacEstImp(CABACWriter* _CABACEstimator) : CABACEstimator(_CABACEstimator) {};
virtual ~BIFCabacEstImp() {};
Franck Galpin
committed
#if JVET_AG0196_CABAC_RETRAIN
virtual uint64_t getBits( const ComponentID compID, Slice& slice, const BifParams& htdfParams )
#else
virtual uint64_t getBits(const ComponentID compID, const Slice& slice, const BifParams& htdfParams)
Franck Galpin
committed
#endif
{
CABACEstimator->initCtxModels(slice);
CABACEstimator->resetBits();
CABACEstimator->bif( compID, slice, htdfParams);
return CABACEstimator->getEstFracBits();
}
};
#endif

Karsten Suehring
committed
// ====================================================================================================================
// Public member functions
// ====================================================================================================================
void EncGOP::compressGOP(int iPOCLast, int iNumPicRcvd, PicList &rcListPic, std::list<PelUnitBuf *> &rcListPicYuvRecOut,
bool isField, bool isTff, const InputColourSpaceConversion snr_conversion,
const bool printFrameMSE,
#if MSSIM_UNIFORM_METRICS_LOG
const bool printMSSSIM,
#endif
bool isEncodeLtRef, const int picIdInGOP)

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
Tangi Poirier
committed
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
#if JVET_Y0240_BIM
const bool isCurrentFrameFiltered = m_pcCfg->getGopBasedTemporalFilterEnabled() || m_pcCfg->getBIM();
#else
const bool isCurrentFrameFiltered = m_pcCfg->getGopBasedTemporalFilterEnabled();
#endif
const SPS& sps = *pcPic->cs->sps;
pcPic->createTempBuffers(pcPic->cs->pps->pcv->maxCUWidth, isCurrentFrameFiltered, m_pcEncLib->isResChangeInClvsEnabled(), false);
pcPic->getTrueOrigBuf().copyFrom(pcPic->getOrigBuf());
if (m_pcEncLib->isResChangeInClvsEnabled())
{
pcPic->M_BUFS(0, PIC_TRUE_ORIGINAL_INPUT).copyFrom(pcPic->M_BUFS(0, PIC_ORIGINAL_INPUT));
}
if(isCurrentFrameFiltered)
{
if (m_pcEncLib->isResChangeInClvsEnabled())
{
m_pcEncLib->getTemporalFilter().filter(pcPic->M_BUFS(0, PIC_ORIGINAL_INPUT), pocCurr);
const Window& curScalingWindow = pcPic->getScalingWindow();
const int curPicWidth = pcPic->M_BUFS(0, PIC_ORIGINAL).Y().width - SPS::getWinUnitX(sps.getChromaFormatIdc()) * (curScalingWindow.getWindowLeftOffset() + curScalingWindow.getWindowRightOffset());
const int curPicHeight = pcPic->M_BUFS(0, PIC_ORIGINAL).Y().height - SPS::getWinUnitY(sps.getChromaFormatIdc()) * (curScalingWindow.getWindowTopOffset() + curScalingWindow.getWindowBottomOffset());
const PPS* pps = m_pcEncLib->getPPS(0);
const Window& refScalingWindow = pps->getScalingWindow();
const int refPicWidth = pcPic->M_BUFS(0, PIC_ORIGINAL_INPUT).Y().width - SPS::getWinUnitX(sps.getChromaFormatIdc()) * (refScalingWindow.getWindowLeftOffset() + refScalingWindow.getWindowRightOffset());
const int refPicHeight = pcPic->M_BUFS(0, PIC_ORIGINAL_INPUT).Y().height - SPS::getWinUnitY(sps.getChromaFormatIdc()) * (refScalingWindow.getWindowTopOffset() + refScalingWindow.getWindowBottomOffset());
const int xScale = ((refPicWidth << SCALE_RATIO_BITS) + (curPicWidth >> 1)) / curPicWidth;
const int yScale = ((refPicHeight << SCALE_RATIO_BITS) + (curPicHeight >> 1)) / curPicHeight;
std::pair<int, int> scalingRatio = std::pair<int, int>(xScale, yScale);
Picture::rescalePicture(scalingRatio, pcPic->M_BUFS(0, PIC_ORIGINAL_INPUT), curScalingWindow, pcPic->M_BUFS(0, PIC_ORIGINAL), pps->getScalingWindow(), chromaFormatIDC, sps.getBitDepths(), true, true,
sps.getHorCollocatedChromaFlag(), sps.getVerCollocatedChromaFlag());
}
else
{
m_pcEncLib->getTemporalFilter().filter(pcPic->M_BUFS(0, PIC_ORIGINAL), pocCurr);
}
pcPic->getFilteredOrigBuf().copyFrom(pcPic->getOrigBuf());
}
Fabrice URBAN
committed
pcPic->cs->createTemporaryCsData((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 JVET_AG0145_ADAPTIVE_CLIPPING
getRealRange(pcPic);
#endif

Karsten Suehring
committed
#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);
if (m_pcCfg->getGdrEnabled() && pocCurr >= m_pcCfg->getGdrPocStart())
else if (m_pcCfg->getGdrEnabled() && (pocCurr != 0) && (pocCurr < m_pcCfg->getGdrPocStart()))
{
pcSlice->setSliceType(B_SLICE);
}
// note : first picture is GDR(I_SLICE)
if (m_pcCfg->getGdrEnabled() && pocCurr == 0)
{
pcSlice->setSliceType(I_SLICE);
}
#endif
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if ( pcSlice->isIntra() )
{
pcSlice->setSeparateTreeEnabled( pcSlice->getSPS()->getUseDualITree() );
}
else
{
//CHECK( !rpcSlice->getSPS()->getSpsNext().getInterSliceSeparateTreeEnabled(), "Error separate trees not enabled\n" )
pcSlice->setSeparateTreeEnabled( pcSlice->getSPS()->getInterSliceSeparateTreeEnabled() );
}
pcSlice->setProcessingIntraRegion( false );
#endif
// 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 );
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if ( !pcSlice->isIntra() )
{
if ( (picWidth * picHeight) <= (1280*720) && ( pcSlice->getTLayer()>0 ) )
{
pcSlice->setSeparateTreeEnabled(false);
}
else if ( pcSlice->getTLayer()>=ID_SEP_TREE_TID_OFF )
{
pcSlice->setSeparateTreeEnabled(false);
}
}
#endif

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())
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
{
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
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);
Na Zhang
committed
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
#if JVET_AF0128_LIC_MERGE_TM
bool bLowDelayB = false;
if (pcSlice->isInterB() && bLowDelay)
{
int min = MAX_INT;
for (int k = 0; k < NUM_REF_PIC_LIST_01; k++)
{
for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx((RefPicList)k); iRefIdx++)
{
if (pcSlice->getPOC() - pcSlice->getRefPic((RefPicList)k, iRefIdx)->getPOC() < min)
{
min = pcSlice->getPOC() - pcSlice->getRefPic((RefPicList)k, iRefIdx)->getPOC();
}
}
}
if (min == 1)
{
bLowDelayB = true;
}
}
pcSlice->setCheckLDB(bLowDelayB);
#endif

Karsten Suehring
committed
}
else
{
pcSlice->setCheckLDC(true);
}
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
2745
2746
2747
2748
2749
#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC
if (!pcSlice->isIntra() && pcSlice->getSPS()->getUseAML())
{
int index = pcSlice->getSPS()->getQPOffsetsIdx(pcSlice->getSliceQp() - (pcSlice->getPPS()->getPicInitQPMinus26() + 26));
if (index != -1)
{
const SPS* sps = pcSlice->getSPS();
pcSlice->setCostForARMC(sps->getLambdaVal(index));
}
else
{
pcSlice->setCostForARMC((uint32_t) LAMBDA_DEC_SIDE[min(max(pcSlice->getSliceQp(), 0), MAX_QP)]);
}
if (pcSlice->getCheckLDC())
{
int iCurrPOC = pcSlice->getPOC();
int iRefIdx = 0;
int mindist = MAX_INT;
for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0); iRefIdx++)
{
if (abs(pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() - iCurrPOC) < mindist)
{
mindist = abs(pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() - iCurrPOC);
}
}
if (pcSlice->isInterB())
{
for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1); iRefIdx++)
{
if (abs(pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() - iCurrPOC) < mindist)
{
mindist = abs(pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() - iCurrPOC);
}
}
}
if (mindist != 1 )
{
pcSlice->setCostForARMC((uint32_t) LAMBDA_DEC_SIDE[min(max(pcSlice->getSliceQp() - 4, 0), MAX_QP)]);
}
}
else
{
pcSlice->setCostForARMC((uint32_t) LAMBDA_DEC_SIDE[min(max(pcSlice->getSliceQp() - 4, 0), MAX_QP)]);
}
}
#endif

Karsten Suehring
committed
//-------------------------------------------------------------
#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 JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if (pcSlice->isIRAP() && pcSlice->getUseIBC())
#else
if (pcSlice->isIRAP() && pcSlice->getSPS()->getIBCFlag())
#endif
#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
int poc1stCol = -1;
int list1stCol = 0;
int list2ndCol = 0;
#endif
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 JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
if ((!isResamplingPossible || !pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->isRefScaled(pcSlice->getPPS())) /*&& (pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->slices[0]->getSliceType() != I_SLICE)*/)
#else
if (!isResamplingPossible || !pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->isRefScaled(pcSlice->getPPS()))
#endif
#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
poc1stCol = pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->getPOC();
list1stCol = 0;
#endif
colRefIdxL0 = refIdx;
break;
}
}
if (pcSlice->getSliceType() == B_SLICE)
#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
list2ndCol = 1;
if (colRefIdxL0 < 0)
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
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())) /*&& (pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->slices[0]->getSliceType() != I_SLICE)*/)
{
poc1stCol = pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->getPOC();
list1stCol = 1;
colRefIdxL0 = refIdx;
break;
}
}
}
#endif
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 JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
int poc2ndCol = pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->getPOC();
if ((poc1stCol != poc2ndCol) && (!isResamplingPossible || !pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->isRefScaled(pcSlice->getPPS())) /*&& (pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->slices[0]->getSliceType() != I_SLICE)*/)
#else
if (!isResamplingPossible || !pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->isRefScaled(pcSlice->getPPS()))
#endif
#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
list2ndCol = 1;
#endif
colRefIdxL1 = refIdx;
break;
}
}
}
#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
else
{
for (int refIdx = 0; refIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0); refIdx++)
{
int poc2ndCol = pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->getPOC();
CHECK(pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->unscaledPic == nullptr, "unscaledPic is not set for L0 reference picture");
if ((poc1stCol != poc2ndCol) && (!isResamplingPossible || !pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->isRefScaled(pcSlice->getPPS())) /*&& (pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->slices[0]->getSliceType() != I_SLICE)*/)
{
colRefIdxL1 = refIdx;
break;
}
}
}
#endif
if (colRefIdxL0 >= 0 && colRefIdxL1 >= 0)
#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
const Picture *refPicL0 = pcSlice->getRefPic(RefPicList(list1stCol), colRefIdxL0);
if (!refPicL0->slices.size())
{
refPicL0 = refPicL0->unscaledPic;
}
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
const Picture *refPicL1 = pcSlice->getRefPic(RefPicList(list2ndCol), colRefIdxL1);
if (!refPicL1->slices.size())
{
refPicL1 = refPicL1->unscaledPic;
}
picHeader->setPicColFromL0Flag(1 - list1stCol);
pcSlice->setColFromL0Flag(1 - list1stCol);
pcSlice->setColRefIdx(colRefIdxL0);
picHeader->setColRefIdx(colRefIdxL0);
picHeader->setPicColFromL0Flag2nd(1 - list2ndCol);
pcSlice->setColFromL0Flag2nd(1 - list2ndCol);
pcSlice->setColRefIdx2nd(colRefIdxL1);
picHeader->setColRefIdx2nd(colRefIdxL1);
int poc1st = refPicL0->getPOC();
int poc2nd = refPicL1->getPOC();
int pocCur = pcSlice->getPOC();
if ((abs(poc1st - pocCur) == abs(poc2nd - pocCur)) && (refPicL0->slices[0]->getSliceQp() < refPicL1->slices[0]->getSliceQp()))
{
picHeader->setPicColFromL0Flag2nd(1 - list1stCol);
pcSlice->setColFromL0Flag2nd(1 - list1stCol);
pcSlice->setColRefIdx2nd(colRefIdxL0);
picHeader->setColRefIdx2nd(colRefIdxL0);
picHeader->setPicColFromL0Flag(1 - list2ndCol);
pcSlice->setColFromL0Flag(1 - list2ndCol);
pcSlice->setColRefIdx(colRefIdxL1);
picHeader->setColRefIdx(colRefIdxL1);
}
#else
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);
picHeader->setColRefIdx(uiColFromL0 ? colRefIdxL0 : colRefIdxL1);
#endif
#if !JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
else if (colRefIdxL0 < 0 && colRefIdxL1 >= 0)
picHeader->setPicColFromL0Flag(false);
pcSlice->setColFromL0Flag(false);
pcSlice->setColRefIdx(colRefIdxL1);
picHeader->setColRefIdx(colRefIdxL1);
#endif
else if (colRefIdxL0 >= 0 && colRefIdxL1 < 0)
{
#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
picHeader->setPicColFromL0Flag(1 - list1stCol);
pcSlice->setColFromL0Flag(1 - list1stCol);
pcSlice->setColRefIdx(colRefIdxL0);
picHeader->setColRefIdx(colRefIdxL0);
picHeader->setPicColFromL0Flag2nd(1 - list2ndCol);
pcSlice->setColFromL0Flag2nd(1 - list2ndCol);
pcSlice->setColRefIdx2nd(0);
picHeader->setColRefIdx2nd(0);
#else
picHeader->setPicColFromL0Flag(true);
pcSlice->setColFromL0Flag(true);
pcSlice->setColRefIdx(colRefIdxL0);
picHeader->setColRefIdx(colRefIdxL0);
#endif
}
else
{
picHeader->setEnableTMVPFlag(0);
#if JVET_AH0069_CMVP
if (picHeader->getEnableTMVPFlag())
{
pcSlice->setRefRefIdxList();
}
#endif
#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING
if (picHeader->getEnableTMVPFlag())
{
#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
for (int colFrameIdx = 0; colFrameIdx < (pcSlice->isInterB() ? 2 : 1); colFrameIdx++)
{
const Picture* const pColPic = pcSlice->getRefPic(RefPicList(colFrameIdx == 0 ? 1 - pcSlice->getColFromL0Flag() : 1 - pcSlice->getColFromL0Flag2nd()), colFrameIdx == 0 ? pcSlice->getColRefIdx() : pcSlice->getColRefIdx2nd());
#else
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();
#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION
pcSlice->resizeImBuf(pColPic->numSlices, colFrameIdx);
#else
Slice *pColSlice = nullptr;
for (int sliceIdx = 0; sliceIdx < pColPic->numSlices; sliceIdx++)
{
pColSlice = pColPic->slices[sliceIdx];
if (pColSlice->isIntra())
{
continue;
}