Commit c5c5ee3d authored by Yonatan Shiferaw's avatar Yonatan Shiferaw
Browse files

Decoder with partial output feature

parent 1af8e5fe
......@@ -15,3 +15,8 @@ deploy
*.pyc
/out/
/doc/_minted-software-manual/
BesketballDrill_subpic_3slice_2tile_5frames.yuv
BasketballDrill_subpic_3slice_2tile_5frames.bin
test.yuv
test.bin
/cfg/per-sequence/ArenaOfValor_256x144.cfg
......@@ -168,18 +168,37 @@ uint32_t DecApp::decode()
bool gdrRecoveryPeriod[MAX_NUM_LAYER_IDS] = { false };
bool prevPicSkipped = true;
bool bPartialOutput = false; //To enable/disable a partial output of a slice
while (!!bitstreamFile)
{
InputNALUnit nalu;
nalu.m_nalUnitType = NAL_UNIT_INVALID;
int bPartialOutputLayer = 0; //layer ID of the picture to be partially output, if bPartialOutput is set to true.
// determine if next NAL unit will be the first one from a new picture
bool bNewPicture = m_cDecLib.isNewPicture(&bitstreamFile, &bytestream);
bool bNewAccessUnit = bNewPicture && m_cDecLib.isNewAccessUnit( bNewPicture, &bitstreamFile, &bytestream );
// Check the conditions to partially output a frame and write the partial frame to the file
if (bPartialOutput
&& !((bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) && !m_cDecLib.getFirstSliceInSequence(nalu.m_nuhLayerId) && !bPicSkipped) // We don't need to partially output a slice if a the whole frame is going to be written
&& ((m_iPOCLastDisplay + 1 == m_cDecLib.getCurrPic()->getPOC()) || m_iPOCLastDisplay == -MAX_INT)) // Make sure that the frame that is being partially written is the frame being expected in the output sequence.
{
// \TODO you may need to apply Filter for the partial frames before writing them to file
msg( INFO, "[POC %d LId: %d <<Partial Output of Frame>>] \n", m_cDecLib.getCurrPic()->getPOC(), bPartialOutputLayer);
xPreWriteOutput(m_cDecLib.getCurrPic(), bPartialOutputLayer);
}
//Initialize the partial output to false
bPartialOutput = false;
if(!bNewPicture)
{
AnnexBStats stats = AnnexBStats();
// find next NAL unit in stream
byteStreamNALUnit(bytestream, nalu.getBitstream().getFifo(), stats);
if (nalu.getBitstream().getFifo().empty())
......@@ -256,6 +275,13 @@ uint32_t DecApp::decode()
int skipFrameCounter = m_iSkipFrame;
m_cDecLib.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay, m_targetOlsIdx);
//Partially output the picture if it is a picture slice that is currently decoded
if ((nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_TRAIL) && (nalu.m_nalUnitType <= NAL_UNIT_CODED_SLICE_GDR))
{
bPartialOutput = true;
bPartialOutputLayer = nalu.m_nuhLayerId;
}
if ( prevPicSkipped && nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_GDR )
{
gdrRecoveryPeriod[nalu.m_nuhLayerId] = true;
......@@ -658,7 +684,7 @@ void DecApp::xWriteOutput( PicList* pcListPic, uint32_t tId )
Picture* pcPic = *(iterPic);
if(pcPic->neededForOutput && pcPic->getPOC() > m_iPOCLastDisplay)
{
numPicsNotYetDisplayed++;
numPicsNotYetDisplayed++;
dpbFullness++;
}
else if(pcPic->referenced)
......@@ -771,7 +797,7 @@ void DecApp::xWriteOutput( PicList* pcListPic, uint32_t tId )
conf.getWindowTopOffset() * SPS::getWinUnitY( chromaFormatIDC ),
conf.getWindowBottomOffset() * SPS::getWinUnitY( chromaFormatIDC ),
NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range );
}
}
}
writeLineToOutputLog(pcPic);
......@@ -954,6 +980,84 @@ void DecApp::xFlushOutput( PicList* pcListPic, const int layerId )
m_iPOCLastDisplay = -MAX_INT;
}
/** \param pcCurrPic current picture to be written to file
*/
void DecApp::xPreWriteOutput( const Picture* pcCurrPic, const int layerId )
{
if(!pcCurrPic)
{
msg( INFO, "[No frame to partially Output!!] \n");
return;
}
const Picture* pcPic = pcCurrPic;
// Open the file to write if not opened yet: for partially outputting the first frame
if( !m_reconFileName.empty() && !m_cVideoIOYuvReconFile[layerId].isOpen() )
{
const BitDepths &bitDepths=pcPic->cs->sps->getBitDepths(); // use bit depths of first reconstructed picture.
for( uint32_t channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++ )
{
if( m_outputBitDepth[channelType] == 0 )
{
m_outputBitDepth[channelType] = bitDepths.recon[channelType];
}
}
if (m_packedYUVMode && (m_outputBitDepth[CH_L] != 10 && m_outputBitDepth[CH_L] != 12))
{
EXIT ("Invalid output bit-depth for packed YUV output, aborting\n");
}
std::string reconFileName = m_reconFileName;
if( m_reconFileName.compare( "/dev/null" ) && m_cDecLib.getVPS() != nullptr && m_cDecLib.getVPS()->getMaxLayers() > 1 && xIslayerIDWithinTargetOutputLayerIdSet( layerId ))
{
size_t pos = reconFileName.find_last_of('.');
std::string layerString = std::string(".layer") + std::to_string(layerId);
if (pos != string::npos)
{
reconFileName.insert(pos, layerString);
}
else
{
reconFileName.append(layerString);
}
}
if( ( m_cDecLib.getVPS() != nullptr && ( m_cDecLib.getVPS()->getMaxLayers() == 1 || xIslayerIDWithinTargetOutputLayerIdSet( layerId ) ) ) || m_cDecLib.getVPS() == nullptr )
{
m_cVideoIOYuvReconFile[layerId].open( reconFileName, true, m_outputBitDepth, m_outputBitDepth, bitDepths.recon ); // write mode
}
}
// write to file
if (!m_reconFileName.empty() && m_cVideoIOYuvReconFile[pcPic->layerId].isOpen())
{
const Window &conf = pcPic->getConformanceWindow();
const SPS* sps = pcPic->cs->sps;
ChromaFormat chromaFormatIDC = sps->getChromaFormatIdc();
if( m_upscaledOutput )
{
m_cVideoIOYuvReconFile[pcPic->layerId].writeUpscaledPicture( *sps, *pcPic->cs->pps, pcPic->getRecoBuf(), m_outputColourSpaceConvert, m_packedYUVMode, m_upscaledOutput, NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range );
}
else
{
m_cVideoIOYuvReconFile[pcPic->layerId].write( pcPic->getRecoBuf().get( COMPONENT_Y ).width, pcPic->getRecoBuf().get( COMPONENT_Y ).height, pcPic->getRecoBuf(),
m_outputColourSpaceConvert,
m_packedYUVMode,
conf.getWindowLeftOffset() * SPS::getWinUnitX( chromaFormatIDC ),
conf.getWindowRightOffset() * SPS::getWinUnitX( chromaFormatIDC ),
conf.getWindowTopOffset() * SPS::getWinUnitY( chromaFormatIDC ),
conf.getWindowBottomOffset() * SPS::getWinUnitY( chromaFormatIDC ),
NUM_CHROMA_FORMAT, m_bClipOutputVideoToRec709Range );
}
}
}
/** \param pcListPic list of pictures to be written to file
*/
void DecApp::xOutputAnnotatedRegions(PicList* pcListPic)
......@@ -1116,13 +1220,20 @@ bool DecApp::xIsNaluWithinTargetDecLayerIdSet( const InputNALUnit* nalu ) const
/** \param nalu Input nalu to check whether its LayerId is within targetOutputLayerIdSet
*/
bool DecApp::xIsNaluWithinTargetOutputLayerIdSet( const InputNALUnit* nalu ) const
{
return xIslayerIDWithinTargetOutputLayerIdSet( nalu->m_nuhLayerId );
}
/** \param layerId Input check whether its LayerId is within targetOutputLayerIdSet
*/
bool DecApp::xIslayerIDWithinTargetOutputLayerIdSet( const int layerId ) const
{
if( !m_targetOutputLayerIdSet.size() ) // By default, the set is empty, meaning all LayerIds are allowed
{
return true;
}
return std::find( m_targetOutputLayerIdSet.begin(), m_targetOutputLayerIdSet.end(), nalu->m_nuhLayerId ) != m_targetOutputLayerIdSet.end();
return std::find( m_targetOutputLayerIdSet.begin(), m_targetOutputLayerIdSet.end(), layerId ) != m_targetOutputLayerIdSet.end();
}
//! \}
......@@ -77,6 +77,7 @@ private:
private:
bool xIsNaluWithinTargetDecLayerIdSet( const InputNALUnit* nalu ) const; ///< check whether given Nalu is within targetDecLayerIdSet
bool xIsNaluWithinTargetOutputLayerIdSet( const InputNALUnit* nalu ) const; ///< check whether given Nalu is within targetOutputLayerIdSet
bool xIslayerIDWithinTargetOutputLayerIdSet( const int layerId ) const; ///< check whether given Nalu layerID is within targetOutputLayerIdSet
public:
DecApp();
......@@ -93,6 +94,7 @@ private:
#else
void xFlushOutput( PicList* pcListPic, const int layerId = NOT_VALID ); ///< flush all remaining decoded pictures to file
#endif
void xPreWriteOutput( const Picture* pcCurrPic, const int layerId = NOT_VALID ); ///< Partially Write a Frame
bool isNewPicture(ifstream *bitstreamFile, class InputByteStream *bytestream); ///< check if next NAL unit will be the first NAL unit from a new picture
bool isNewAccessUnit(bool newPicture, ifstream *bitstreamFile, class InputByteStream *bytestream); ///< check if next NAL unit will be the first NAL unit from a new access unit
......
......@@ -295,6 +295,8 @@ public:
bool getMixedNaluTypesInPicFlag();
Picture* getCurrPic() const { return m_pcPic; } //\TODO Only output if there is a decoded slice only // check active picture with -- if (m_pcPic).
protected:
void xUpdateRasInit(Slice* slice);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment