/** - create internal class - initialize internal class - until the end of the bitstream, call decoding function in TDecTop class - delete allocated buffers - destroy internal class . */ Void TAppDecTop::decode() { #if VIDYO_VPS_INTEGRATION|QC_MVHEVC_B0046 increaseNumberOfViews( 0, 0, 0 ); #else increaseNumberOfViews( 1 ); #endif #if FLEX_CODING_ORDER_M23723 Int iDepthViewIdx = 0; Int iTextureViewIdx=0; Bool firstFrame=1; Bool viewIdZero=true; Int fcoIndex=0; //when the current frame is not first frame,use FCO_index stand for viewDepth. #endif Int viewDepthId = 0; Int previousViewDepthId = 0; UInt uiPOC[MAX_VIEW_NUM*2]; TComList<TComPic*>* pcListPic[MAX_VIEW_NUM*2]; Bool newPicture[MAX_VIEW_NUM*2]; Bool previousPictureDecoded = false; for( Int i = 0; i < MAX_VIEW_NUM*2; i++ ) { uiPOC[i] = 0; pcListPic[i] = NULL; newPicture[i] = false; #if FLEX_CODING_ORDER_M23723 m_fcoOrder[i] = ' '; #endif } ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary); if (!bitstreamFile) { fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile); exit(EXIT_FAILURE); } if( m_pchScaleOffsetFile ) { m_pScaleOffsetFile = ::fopen( m_pchScaleOffsetFile, "wt" ); AOF( m_pScaleOffsetFile ); } m_cCamParsCollector.init( m_pScaleOffsetFile ); InputByteStream bytestream(bitstreamFile); while (!!bitstreamFile) { /* location serves to work around a design fault in the decoder, whereby * the process of reading a new slice that is the first slice of a new frame * requires the TDecTop::decode() method to be called again with the same * nal unit. */ streampos location = bitstreamFile.tellg(); AnnexBStats stats = AnnexBStats(); vector<uint8_t> nalUnit; InputNALUnit nalu; byteStreamNALUnit(bytestream, nalUnit, stats); // call actual decoding function if (nalUnit.empty()) { /* this can happen if the following occur: * - empty input file * - two back-to-back start_code_prefixes * - start_code_prefix immediately followed by EOF */ fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n"); } else { read(nalu, nalUnit); #if QC_MVHEVC_B0046 viewDepthId = nalu.m_layerId; Int depth = 0; Int viewId = viewDepthId; #else #if VIDYO_VPS_INTEGRATION Int viewId = 0; Int depth = 0; if(nalu.m_nalUnitType != NAL_UNIT_VPS || nalu.m_layerId) { // code assumes that the first nal unit is VPS // currently, this is a hack that requires non-first VPSs have non-zero layer_id viewId = getVPSAccess()->getActiveVPS()->getViewId(nalu.m_layerId); depth = getVPSAccess()->getActiveVPS()->getDepthFlag(nalu.m_layerId); } #if FLEX_CODING_ORDER_M23723 if (viewId>0) { viewIdZero=false; } if (viewIdZero==false&&viewId==0) { firstFrame=0; //if viewId has been more than zero and now it set to zero again, we can see that it is not the first view } if (firstFrame) { // if the current view is first frame, we set the viewDepthId as texture plus depth and get the FCO order viewDepthId = iDepthViewIdx+iTextureViewIdx; m_fcoViewDepthId=viewDepthId; } else {//if current view is not first frame, we set the viewDepthId depended on the FCO order viewDepthId=0; if (depth) { for (fcoIndex=0;fcoIndex<2*MAX_VIEW_NUM;fcoIndex++ ) { if (m_fcoOrder[fcoIndex]=='D') { if (viewId==viewDepthId) break; else viewDepthId++; } } } else { for (fcoIndex=0;fcoIndex<2*MAX_VIEW_NUM;fcoIndex++ ) { if (m_fcoOrder[fcoIndex]=='T') { if (viewId==viewDepthId) break; else viewDepthId++; } } } viewDepthId=fcoIndex; } #else viewDepthId = nalu.m_layerId; // coding order T0D0T1D1T2D2 #endif #else Int viewId = nalu.m_viewId; Int depth = nalu.m_isDepth ? 1 : 0; #if FLEX_CODING_ORDER_M23723 if (viewId>0) { viewIdZero=false; } if (viewIdZero==false&&viewId==0) { firstFrame=0; } if (firstFrame) { viewDepthId = iDepthViewIdx+iTextureViewIdx; m_fcoViewDepthId=viewDepthId; } else { viewDepthId=0; if (depth) { for (fcoIndex=0;fcoIndex<2*MAX_VIEW_NUM;fcoIndex++ ) { if (m_fcoOrder[fcoIndex]=='D') { if (viewId==viewDepthId) break; else viewDepthId++; } } } else { for (fcoIndex=0;fcoIndex<2*MAX_VIEW_NUM;fcoIndex++ ) { if (m_fcoOrder[fcoIndex]=='T') { if (viewId==viewDepthId) break; else viewDepthId++; } } } viewDepthId=fcoIndex; } #else viewDepthId = viewId * 2 + depth; // coding order T0D0T1D1T2D2 #endif #endif #endif newPicture[viewDepthId] = false; if( viewDepthId >= m_tDecTop.size() ) { #if VIDYO_VPS_INTEGRATION|QC_MVHEVC_B0046 increaseNumberOfViews( viewDepthId, viewId, depth ); #else increaseNumberOfViews( viewDepthId +1 ); #endif } if(m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) { previousPictureDecoded = false; } if(m_tDecTop.size() > 1 && (viewDepthId != previousViewDepthId) && previousPictureDecoded ) { m_tDecTop[previousViewDepthId]->executeDeblockAndAlf(uiPOC[previousViewDepthId], pcListPic[previousViewDepthId], m_iSkipFrame, m_pocLastDisplay[previousViewDepthId]); } if( ( viewDepthId == 0 && (viewDepthId != previousViewDepthId) ) || m_tDecTop.size() == 1 ) { #if H3D_IVRP for( Int i = 0; i < m_tDecTop.size(); i++ ) { m_tDecTop[i]->deleteExtraPicBuffers( uiPOC[i] ); } #endif for( Int i = 0; i < m_tDecTop.size(); i++ ) { m_tDecTop[i]->compressMotion( uiPOC[i] ); } } if( !(m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) ) { #if QC_MVHEVC_B0046 if(viewDepthId && m_tDecTop[viewDepthId]->m_bFirstNal== false) { m_tDecTop[viewDepthId]->m_bFirstNal = true; ParameterSetManagerDecoder* pDecV0 = m_tDecTop[0]->xGetParaSetDec(); m_tDecTop[viewDepthId]->xCopyVPS(pDecV0->getPrefetchedVPS(0)); m_tDecTop[viewDepthId]->xCopySPS(pDecV0->getPrefetchedSPS(0)); m_tDecTop[viewDepthId]->xCopyPPS(pDecV0->getPrefetchedPPS(0)); } #endif newPicture[viewDepthId] = m_tDecTop[viewDepthId]->decode(nalu, m_iSkipFrame, m_pocLastDisplay[viewDepthId]); if (newPicture[viewDepthId]) { bitstreamFile.clear(); /* location points to the current nalunit payload[1] due to the * need for the annexB parser to read three extra bytes. * [1] except for the first NAL unit in the file * (but bNewPicture doesn't happen then) */ bitstreamFile.seekg(location-streamoff(3)); bytestream.reset(); } if( nalu.isSlice() ) { previousPictureDecoded = true; #if FLEX_CODING_ORDER_M23723 if (firstFrame) { if (depth) { iDepthViewIdx++; m_fcoOrder[viewDepthId]='D'; } else { iTextureViewIdx++; m_fcoOrder[viewDepthId]='T'; } } #endif } } } if( ( (newPicture[viewDepthId] || !bitstreamFile) && m_tDecTop.size() == 1) || (!bitstreamFile && previousPictureDecoded == true) ) { m_tDecTop[viewDepthId]->executeDeblockAndAlf(uiPOC[viewDepthId], pcListPic[viewDepthId], m_iSkipFrame, m_pocLastDisplay[viewDepthId]); } if( pcListPic[viewDepthId] ) { #if QC_REM_IDV_B0046 Int iviewId = m_tDecTop[viewDepthId]->getViewId(); if( newPicture[viewDepthId] && (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR || ((nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR && iviewId) && m_tDecTop[viewDepthId]->getNalUnitTypeBaseView() == NAL_UNIT_CODED_SLICE_IDR)) ) #else if( newPicture[viewDepthId] && (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR || (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_IDV && m_tDecTop[viewDepthId]->getNalUnitTypeBaseView() == NAL_UNIT_CODED_SLICE_IDR)) ) #endif { xFlushOutput( pcListPic[viewDepthId], viewDepthId ); } // write reconstruction to file if(newPicture[viewDepthId]) { xWriteOutput( pcListPic[viewDepthId], viewDepthId, nalu.m_temporalId ); } } previousViewDepthId = viewDepthId; } if( m_cCamParsCollector.isInitialized() ) { m_cCamParsCollector.setSlice( 0 ); } // last frame for( Int viewDepthIdx = 0; viewDepthIdx < m_tDecTop.size(); viewDepthIdx++ ) { xFlushOutput( pcListPic[viewDepthIdx], viewDepthIdx ); } xDestroyDecLib(); }
/** - create internal class - initialize internal class - until the end of the bitstream, call decoding function in TDecTop class - delete allocated buffers - destroy internal class . */ Void TAppDecTop::decode() { UInt uiPOC; TComList<TComPic*>* pcListPic = NULL; ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary); if (!bitstreamFile) { fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile); exit(EXIT_FAILURE); } InputByteStream bytestream(bitstreamFile); // create & initialize internal classes xCreateDecLib(); xInitDecLib (); m_iPOCLastDisplay += m_iSkipFrame; // set the last displayed POC correctly for skip forward. // main decoder loop bool recon_opened = false; // reconstruction file not yet opened. (must be performed after SPS is seen) while (!!bitstreamFile) { /* location serves to work around a design fault in the decoder, whereby * the process of reading a new slice that is the first slice of a new frame * requires the TDecTop::decode() method to be called again with the same * nal unit. */ streampos location = bitstreamFile.tellg(); AnnexBStats stats = AnnexBStats(); #if G1002_RPS bool bPreviousPictureDecoded = false; #endif vector<uint8_t> nalUnit; #if G1002_RPS && G1002_IDR_POC_ZERO_BUGFIX InputNALUnit nalu; #endif byteStreamNALUnit(bytestream, nalUnit, stats); // call actual decoding function bool bNewPicture = false; if (nalUnit.empty()) /* this can happen if the following occur: * - empty input file * - two back-to-back start_code_prefixes * - start_code_prefix immediately followed by EOF */ fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n"); else { #if !G1002_RPS || !G1002_IDR_POC_ZERO_BUGFIX InputNALUnit nalu; #endif read(nalu, nalUnit); #if G1002_RPS if(m_iMaxTemporalLayer >= 0 && nalu.m_TemporalID > m_iMaxTemporalLayer) { if(bPreviousPictureDecoded) { bNewPicture = true; bPreviousPictureDecoded = false; } else { bNewPicture = false; } } else { #endif bNewPicture = m_cTDecTop.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay); if (bNewPicture) { bitstreamFile.clear(); /* location points to the current nalunit payload[1] due to the * need for the annexB parser to read three extra bytes. * [1] except for the first NAL unit in the file * (but bNewPicture doesn't happen then) */ bitstreamFile.seekg(location-streamoff(3)); bytestream.reset(); } #if G1002_RPS bPreviousPictureDecoded = true; } #endif } if (bNewPicture || !bitstreamFile) { m_cTDecTop.executeDeblockAndAlf(uiPOC, pcListPic, m_iSkipFrame, m_iPOCLastDisplay); #if G1002_RPS && G1002_IDR_POC_ZERO_BUGFIX if(nalu.m_UnitType == NAL_UNIT_CODED_SLICE_IDR) { xFlushOutput( pcListPic ); } #endif } if( pcListPic ) { if ( m_pchReconFile && !recon_opened ) { if ( m_outputBitDepth == 0 ) m_outputBitDepth = g_uiBitDepth + g_uiBitIncrement; m_cTVideoIOYuvReconFile.open( m_pchReconFile, true, m_outputBitDepth, g_uiBitDepth + g_uiBitIncrement ); // write mode recon_opened = true; } // write reconstuction to file #if G1002_RPS && G1002_IDR_POC_ZERO_BUGFIX if(bNewPicture) { xWriteOutput( pcListPic ); } #else xWriteOutput( pcListPic ); #endif } } #if G1002_RPS xFlushOutput( pcListPic ); #endif // delete buffers m_cTDecTop.deletePicBuffer(); // destroy internal classes xDestroyDecLib(); }
/** - create internal class - initialize internal class - until the end of the bitstream, call decoding function in TDecTop class - delete allocated buffers - destroy internal class . */ Void TAppDecTop::decode() { Int poc; TComList<TComPic*>* pcListPic = NULL; ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary); if (!bitstreamFile) { fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile); exit(EXIT_FAILURE); } InputByteStream bytestream(bitstreamFile); if (!m_outputDecodedSEIMessagesFilename.empty() && m_outputDecodedSEIMessagesFilename!="-") { m_seiMessageFileStream.open(m_outputDecodedSEIMessagesFilename.c_str(), std::ios::out); if (!m_seiMessageFileStream.is_open() || !m_seiMessageFileStream.good()) { fprintf(stderr, "\nUnable to open file `%s' for writing decoded SEI messages\n", m_outputDecodedSEIMessagesFilename.c_str()); exit(EXIT_FAILURE); } } // create & initialize internal classes xCreateDecLib(); xInitDecLib (); m_iPOCLastDisplay += m_iSkipFrame; // set the last displayed POC correctly for skip forward. // main decoder loop Bool openedReconFile = false; // reconstruction file not yet opened. (must be performed after SPS is seen) Bool loopFiltered = false; while (!!bitstreamFile) { /* location serves to work around a design fault in the decoder, whereby * the process of reading a new slice that is the first slice of a new frame * requires the TDecTop::decode() method to be called again with the same * nal unit. */ #if RExt__DECODER_DEBUG_BIT_STATISTICS TComCodingStatistics::TComCodingStatisticsData backupStats(TComCodingStatistics::GetStatistics()); streampos location = bitstreamFile.tellg() - streampos(bytestream.GetNumBufferedBytes()); #else streampos location = bitstreamFile.tellg(); #endif AnnexBStats stats = AnnexBStats(); vector<uint8_t> nalUnit; InputNALUnit nalu; byteStreamNALUnit(bytestream, nalUnit, stats); // call actual decoding function Bool bNewPicture = false; if (nalUnit.empty()) { /* this can happen if the following occur: * - empty input file * - two back-to-back start_code_prefixes * - start_code_prefix immediately followed by EOF */ fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n"); } else { read(nalu, nalUnit); if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu) ) { bNewPicture = false; } else { bNewPicture = m_cTDecTop.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay); if (bNewPicture) { bitstreamFile.clear(); /* location points to the current nalunit payload[1] due to the * need for the annexB parser to read three extra bytes. * [1] except for the first NAL unit in the file * (but bNewPicture doesn't happen then) */ #if RExt__DECODER_DEBUG_BIT_STATISTICS bitstreamFile.seekg(location); bytestream.reset(); TComCodingStatistics::SetStatistics(backupStats); #else bitstreamFile.seekg(location-streamoff(3)); bytestream.reset(); #endif } } } #if FIX_OUTPUT_ORDER_BEHAVIOR if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) && !m_cTDecTop.getFirstSliceInSequence () ) #else if (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS) #endif { if (!loopFiltered || bitstreamFile) { m_cTDecTop.executeLoopFilters(poc, pcListPic); } loopFiltered = (nalu.m_nalUnitType == NAL_UNIT_EOS); #if FIX_OUTPUT_ORDER_BEHAVIOR if (nalu.m_nalUnitType == NAL_UNIT_EOS) { m_cTDecTop.setFirstSliceInSequence(true); } #endif } #if FIX_OUTPUT_ORDER_BEHAVIOR else if ( (bNewPicture || !bitstreamFile || nalu.m_nalUnitType == NAL_UNIT_EOS ) && m_cTDecTop.getFirstSliceInSequence () ) { m_cTDecTop.setFirstSliceInPicture (true); } #endif #if !FIX_WRITING_OUTPUT #if SETTING_NO_OUT_PIC_PRIOR if (bNewPicture && m_cTDecTop.getIsNoOutputPriorPics()) { m_cTDecTop.checkNoOutputPriorPics( pcListPic ); } #endif #endif if( pcListPic ) { if ( m_pchReconFile && !openedReconFile ) { for (UInt channelType = 0; channelType < MAX_NUM_CHANNEL_TYPE; channelType++) { if (m_outputBitDepth[channelType] == 0) m_outputBitDepth[channelType] = g_bitDepth[channelType]; } m_cTVideoIOYuvReconFile.open( m_pchReconFile, true, m_outputBitDepth, m_outputBitDepth, g_bitDepth ); // write mode openedReconFile = true; } #if FIX_WRITING_OUTPUT // write reconstruction to file if( bNewPicture ) { xWriteOutput( pcListPic, nalu.m_temporalId ); } #if SETTING_NO_OUT_PIC_PRIOR if ( (bNewPicture || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_CRA) && m_cTDecTop.getNoOutputPriorPicsFlag() ) { m_cTDecTop.checkNoOutputPriorPics( pcListPic ); m_cTDecTop.setNoOutputPriorPicsFlag (false); } #endif #endif if ( bNewPicture && ( 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_BLA_N_LP || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP ) ) { xFlushOutput( pcListPic ); } if (nalu.m_nalUnitType == NAL_UNIT_EOS) { #if FIX_OUTPUT_EOS xWriteOutput( pcListPic, nalu.m_temporalId ); #if FIX_OUTPUT_ORDER_BEHAVIOR m_cTDecTop.setFirstSliceInPicture (false); #endif #else xFlushOutput( pcListPic ); #endif } // write reconstruction to file -- for additional bumping as defined in C.5.2.3 #if FIX_WRITING_OUTPUT if(!bNewPicture && nalu.m_nalUnitType >= NAL_UNIT_CODED_SLICE_TRAIL_N && nalu.m_nalUnitType <= NAL_UNIT_RESERVED_VCL31) #else if(bNewPicture) #endif { xWriteOutput( pcListPic, nalu.m_temporalId ); } } } xFlushOutput( pcListPic ); // delete buffers m_cTDecTop.deletePicBuffer(); // destroy internal classes xDestroyDecLib(); }
/** - create internal class - initialize internal class - until the end of the bitstream, call decoding function in TDecTop class - delete allocated buffers - destroy internal class . */ Void TAppDecTop::decode() { Int poc; TComList<TComPic*>* pcListPic = NULL; ifstream bitstreamFile(m_pchBitstreamFile, ifstream::in | ifstream::binary); if (!bitstreamFile) { fprintf(stderr, "\nfailed to open bitstream file `%s' for reading\n", m_pchBitstreamFile); exit(EXIT_FAILURE); } InputByteStream bytestream(bitstreamFile); // create & initialize internal classes xCreateDecLib(); xInitDecLib (); m_iPOCLastDisplay += m_iSkipFrame; // set the last displayed POC correctly for skip forward. // main decoder loop Bool recon_opened = false; // reconstruction file not yet opened. (must be performed after SPS is seen) while (!!bitstreamFile) { /* location serves to work around a design fault in the decoder, whereby * the process of reading a new slice that is the first slice of a new frame * requires the TDecTop::decode() method to be called again with the same * nal unit. */ streampos location = bitstreamFile.tellg(); AnnexBStats stats = AnnexBStats(); Bool bPreviousPictureDecoded = false; vector<uint8_t> nalUnit; InputNALUnit nalu; byteStreamNALUnit(bytestream, nalUnit, stats); // call actual decoding function Bool bNewPicture = false; if (nalUnit.empty()) { /* this can happen if the following occur: * - empty input file * - two back-to-back start_code_prefixes * - start_code_prefix immediately followed by EOF */ fprintf(stderr, "Warning: Attempt to decode an empty NAL unit\n"); } else { read(nalu, nalUnit); if( (m_iMaxTemporalLayer >= 0 && nalu.m_temporalId > m_iMaxTemporalLayer) || !isNaluWithinTargetDecLayerIdSet(&nalu) ) { if(bPreviousPictureDecoded) { bNewPicture = true; bPreviousPictureDecoded = false; } else { bNewPicture = false; } } else { bNewPicture = m_cTDecTop.decode(nalu, m_iSkipFrame, m_iPOCLastDisplay); if (bNewPicture) { bitstreamFile.clear(); /* location points to the current nalunit payload[1] due to the * need for the annexB parser to read three extra bytes. * [1] except for the first NAL unit in the file * (but bNewPicture doesn't happen then) */ bitstreamFile.seekg(location-streamoff(3)); bytestream.reset(); } bPreviousPictureDecoded = true; } } if (bNewPicture || !bitstreamFile) { m_cTDecTop.executeLoopFilters(poc, pcListPic); } if( pcListPic ) { if ( m_pchReconFile && !recon_opened ) { if (!m_outputBitDepthY) { m_outputBitDepthY = g_bitDepthY; } if (!m_outputBitDepthC) { m_outputBitDepthC = g_bitDepthC; } m_cTVideoIOYuvReconFile.open( m_pchReconFile, true, m_outputBitDepthY, m_outputBitDepthC, g_bitDepthY, g_bitDepthC ); // write mode recon_opened = true; } if ( bNewPicture && ( 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_BLA_N_LP || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL || nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP ) ) { xFlushOutput( pcListPic ); } // write reconstruction to file if(bNewPicture) { xWriteOutput( pcListPic, nalu.m_temporalId ); } } } xFlushOutput( pcListPic ); // delete buffers m_cTDecTop.deletePicBuffer(); // destroy internal classes xDestroyDecLib(); }