Commit 4951ad32 authored by Jack Enhorn's avatar Jack Enhorn
Browse files

GDR related decoder fixes

parent e286149a
...@@ -165,6 +165,9 @@ uint32_t DecApp::decode() ...@@ -165,6 +165,9 @@ uint32_t DecApp::decode()
m_cDecLib.setHTidExternalSetFlag(m_mTidExternalSet); m_cDecLib.setHTidExternalSetFlag(m_mTidExternalSet);
m_cDecLib.setTOlsIdxExternalFlag(m_tOlsIdxTidExternalSet); m_cDecLib.setTOlsIdxExternalFlag(m_tOlsIdxTidExternalSet);
bool gdrRecoveryPeriod[MAX_NUM_LAYER_IDS] = { false };
bool prevPicSkipped = true;
while (!!bitstreamFile) while (!!bitstreamFile)
{ {
InputNALUnit nalu; InputNALUnit nalu;
...@@ -249,7 +252,40 @@ uint32_t DecApp::decode() ...@@ -249,7 +252,40 @@ uint32_t DecApp::decode()
bPicSkipped = false; bPicSkipped = false;
} }
} }
int skipFrameCounter = m_iSkipFrame;
m_cDecLib.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay, m_targetOlsIdx); m_cDecLib.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay, m_targetOlsIdx);
if ( prevPicSkipped && nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_GDR )
{
gdrRecoveryPeriod[nalu.m_nuhLayerId] = true;
}
if ( skipFrameCounter == 1 && ( nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_GDR || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA ))
{
skipFrameCounter--;
}
if ( m_iSkipFrame < skipFrameCounter &&
((nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_TRAIL) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_STSA) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_RASL) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_RADL) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA) || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_GDR)))
{
if (m_cDecLib.isSliceNaluFirstInAU(true, nalu))
{
m_cDecLib.checkSeiInPictureUnit();
m_cDecLib.resetPictureSeiNalus();
m_cDecLib.checkAPSInPictureUnit();
m_cDecLib.resetPictureUnitNals();
m_cDecLib.resetAccessUnitSeiTids();
m_cDecLib.checkSEIInAccessUnit();
m_cDecLib.resetAccessUnitSeiPayLoadTypes();
m_cDecLib.resetAccessUnitNals();
m_cDecLib.resetAccessUnitApsNals();
m_cDecLib.resetAccessUnitPicInfo();
}
bPicSkipped = true;
m_iSkipFrame++; // skipFrame count restore, the real decrement occur at the begin of next frame
}
if (nalu.m_nalUnitType == NAL_UNIT_OPI) if (nalu.m_nalUnitType == NAL_UNIT_OPI)
{ {
if (!m_cDecLib.getHTidExternalSetFlag() && m_cDecLib.getOPI()->getHtidInfoPresentFlag()) if (!m_cDecLib.getHTidExternalSetFlag() && m_cDecLib.getOPI()->getHtidInfoPresentFlag())
...@@ -270,6 +306,12 @@ uint32_t DecApp::decode() ...@@ -270,6 +306,12 @@ uint32_t DecApp::decode()
bPicSkipped = true; bPicSkipped = true;
} }
} }
if( nalu.isSlice() )
{
prevPicSkipped = bPicSkipped;
}
// once an EOS NAL unit appears in the current PU, mark the variable isEosPresentInPu as true // once an EOS NAL unit appears in the current PU, mark the variable isEosPresentInPu as true
if (nalu.m_nalUnitType == NAL_UNIT_EOS) if (nalu.m_nalUnitType == NAL_UNIT_EOS)
{ {
...@@ -299,6 +341,14 @@ uint32_t DecApp::decode() ...@@ -299,6 +341,14 @@ uint32_t DecApp::decode()
m_cDecLib.updateAssociatedIRAP(); m_cDecLib.updateAssociatedIRAP();
m_cDecLib.updatePrevGDRInSameLayer(); m_cDecLib.updatePrevGDRInSameLayer();
m_cDecLib.updatePrevIRAPAndGDRSubpic(); m_cDecLib.updatePrevIRAPAndGDRSubpic();
if ( gdrRecoveryPeriod[nalu.m_nuhLayerId] )
{
if ( m_cDecLib.getGDRRecoveryPocReached() )
{
gdrRecoveryPeriod[nalu.m_nuhLayerId] = false;
}
}
} }
else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) && else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) &&
m_cDecLib.getFirstSliceInSequence(nalu.m_nuhLayerId)) m_cDecLib.getFirstSliceInSequence(nalu.m_nuhLayerId))
...@@ -308,6 +358,19 @@ uint32_t DecApp::decode() ...@@ -308,6 +358,19 @@ uint32_t DecApp::decode()
if( pcListPic ) if( pcListPic )
{ {
if ( gdrRecoveryPeriod[nalu.m_nuhLayerId] ) // Suppress YUV and OPL output during GDR recovery
{
PicList::iterator iterPic = pcListPic->begin();
while (iterPic != pcListPic->end())
{
Picture *pcPic = *(iterPic++);
if (pcPic->layerId == nalu.m_nuhLayerId)
{
pcPic->neededForOutput = false;
}
}
}
if( !m_reconFileName.empty() && !m_cVideoIOYuvReconFile[nalu.m_nuhLayerId].isOpen() ) if( !m_reconFileName.empty() && !m_cVideoIOYuvReconFile[nalu.m_nuhLayerId].isOpen() )
{ {
const BitDepths &bitDepths=pcListPic->front()->cs->sps->getBitDepths(); // use bit depths of first reconstructed picture. const BitDepths &bitDepths=pcListPic->front()->cs->sps->getBitDepths(); // use bit depths of first reconstructed picture.
......
...@@ -614,12 +614,19 @@ void Slice::checkRPL(const ReferencePictureList* pRPL0, const ReferencePictureLi ...@@ -614,12 +614,19 @@ void Slice::checkRPL(const ReferencePictureList* pRPL0, const ReferencePictureLi
int irapPOC = getAssociatedIRAPPOC(); int irapPOC = getAssociatedIRAPPOC();
const int numEntries[] = { pRPL0->getNumberOfShorttermPictures() + pRPL0->getNumberOfLongtermPictures() + pRPL0->getNumberOfInterLayerPictures(), pRPL1->getNumberOfShorttermPictures() + pRPL1->getNumberOfLongtermPictures() + pRPL1->getNumberOfInterLayerPictures() }; int numEntries[] = { pRPL0->getNumberOfShorttermPictures() + pRPL0->getNumberOfLongtermPictures() + pRPL0->getNumberOfInterLayerPictures(), pRPL1->getNumberOfShorttermPictures() + pRPL1->getNumberOfLongtermPictures() + pRPL1->getNumberOfInterLayerPictures() };
const int numActiveEntries[] = { getNumRefIdx( REF_PIC_LIST_0 ), getNumRefIdx( REF_PIC_LIST_1 ) }; const int numActiveEntries[] = { getNumRefIdx( REF_PIC_LIST_0 ), getNumRefIdx( REF_PIC_LIST_1 ) };
const ReferencePictureList* rpl[] = { pRPL0, pRPL1 }; const ReferencePictureList* rpl[] = { pRPL0, pRPL1 };
const bool fieldSeqFlag = getSPS()->getFieldSeqFlag(); const bool fieldSeqFlag = getSPS()->getFieldSeqFlag();
const int layerIdx = m_pcPic->cs->vps == nullptr ? 0 : m_pcPic->cs->vps->getGeneralLayerIdx( m_pcPic->layerId ); const int layerIdx = m_pcPic->cs->vps == nullptr ? 0 : m_pcPic->cs->vps->getGeneralLayerIdx( m_pcPic->layerId );
if ( rcListPic.size() < numEntries[0] || rcListPic.size() < numEntries[1] )
{
numEntries[0] = 0;
numEntries[1] = 0;
msg( NOTICE, "Reset numEntriesL0 and numEntriesL1. E.g. receive a CRA after some skipped slices\n");
}
for( int refPicList = 0; refPicList < 2; refPicList++ ) for( int refPicList = 0; refPicList < 2; refPicList++ )
{ {
for( int i = 0; i < numEntries[refPicList]; i++ ) for( int i = 0; i < numEntries[refPicList]; i++ )
...@@ -668,7 +675,7 @@ void Slice::checkRPL(const ReferencePictureList* pRPL0, const ReferencePictureLi ...@@ -668,7 +675,7 @@ void Slice::checkRPL(const ReferencePictureList* pRPL0, const ReferencePictureLi
// Generated reference picture does not have picture header // Generated reference picture does not have picture header
const bool isGeneratedRefPic = pcRefPic->slices[0]->getPicHeader() ? false : true; const bool isGeneratedRefPic = pcRefPic->slices[0]->getPicHeader() ? false : true;
const bool nonReferencePictureFlag = isGeneratedRefPic ? pcRefPic->slices[0]->getPicHeader()->getNonReferencePictureFlag() : pcRefPic->nonReferencePictureFlag; const bool nonReferencePictureFlag = isGeneratedRefPic ? pcRefPic->nonReferencePictureFlag : pcRefPic->slices[0]->getPicHeader()->getNonReferencePictureFlag();
CHECK( pcRefPic == m_pcPic || nonReferencePictureFlag, "The picture referred to by each entry in RefPicList[ 0 ] or RefPicList[ 1 ] shall not be the current picture and shall have ph_non_ref_pic_flag equal to 0" ); CHECK( pcRefPic == m_pcPic || nonReferencePictureFlag, "The picture referred to by each entry in RefPicList[ 0 ] or RefPicList[ 1 ] shall not be the current picture and shall have ph_non_ref_pic_flag equal to 0" );
if( i < numActiveEntries[refPicList] ) if( i < numActiveEntries[refPicList] )
...@@ -1110,37 +1117,40 @@ void Slice::checkLeadingPictureRestrictions(PicList& rcListPic, const PPS& pps) ...@@ -1110,37 +1117,40 @@ void Slice::checkLeadingPictureRestrictions(PicList& rcListPic, const PPS& pps)
} }
const Slice* pcSlice = pcPic->slices[0]; const Slice* pcSlice = pcPic->slices[0];
if (pcSlice->getPicHeader()->getPicOutputFlag() == 1 && !this->getNoOutputOfPriorPicsFlag() && pcPic->layerId == this->m_nuhLayerId) if(pcSlice->getPicHeader()) // Generated reference picture does not have picture header
{ {
if ((nalUnitType == NAL_UNIT_CODED_SLICE_CRA || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL) && !pps.getMixedNaluTypesInPicFlag()) if (pcSlice->getPicHeader()->getPicOutputFlag() == 1 && !this->getNoOutputOfPriorPicsFlag() && pcPic->layerId == this->m_nuhLayerId)
{ {
CHECK(pcPic->poc >= this->getPOC(), "Any picture, with nuh_layer_id equal to a particular value layerId, that precedes an IRAP picture with nuh_layer_id " if ((nalUnitType == NAL_UNIT_CODED_SLICE_CRA || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL) && !pps.getMixedNaluTypesInPicFlag())
"equal to layerId in decoding order shall precede the IRAP picture in output order."); {
CHECK(pcPic->poc >= this->getPOC(), "Any picture, with nuh_layer_id equal to a particular value layerId, that precedes an IRAP picture with nuh_layer_id "
"equal to layerId in decoding order shall precede the IRAP picture in output order.");
}
} }
}
if (pcSlice->getPicHeader()->getPicOutputFlag() == 1 && pcPic->layerId == this->m_nuhLayerId) if (pcSlice->getPicHeader()->getPicOutputFlag() == 1 && pcPic->layerId == this->m_nuhLayerId)
{
if (nalUnitType == NAL_UNIT_CODED_SLICE_RADL)
{ {
if (this->getAssociatedIRAPPOC() > pcSlice->getAssociatedIRAPPOC() && !pps.getMixedNaluTypesInPicFlag()) if (nalUnitType == NAL_UNIT_CODED_SLICE_RADL)
{ {
if (this->getAssociatedIRAPPOC() != pcPic->poc) if (this->getAssociatedIRAPPOC() > pcSlice->getAssociatedIRAPPOC() && !pps.getMixedNaluTypesInPicFlag())
{ {
CHECK(pcPic->poc >= this->getPOC(), "Any picture, with nuh_layer_id equal to a particular value layerId, that precedes an IRAP picture with nuh_layer_id " if (this->getAssociatedIRAPPOC() != pcPic->poc)
"equal to layerId in decoding order shall precede any RADL picture associated with the IRAP picture in output order."); {
CHECK(pcPic->poc >= this->getPOC(), "Any picture, with nuh_layer_id equal to a particular value layerId, that precedes an IRAP picture with nuh_layer_id "
"equal to layerId in decoding order shall precede any RADL picture associated with the IRAP picture in output order.");
}
} }
} }
} }
}
if (pcSlice->getPicHeader()->getPicOutputFlag() == 1 && !this->getPicHeader()->getNoOutputBeforeRecoveryFlag() && pcPic->layerId == this->m_nuhLayerId if (pcSlice->getPicHeader()->getPicOutputFlag() == 1 && !this->getPicHeader()->getNoOutputBeforeRecoveryFlag() && pcPic->layerId == this->m_nuhLayerId
&& nalUnitType != NAL_UNIT_CODED_SLICE_GDR && this->getPicHeader()->getRecoveryPocCnt() != -1) && nalUnitType != NAL_UNIT_CODED_SLICE_GDR && this->getPicHeader()->getRecoveryPocCnt() != -1)
{
if (this->getPOC() == this->getPicHeader()->getRecoveryPocCnt() + this->getPrevGDRInSameLayerPOC())
{ {
CHECK(pcPic->poc >= this->getPOC(), "Any picture, with nuh_layer_id equal to a particular value layerId, that precedes a recovery point picture with " if (this->getPOC() == this->getPicHeader()->getRecoveryPocCnt() + this->getPrevGDRInSameLayerPOC())
"nuh_layer_id equal to layerId in decoding order shall precede the recovery point picture in output order."); {
CHECK(pcPic->poc >= this->getPOC(), "Any picture, with nuh_layer_id equal to a particular value layerId, that precedes a recovery point picture with "
"nuh_layer_id equal to layerId in decoding order shall precede the recovery point picture in output order.");
}
} }
} }
...@@ -1251,14 +1261,18 @@ void Slice::checkSubpicTypeConstraints(PicList& rcListPic, const ReferencePictur ...@@ -1251,14 +1261,18 @@ void Slice::checkSubpicTypeConstraints(PicList& rcListPic, const ReferencePictur
bool isBufPicOutput = false; bool isBufPicOutput = false;
int bufSubpicType = NAL_UNIT_INVALID; int bufSubpicType = NAL_UNIT_INVALID;
int bufSubpicPrevIRAPSubpicPOC = 0; int bufSubpicPrevIRAPSubpicPOC = 0;
for (int i = 0; i < bufPic->numSlices; i++)
if (bufPic->slices[0]->getPicHeader() != NULL) // Generated reference picture does not have picture header
{ {
if (bufPic->sliceSubpicIdx[i] == curSubpicIdx) for (int i = 0; i < bufPic->numSlices; i++)
{ {
isBufPicOutput = bufPic->slices[i]->getPicHeader()->getPicOutputFlag(); if (bufPic->sliceSubpicIdx[i] == curSubpicIdx)
bufSubpicType = bufPic->slices[i]->getNalUnitType(); {
bufSubpicPrevIRAPSubpicPOC = bufPic->slices[i]->getPrevIRAPSubpicPOC(); isBufPicOutput = bufPic->slices[i]->getPicHeader()->getPicOutputFlag();
break; bufSubpicType = bufPic->slices[i]->getNalUnitType();
bufSubpicPrevIRAPSubpicPOC = bufPic->slices[i]->getPrevIRAPSubpicPOC();
break;
}
} }
} }
...@@ -1813,7 +1827,7 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi ...@@ -1813,7 +1827,7 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi
{ {
if (printErrors) if (printErrors)
{ {
msg(ERROR, "\nCurrent picture: %d Long-term reference picture with POC = %3d seems to have been removed or not correctly decoded.", this->getPOC(), notPresentPoc); msg(ERROR, "Error: Current picture: %d Long-term reference picture with POC = %3d seems to have been removed or not correctly decoded.\n", this->getPOC(), notPresentPoc);
} }
return notPresentPoc; return notPresentPoc;
} }
...@@ -1844,7 +1858,7 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi ...@@ -1844,7 +1858,7 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi
{ {
if (printErrors) if (printErrors)
{ {
msg(ERROR, "\nCurrent picture: %d Short-term reference picture with POC = %3d seems to have been removed or not correctly decoded.", this->getPOC(), notPresentPoc); msg(ERROR, "Error: Current picture: %d Short-term reference picture with POC = %3d seems to have been removed or not correctly decoded.\n", this->getPOC(), notPresentPoc);
} }
return notPresentPoc; return notPresentPoc;
} }
...@@ -1923,7 +1937,7 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi ...@@ -1923,7 +1937,7 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi
{ {
if (printErrors) if (printErrors)
{ {
msg(ERROR, "\nCurrent picture: %d Long-term reference picture with POC = %3d seems to have been removed or not correctly decoded.", this->getPOC(), notPresentPoc); msg(ERROR, "Error: Current picture: %d Long-term reference picture with POC = %3d seems to have been removed or not correctly decoded.\n", this->getPOC(), notPresentPoc);
} }
*refPicIndex = ii; *refPicIndex = ii;
return notPresentPoc; return notPresentPoc;
...@@ -1955,7 +1969,7 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi ...@@ -1955,7 +1969,7 @@ int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePi
{ {
if (printErrors) if (printErrors)
{ {
msg(ERROR, "\nCurrent picture: %d Short-term reference picture with POC = %3d seems to have been removed or not correctly decoded.", this->getPOC(), notPresentPoc); msg(ERROR, "Error: Current picture: %d Short-term reference picture with POC = %3d seems to have been removed or not correctly decoded.\n", this->getPOC(), notPresentPoc);
} }
*refPicIndex = ii; *refPicIndex = ii;
return notPresentPoc; return notPresentPoc;
......
...@@ -424,11 +424,11 @@ DecLib::DecLib() ...@@ -424,11 +424,11 @@ DecLib::DecLib()
, m_prevPicPOC(MAX_INT) , m_prevPicPOC(MAX_INT)
, m_prevTid0POC(0) , m_prevTid0POC(0)
, m_bFirstSliceInPicture(true) , m_bFirstSliceInPicture(true)
, m_firstSliceInSequence{ true }
, m_firstSliceInBitstream(true) , m_firstSliceInBitstream(true)
, m_isFirstAuInCvs( true ) , m_isFirstAuInCvs( true )
, m_prevSliceSkipped(false) , m_prevSliceSkipped(false)
, m_skippedPOC(0) , m_skippedPOC(MAX_INT)
, m_skippedLayerID(MAX_INT)
, m_lastPOCNoOutputPriorPics(-1) , m_lastPOCNoOutputPriorPics(-1)
, m_isNoOutputPriorPics(false) , m_isNoOutputPriorPics(false)
, m_lastNoOutputBeforeRecoveryFlag{ false } , m_lastNoOutputBeforeRecoveryFlag{ false }
...@@ -463,6 +463,8 @@ DecLib::DecLib() ...@@ -463,6 +463,8 @@ DecLib::DecLib()
memset(m_prevEOS, false, sizeof(m_prevEOS)); memset(m_prevEOS, false, sizeof(m_prevEOS));
memset(m_accessUnitEos, false, sizeof(m_accessUnitEos)); memset(m_accessUnitEos, false, sizeof(m_accessUnitEos));
std::fill_n(m_prevGDRInSameLayerPOC, MAX_VPS_LAYERS, -MAX_INT); std::fill_n(m_prevGDRInSameLayerPOC, MAX_VPS_LAYERS, -MAX_INT);
std::fill_n(m_prevGDRInSameLayerRecoveryPOC, MAX_VPS_LAYERS, -MAX_INT);
std::fill_n(m_firstSliceInSequence, MAX_VPS_LAYERS, true);
std::fill_n(m_pocCRA, MAX_VPS_LAYERS, -MAX_INT); std::fill_n(m_pocCRA, MAX_VPS_LAYERS, -MAX_INT);
for (int i = 0; i < MAX_VPS_LAYERS; i++) for (int i = 0; i < MAX_VPS_LAYERS; i++)
{ {
...@@ -898,13 +900,22 @@ void DecLib::xCreateLostPicture( int iLostPoc, const int layerId ) ...@@ -898,13 +900,22 @@ void DecLib::xCreateLostPicture( int iLostPoc, const int layerId )
void DecLib::xCreateUnavailablePicture( const PPS *pps, const int iUnavailablePoc, const bool longTermFlag, const int temporalId, const int layerId, const bool interLayerRefPicFlag ) void DecLib::xCreateUnavailablePicture( const PPS *pps, const int iUnavailablePoc, const bool longTermFlag, const int temporalId, const int layerId, const bool interLayerRefPicFlag )
{ {
msg(INFO, "\ninserting unavailable poc : %d\n", iUnavailablePoc); msg(INFO, "Note: Inserting unavailable POC : %d\n", iUnavailablePoc);
Picture* cFillPic = xGetNewPicBuffer( *( m_parameterSetManager.getFirstSPS() ), *( m_parameterSetManager.getFirstPPS() ), 0, layerId ); Picture* cFillPic = xGetNewPicBuffer( *( m_parameterSetManager.getFirstSPS() ), *( m_parameterSetManager.getFirstPPS() ), 0, layerId );
CHECK(!cFillPic->slices.size(), "No slices in picture"); cFillPic->cs = new CodingStructure( g_globalUnitCache.cuCache, g_globalUnitCache.puCache, g_globalUnitCache.tuCache );
cFillPic->cs->sps = m_parameterSetManager.getFirstSPS();
cFillPic->cs->pps = m_parameterSetManager.getFirstPPS();
cFillPic->cs->vps = m_parameterSetManager.getVPS(0);
cFillPic->cs->create(cFillPic->cs->sps->getChromaFormatIdc(), Area(0, 0, cFillPic->cs->pps->getPicWidthInLumaSamples(), cFillPic->cs->pps->getPicHeightInLumaSamples()), true, (bool)(cFillPic->cs->sps->getPLTMode()));
cFillPic->allocateNewSlice();
cFillPic->slices[0]->initSlice(); cFillPic->slices[0]->initSlice();
cFillPic->setDecodingOrderNumber(0);
cFillPic->subLayerNonReferencePictureDueToSTSA = false;
cFillPic->unscaledPic = cFillPic;
uint32_t yFill = 1 << (m_parameterSetManager.getFirstSPS()->getBitDepth(CHANNEL_TYPE_LUMA) - 1); uint32_t yFill = 1 << (m_parameterSetManager.getFirstSPS()->getBitDepth(CHANNEL_TYPE_LUMA) - 1);
uint32_t cFill = 1 << (m_parameterSetManager.getFirstSPS()->getBitDepth(CHANNEL_TYPE_CHROMA) - 1); uint32_t cFill = 1 << (m_parameterSetManager.getFirstSPS()->getBitDepth(CHANNEL_TYPE_CHROMA) - 1);
cFillPic->getRecoBuf().Y().fill(yFill); cFillPic->getRecoBuf().Y().fill(yFill);
...@@ -916,7 +927,12 @@ void DecLib::xCreateUnavailablePicture( const PPS *pps, const int iUnavailableP ...@@ -916,7 +927,12 @@ void DecLib::xCreateUnavailablePicture( const PPS *pps, const int iUnavailableP
cFillPic->interLayerRefPicFlag = interLayerRefPicFlag; cFillPic->interLayerRefPicFlag = interLayerRefPicFlag;
cFillPic->longTerm = longTermFlag; cFillPic->longTerm = longTermFlag;
cFillPic->slices[0]->setPOC(iUnavailablePoc); cFillPic->slices[0]->setPOC(iUnavailablePoc);
xUpdatePreviousTid0POC(cFillPic->slices[0]); cFillPic->poc = iUnavailablePoc;
if( (cFillPic->slices[0]->getTLayer() == 0) && (cFillPic->slices[0]->getNalUnitType() != NAL_UNIT_CODED_SLICE_RASL) && (cFillPic->slices[0]->getNalUnitType() != NAL_UNIT_CODED_SLICE_RADL) )
{
m_prevTid0POC = cFillPic->slices[0]->getPOC();
}
cFillPic->reconstructed = true; cFillPic->reconstructed = true;
cFillPic->neededForOutput = false; cFillPic->neededForOutput = false;
// picture header is not derived for generated reference picture // picture header is not derived for generated reference picture
...@@ -955,6 +971,11 @@ void DecLib::checkLayerIdIncludedInCvss() ...@@ -955,6 +971,11 @@ void DecLib::checkLayerIdIncludedInCvss()
for (auto pic = m_accessUnitPicInfo.begin(); pic != m_accessUnitPicInfo.end(); pic++) for (auto pic = m_accessUnitPicInfo.begin(); pic != m_accessUnitPicInfo.end(); pic++)
{ {
bool layerIdFind; bool layerIdFind;
if ( m_firstAccessUnitPicInfo.size() == 0 )
{
msg( NOTICE, "Note: checkIncludedInFirstAu(), m_firstAccessUnitPicInfo.size() is 0.\n");
continue;
}
for (auto picFirst = m_firstAccessUnitPicInfo.begin(); picFirst != m_firstAccessUnitPicInfo.end(); picFirst++) for (auto picFirst = m_firstAccessUnitPicInfo.begin(); picFirst != m_firstAccessUnitPicInfo.end(); picFirst++)
{ {
layerIdFind = pic->m_nuhLayerId == picFirst->m_nuhLayerId ? true : false; layerIdFind = pic->m_nuhLayerId == picFirst->m_nuhLayerId ? true : false;
...@@ -2086,6 +2107,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl ...@@ -2086,6 +2107,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
m_accessUnitNoOutputPriorPicFlags.push_back(m_apcSlicePilot->getNoOutputOfPriorPicsFlag()); m_accessUnitNoOutputPriorPicFlags.push_back(m_apcSlicePilot->getNoOutputOfPriorPicsFlag());
} }
if (m_picHeader.getGdrPicFlag())
{
m_prevGDRInSameLayerRecoveryPOC[nalu.m_nuhLayerId] = m_picHeader.getRecoveryPocCnt();
}
PPS *pps = m_parameterSetManager.getPPS(m_picHeader.getPPSId()); PPS *pps = m_parameterSetManager.getPPS(m_picHeader.getPPSId());
CHECK(pps == 0, "No PPS present"); CHECK(pps == 0, "No PPS present");
SPS *sps = m_parameterSetManager.getSPS(pps->getSPSId()); SPS *sps = m_parameterSetManager.getSPS(pps->getSPSId());
...@@ -2282,10 +2308,12 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl ...@@ -2282,10 +2308,12 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
// Skip pictures due to random access // Skip pictures due to random access
if (isRandomAccessSkipPicture(iSkipFrame, iPOCLastDisplay, pps->getMixedNaluTypesInPicFlag())) if (isRandomAccessSkipPicture(iSkipFrame, iPOCLastDisplay, pps->getMixedNaluTypesInPicFlag(), nalu.m_nuhLayerId))
{ {
m_prevSliceSkipped = true; m_prevSliceSkipped = true;
m_skippedPOC = m_apcSlicePilot->getPOC(); m_skippedPOC = m_apcSlicePilot->getPOC();
m_skippedLayerID = nalu.m_nuhLayerId;
// reset variables for bitstream conformance tests // reset variables for bitstream conformance tests
resetAccessUnitNals(); resetAccessUnitNals();
resetAccessUnitApsNals(); resetAccessUnitApsNals();
...@@ -2335,7 +2363,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl ...@@ -2335,7 +2363,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
{ {
if (m_apcSlicePilot->getRPL0()->isInterLayerRefPic(refPicIndex) == 0) if (m_apcSlicePilot->getRPL0()->isInterLayerRefPic(refPicIndex) == 0)
{ {
xCreateUnavailablePicture( m_apcSlicePilot->getPPS(), lostPoc - 1, m_apcSlicePilot->getRPL0()->isRefPicLongterm( refPicIndex ), m_apcSlicePilot->getPic()->temporalId, m_apcSlicePilot->getPic()->layerId, m_apcSlicePilot->getRPL0()->isInterLayerRefPic( refPicIndex ) ); xCreateUnavailablePicture( pps, lostPoc, m_apcSlicePilot->getRPL0()->isRefPicLongterm( refPicIndex ), m_apcSlicePilot->getTLayer(), m_apcSlicePilot->getNalUnitLayerId(), m_apcSlicePilot->getRPL0()->isInterLayerRefPic( refPicIndex ) );
} }
} }
else else
...@@ -2956,6 +2984,11 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay, i ...@@ -2956,6 +2984,11 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay, i
case NAL_UNIT_SUFFIX_SEI: case NAL_UNIT_SUFFIX_SEI:
if (m_pcPic) if (m_pcPic)
{ {
if ( m_prevSliceSkipped )
{
msg( NOTICE, "Note: received suffix SEI but current picture is skipped.\n");
return false;
}
m_pictureSeiNalus.push_back(new InputNALUnit(nalu)); m_pictureSeiNalus.push_back(new InputNALUnit(nalu));
m_accessUnitSeiTids.push_back(nalu.m_temporalId); m_accessUnitSeiTids.push_back(nalu.m_temporalId);
const SPS *sps = m_parameterSetManager.getActiveSPS(); const SPS *sps = m_parameterSetManager.getActiveSPS();
...@@ -2987,6 +3020,7 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay, i ...@@ -2987,6 +3020,7 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay, i
m_associatedIRAPType[nalu.m_nuhLayerId] = NAL_UNIT_INVALID; m_associatedIRAPType[nalu.m_nuhLayerId] = NAL_UNIT_INVALID;
m_pocCRA[nalu.m_nuhLayerId] = -MAX_INT; m_pocCRA[nalu.m_nuhLayerId] = -MAX_INT;
m_prevGDRInSameLayerPOC[nalu.m_nuhLayerId] = -MAX_INT; m_prevGDRInSameLayerPOC[nalu.m_nuhLayerId] = -MAX_INT;
m_prevGDRInSameLayerRecoveryPOC[nalu.m_nuhLayerId] = -MAX_INT;
std::fill_n(m_prevGDRSubpicPOC[nalu.m_nuhLayerId], MAX_NUM_SUB_PICS, -MAX_INT); std::fill_n(m_prevGDRSubpicPOC[nalu.m_nuhLayerId], MAX_NUM_SUB_PICS, -MAX_INT);
std::fill_n(m_prevIRAPSubpicPOC[nalu.m_nuhLayerId], MAX_NUM_SUB_PICS, -MAX_INT); std::fill_n(m_prevIRAPSubpicPOC[nalu.m_nuhLayerId], MAX_NUM_SUB_PICS, -MAX_INT);
memset(m_prevIRAPSubpicDecOrderNo[nalu.m_nuhLayerId], 0, sizeof(int)*MAX_NUM_SUB_PICS); memset(m_prevIRAPSubpicDecOrderNo[nalu.m_nuhLayerId], 0, sizeof(int)*MAX_NUM_SUB_PICS);
...@@ -3055,11 +3089,22 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay, i ...@@ -3055,11 +3089,22 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay, i
* equal to or greater than the random access point POC is attempted. For non IDR/CRA/BLA random * equal to or greater than the random access point POC is attempted. For non IDR/CRA/BLA random
* access point there is no guarantee that the decoder will not crash. * access point there is no guarantee that the decoder will not crash.
*/ */
bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, bool mixedNaluInPicFlag ) bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, bool mixedNaluInPicFlag, uint32_t layerId )
{ {
if( (iSkipFrame > 0) &&
(m_apcSlicePilot->getFirstCtuRsAddrInSlice() == 0 && layerId == 0) &&
(m_skippedPOC != MAX_INT) && (m_skippedLayerID != MAX_INT))
{
// When skipFrame count greater than 0, and current frame is not the first frame of sequence, decrement skipFrame count.
// If skipFrame count is still greater than 0, the current frame will be skipped.
iSkipFrame--;
}
if (iSkipFrame) if (iSkipFrame)
{ {
iSkipFrame--; // decrement the counter iSkipFrame--; // decrement the counter
m_maxDecSubPicIdx = 0;
m_maxDecSliceAddrInSubPic = -1;
return true; return true;
} }
else if ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP ) else if ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP )
...@@ -3068,7 +3113,7 @@ bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, b ...@@ -3068,7 +3113,7 @@ bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, b
} }
else if (m_pocRandomAccess == MAX_INT) // start of random access point, m_pocRandomAccess has not been set yet. else if (m_pocRandomAccess == MAX_INT) // start of random access point, m_pocRandomAccess has not been set yet.
{ {
if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_apcSlicePilot->getPicHeader()->getRecoveryPocCnt() == 0 ) ) if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR )
{ {
// set the POC random access since we need to skip the reordered pictures in the case of CRA/CRANT/BLA/BLANT. // set the POC random access since we need to skip the reordered pictures in the case of CRA/CRANT/BLA/BLANT.
m_pocRandomAccess = m_apcSlicePilot->getPOC(); m_pocRandomAccess = m_apcSlicePilot->getPOC();
...@@ -3077,9 +3122,12 @@ bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, b ...@@ -3077,9 +3122,12 @@ bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, b
{ {
if(!m_warningMessageSkipPicture) if(!m_warningMessageSkipPicture)
{ {
msg( WARNING, "\nWarning: this is not a valid random access point and the data is discarded until the first CRA picture"); msg( WARNING, "Warning: This is not a valid random access point and the data is discarded until the first CRA or GDR picture\n");
m_warningMessageSkipPicture = true; m_warningMessageSkipPicture = true;
} }
iSkipFrame--;
m_maxDecSubPicIdx = 0;
m_maxDecSliceAddrInSubPic = -1;
return true; return true;
} }
} }
...@@ -3089,6 +3137,9 @@ bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, b ...@@ -3089,6 +3137,9 @@ bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay, b
mixedNaluInPicFlag)) mixedNaluInPicFlag))
{ {
iPOCLastDisplay++; iPOCLastDisplay++;
iSkipFrame--;
m_maxDecSubPicIdx = 0;
m_maxDecSliceAddrInSubPic = -1;
return true; return true;
} }
// if we reach here, then the picture is not skipped. // if we reach here, then the picture is not skipped.
......
...@@ -73,6 +73,7 @@ private: ...@@ -73,6 +73,7 @@ private:
GeneralHrdParams m_prevGeneralHrdParams;