Void TDecTop::deletePicBuffer ( ) { TComList<TComPic*>::iterator iterPic = m_cListPic.begin(); Int iSize = Int( m_cListPic.size() ); for (Int i = 0; i < iSize; i++ ) { TComPic* pcPic = *(iterPic++); pcPic->destroy(); delete pcPic; pcPic = NULL; } // destroy ALF temporary buffers m_cAdaptiveLoopFilter.destroy(); #if MTK_SAO m_cSAO.destroy(); #endif m_cLoopFilter. destroy(); // destroy ROM destroyROM(); }
void DPB::computeRPS(int curPoc, bool isRAP, TComReferencePictureSet * rps, unsigned int maxDecPicBuffer) { unsigned int poci = 0, numNeg = 0, numPos = 0; TComPic* iterPic = m_picList.first(); while (iterPic && (poci < maxDecPicBuffer - 1)) { if ((iterPic->getPOC() != curPoc) && (iterPic->getSlice()->isReferenced())) { rps->m_POC[poci] = iterPic->getPOC(); rps->m_deltaPOC[poci] = rps->m_POC[poci] - curPoc; (rps->m_deltaPOC[poci] < 0) ? numNeg++ : numPos++; rps->m_used[poci] = !isRAP; poci++; } iterPic = iterPic->m_next; } rps->m_numberOfPictures = poci; rps->m_numberOfPositivePictures = numPos; rps->m_numberOfNegativePictures = numNeg; rps->m_numberOfLongtermPictures = 0; rps->m_interRPSPrediction = false; // To be changed later when needed rps->sortDeltaPOC(); }
DPB::~DPB() { while (!m_picList.empty()) { TComPic* pic = m_picList.popFront(); pic->destroy(); delete pic; } }
DPB::~DPB() { while (!m_picList.empty()) { TComPic* pic = m_picList.popFront(); pic->destroy(m_cfg->param.bframes); delete pic; } }
Void TEncTop::deletePicBuffer() { TComList<TComPic*>::iterator iterPic = m_cListPic.begin(); Int iSize = Int( m_cListPic.size() ); for ( Int i = 0; i < iSize; i++ ) { TComPic* pcPic = *(iterPic++); pcPic->destroy(); delete pcPic; pcPic = NULL; } }
Void updatePixel(TComDataCU* pCtu, Pixel** ppPixel) { UInt uiMaxCUWidth = pCtu->getSlice()->getSPS()->getMaxCUWidth(); // max cu width UInt uiMaxCUHeight = pCtu->getSlice()->getSPS()->getMaxCUHeight(); // max cu height // pic TComPic *pcPic = pCtu->getPic(); //TComPicYuv* pcPredYuv = pcPic->getPicYuvPred(); //TComPicYuv* pcResiYuv = pcPic->getPicYuvResi(); TComPicYuv* pcRecoYuv = pcPic->getPicYuvRec(); UInt uiNumValidCopmonent = pcPic->getNumberValidComponents(); for (UInt ch = 0; ch < uiNumValidCopmonent; ch++) { ComponentID cId = ComponentID(ch); // picture description UInt uiStride = pcRecoYuv->getStride(cId); // stride for a certain component UInt uiPicWidth = pcRecoYuv->getWidth(cId); // picture width for a certain component UInt uiPicHeight = pcRecoYuv->getHeight(cId); // picture height for a certain component UInt uiCUPelX = pCtu->getCUPelX() >> (pcRecoYuv->getComponentScaleX(cId)); // x of upper left corner of the cu UInt uiCUPelY = pCtu->getCUPelY() >> (pcRecoYuv->getComponentScaleY(cId));; // y of upper left corner of the UInt uiCBWidth = uiMaxCUWidth >> (pcRecoYuv->getComponentScaleX(cId)); // code block width for a certain component UInt uiCBHeight = uiMaxCUHeight >> (pcRecoYuv->getComponentScaleY(cId)); // code block height for a certain component // rectangle of the code block UInt uiTopX = Clip3((UInt)0, uiPicWidth, uiCUPelX); UInt uiTopY = Clip3((UInt)0, uiPicHeight, uiCUPelY); UInt uiBottomX = Clip3((UInt)0, uiPicWidth, uiCUPelX + uiCBWidth); UInt uiBottomY = Clip3((UInt)0, uiPicHeight, uiCUPelY + uiCBHeight); Pel* pBuffer = pcRecoYuv->getAddr(cId); for (UInt uiY = uiTopY; uiY < uiBottomY; uiY++) { for (UInt uiX = uiTopX; uiX < uiBottomX; uiX++) { UInt uiOrgX, uiOrgY; uiOrgX = g_auiRsmpldToOrg[cId][0][uiX]; uiOrgY = g_auiRsmpldToOrg[cId][1][uiY]; Pixel* pPixel = ppPixel[cId] + getSerialIndex(uiOrgX, uiOrgY, uiPicWidth); pPixel->m_bIsRec = true; pPixel->m_uiReco = pBuffer[uiY*uiStride + uiX]; } } } }
Int TComSlice::getActualRefNumber( TComList<TComPic*>& rcListPic ) { Int iActualNumOfReference = 0; TComList<TComPic*>::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end() ) { TComPic* rpcPic = *(iterPic); if ( rpcPic->getSlice( 0 )->isReferenced() && rpcPic->getReconMark() ) { iActualNumOfReference++; } iterPic++; } return iActualNumOfReference; }
TComPic* TComSlice::xGetRefPic(PicList& picList, int poc) { TComPic *iterPic = picList.first(); TComPic* pic = NULL; while (iterPic) { pic = iterPic; if (pic->getPOC() == poc) { break; } iterPic = iterPic->m_next; } return pic; }
/** Function for marking reference pictures with higher temporal layer IDs as not used if the current picture is a temporal layer switching point. * \param rcListPic List of picture buffers * Both the encoder and decoder call this function to mark reference pictures with temporal layer ID higher than current picture's temporal layer ID as not used. */ Void TComSlice::decodingTLayerSwitchingMarking( TComList<TComPic*>& rcListPic ) { TComPic* rpcPic; if ( m_bTLayerSwitchingFlag ) { // mark all pictures of temporal layer > m_uiTLyr as not used for reference TComList<TComPic*>::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end() ) { rpcPic = *(iterPic); if ( rpcPic->getTLayer() > m_uiTLayer ) { rpcPic->getSlice( 0 )->setReferenced( false ); } iterPic++; } } }
Void TDecTop::checkNoOutputPriorPics (TComList<TComPic*>* pcListPic) { if (!pcListPic || !m_isNoOutputPriorPics) { return; } TComList<TComPic*>::iterator iterPic = pcListPic->begin(); while (iterPic != pcListPic->end()) { TComPic* pcPicTmp = *(iterPic++); if (m_lastPOCNoOutputPriorPics != pcPicTmp->getPOC()) { pcPicTmp->setOutputMark(false); } } }
TComPic* TComSlice::xGetLongTermRefPic(PicList& picList, int poc, bool pocHasMsb) { TComPic* iterPic = picList.first(); TComPic* pic = iterPic; TComPic* stPic = pic; int pocCycle = 1 << getSPS()->getBitsForPOC(); if (!pocHasMsb) { poc = poc % pocCycle; } while (iterPic) { pic = iterPic; if (pic && pic->getPOC() != this->getPOC() && pic->getSlice()->isReferenced()) { int picPoc = pic->getPOC(); if (!pocHasMsb) { picPoc = picPoc % pocCycle; } if (poc == picPoc) { if (pic->getIsLongTerm()) { return pic; } else { stPic = pic; } break; } } iterPic = iterPic->m_next; } return stPic; }
/** - Application has picture buffer list with size of GOP + 1 - Picture buffer list acts like as ring buffer - End of the list has the latest picture . \param flush cause encoder to encode a partial GOP \param pcPicYuvOrg original YUV picture \param pcPicYuvTrueOrg \param snrCSC \retval rcListPicYuvRecOut list of reconstruction YUV pictures \retval accessUnitsOut list of output access units \retval iNumEncoded number of encoded pictures */ Void TEncTop::encode( Bool flush, TComPicYuv* pcPicYuvOrg, TComPicYuv* pcPicYuvTrueOrg, const InputColourSpaceConversion snrCSC, TComList<TComPicYuv*>& rcListPicYuvRecOut, std::list<AccessUnit>& accessUnitsOut, Int& iNumEncoded ) { if (pcPicYuvOrg != NULL) { // get original YUV TComPic* pcPicCurr = NULL; xGetNewPicBuffer( pcPicCurr ); pcPicYuvOrg->copyToPic( pcPicCurr->getPicYuvOrg() ); pcPicYuvTrueOrg->copyToPic( pcPicCurr->getPicYuvTrueOrg() ); // compute image characteristics if ( getUseAdaptiveQP() ) { m_cPreanalyzer.xPreanalyze( dynamic_cast<TEncPic*>( pcPicCurr ) ); } } if ((m_iNumPicRcvd == 0) || (!flush && (m_iPOCLast != 0) && (m_iNumPicRcvd != m_iGOPSize) && (m_iGOPSize != 0))) { iNumEncoded = 0; return; } if ( m_RCEnableRateControl ) { m_cRateCtrl.initRCGOP( m_iNumPicRcvd ); } // compress GOP m_cGOPEncoder.compressGOP(m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut, accessUnitsOut, false, false, snrCSC, m_printFrameMSE,&m_cSearch); if ( m_RCEnableRateControl ) { m_cRateCtrl.destroyRCGOP(); } iNumEncoded = m_iNumPicRcvd; m_iNumPicRcvd = 0; m_uiNumAllPicCoded += iNumEncoded; }
// move unreferenced pictures from picList to freeList for recycle void DPB::recycleUnreferenced(PicList& freeList) { TComPic *iterPic = m_picList.first(); while (iterPic) { TComPic *pic = iterPic; iterPic = iterPic->m_next; if (pic->getSlice()->isReferenced() == false && pic->m_countRefEncoders == 0) { pic->m_reconRowCount = 0; // iterator is invalidated by remove, restart scan m_picList.remove(*pic); iterPic = m_picList.first(); freeList.pushBack(*pic); } } }
Void TDecTop::deletePicBuffer ( ) { TComList<TComPic*>::iterator iterPic = m_cListPic.begin(); Int iSize = Int( m_cListPic.size() ); for (Int i = 0; i < iSize; i++ ) { TComPic* pcPic = *(iterPic++); pcPic->destroy(); delete pcPic; pcPic = NULL; } m_cSAO.destroy(); m_cLoopFilter. destroy(); // destroy ROM destroyROM(); }
Void TDecTop::executeLoopFilters(Int& poc, TComList<TComPic*>*& rpcListPic) { if (!m_pcPic) { /* nothing to deblock */ return; } TComPic* pcPic = m_pcPic; // Execute Deblock + Cleanup m_cGopDecoder.filterPicture(pcPic); TComSlice::sortPicList( m_cListPic ); // sorting for application output poc = pcPic->getSlice(m_uiSliceIdx-1)->getPOC(); rpcListPic = &m_cListPic; m_cCuDecoder.destroy(); m_bFirstSliceInPicture = true; return; }
/** Function for mimicking decoder's reference picture buffer management. * \param rcListPic List of picture buffers * \param iGOPSIze Current GOP size * \param iMaxRefPicNum Maximum number of reference pictures allowed * The encoder calls this function to mimic the picture buffer management of the decoder in the function xGetNewPicBuffer. * This will ensure in the encoder that the pictures that does not exist in the decoder will not be used as reference. * TODO: This assumes that the new pics are added at the end of the list. * This needs to be changed for the general case including for the long-term ref pics. * In the future, we should create a single common function for both the encoder and decoder. */ Void TComSlice::decodingMarking( TComList<TComPic*>& rcListPic, Int iGOPSIze, Int& iMaxRefPicNum ) { Int iActualNumOfReference = 0; TComList<TComPic*>::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end() ) { TComPic* rpcPic = *(iterPic); if ( rpcPic->getSlice( 0 )->isReferenced() ) { if ( rpcPic != getPic() ) { iActualNumOfReference++; } } iterPic++; } // TODO: This assumes that the new pics are added at the end of the list // This needs to be changed for the general case including for the long-term ref pics iMaxRefPicNum = max(iMaxRefPicNum, max(max(2, getNumRefIdx(REF_PIC_LIST_0)+1), iGOPSIze/2 + 2 + getNumRefIdx(REF_PIC_LIST_0))); if ( iActualNumOfReference >= iMaxRefPicNum ) { Int iNumToBeReset = iActualNumOfReference - iMaxRefPicNum + 1; iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end() && iNumToBeReset > 0 ) { TComPic* rpcPic = *(iterPic); if ( rpcPic->getSlice( 0 )->isReferenced() ) { rpcPic->getSlice( 0 )->setReferenced( false ); iNumToBeReset--; } iterPic++; } } }
/** Function for marking the reference pictures when an IDR/CRA/CRANT/BLA/BLANT is encountered. * \param pocCRA POC of the CRA/CRANT/BLA/BLANT picture * \param bRefreshPending flag indicating if a deferred decoding refresh is pending * \param picList reference to the reference picture list * This function marks the reference pictures as "unused for reference" in the following conditions. * If the nal_unit_type is IDR/BLA/BLANT, all pictures in the reference picture list * are marked as "unused for reference" * If the nal_unit_type is BLA/BLANT, set the pocCRA to the temporal reference of the current picture. * Otherwise * If the bRefreshPending flag is true (a deferred decoding refresh is pending) and the current * temporal reference is greater than the temporal reference of the latest CRA/CRANT/BLA/BLANT picture (pocCRA), * mark all reference pictures except the latest CRA/CRANT/BLA/BLANT picture as "unused for reference" and set * the bRefreshPending flag to false. * If the nal_unit_type is CRA/CRANT, set the bRefreshPending flag to true and pocCRA to the temporal * reference of the current picture. * Note that the current picture is already placed in the reference list and its marking is not changed. * If the current picture has a nal_ref_idc that is not 0, it will remain marked as "used for reference". */ void DPB::decodingRefreshMarking(int pocCurr, NalUnitType nalUnitType) { if (nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP || nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL || nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP) // IDR or BLA picture { // mark all pictures as not used for reference TComPic* iterPic = m_picList.first(); while (iterPic) { if (iterPic->getPOC() != pocCurr) iterPic->getSlice()->setReferenced(false); iterPic = iterPic->m_next; } if (nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP || nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL || nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP) { m_pocCRA = pocCurr; } } else // CRA or No DR { if (m_bRefreshPending == true && pocCurr > m_pocCRA) // CRA reference marking pending { TComPic* iterPic = m_picList.first(); while (iterPic) { if (iterPic->getPOC() != pocCurr && iterPic->getPOC() != m_pocCRA) iterPic->getSlice()->setReferenced(false); iterPic = iterPic->m_next; } m_bRefreshPending = false; } if (nalUnitType == NAL_UNIT_CODED_SLICE_CRA) // CRA picture found { m_bRefreshPending = true; m_pocCRA = pocCurr; } } }
/** Function for marking the reference pictures when an IDR and CDR is encountered. * \param uiPOCCDR POC of the CDR picture * \param bRefreshPending flag indicating if a deferred decoding refresh is pending * \param rcListPic reference to the reference picture list * This function marks the reference pictures as "unused for reference" in the following conditions. * If the nal_unit_type is IDR all pictures in the reference picture list * is marked as "unused for reference" * Otherwise do for the CDR case (non CDR case has no effect since both if conditions below will not be true) * If the bRefreshPending flag is true (a deferred decoding refresh is pending) and the current * temporal reference is greater than the temporal reference of the latest CDR picture (uiPOCCDR), * mark all reference pictures except the latest CDR picture as "unused for reference" and set * the bRefreshPending flag to false. * If the nal_unit_type is CDR, set the bRefreshPending flag to true and iPOCCDR to the temporal * reference of the current picture. * Note that the current picture is already placed in the reference list and its marking is not changed. * If the current picture has a nal_ref_idc that is not 0, it will remain marked as "used for reference". */ Void TComSlice::decodingRefreshMarking(UInt& uiPOCCDR, Bool& bRefreshPending, TComList<TComPic*>& rcListPic) { TComPic* rpcPic; UInt uiPOCCurr = getPOC(); if (getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR) // IDR { // mark all pictures as not used for reference TComList<TComPic*>::iterator iterPic = rcListPic.begin(); while (iterPic != rcListPic.end()) { rpcPic = *(iterPic); rpcPic->setCurrSliceIdx(0); if (rpcPic->getPOC() != uiPOCCurr) rpcPic->getSlice(0)->setReferenced(false); iterPic++; } } else // CDR or No DR { if (bRefreshPending==true && uiPOCCurr > uiPOCCDR) // CDR reference marking pending { TComList<TComPic*>::iterator iterPic = rcListPic.begin(); while (iterPic != rcListPic.end()) { rpcPic = *(iterPic); if (rpcPic->getPOC() != uiPOCCurr && rpcPic->getPOC() != uiPOCCDR) rpcPic->getSlice(0)->setReferenced(false); iterPic++; } bRefreshPending = false; } if (getNalUnitType() == NAL_UNIT_CODED_SLICE_CDR) // CDR picture found { bRefreshPending = true; uiPOCCDR = uiPOCCurr; } } }
Void TComSlice::sortPicList (TComList<TComPic*>& rcListPic) { TComPic* pcPicExtract; TComPic* pcPicInsert; TComList<TComPic*>::iterator iterPicExtract; TComList<TComPic*>::iterator iterPicExtract_1; TComList<TComPic*>::iterator iterPicInsert; for (Int i = 1; i < (Int)(rcListPic.size()); i++) { iterPicExtract = rcListPic.begin(); for (Int j = 0; j < i; j++) iterPicExtract++; pcPicExtract = *(iterPicExtract); pcPicExtract->setCurrSliceIdx(0); iterPicInsert = rcListPic.begin(); while (iterPicInsert != iterPicExtract) { pcPicInsert = *(iterPicInsert); pcPicInsert->setCurrSliceIdx(0); if (pcPicInsert->getPOC() >= pcPicExtract->getPOC()) { break; } iterPicInsert++; } iterPicExtract_1 = iterPicExtract; iterPicExtract_1++; // swap iterPicExtract and iterPicInsert, iterPicExtract = curr. / iterPicInsert = insertion position rcListPic.insert (iterPicInsert, iterPicExtract, iterPicExtract_1); rcListPic.erase (iterPicExtract); } }
Void derivePGRPLT(TComDataCU* pcCtu) { TComPic* pcPic = pcCtu->getPic(); TComPicYuv* pcOrgYuv = pcPic->getPicYuvOrg(); UInt uiNumValidComponents = pcOrgYuv->getNumberValidComponents(); UInt uiMaxCUWidth = pcCtu->getSlice()->getSPS()->getMaxCUWidth(); UInt uiMaxCUHeight = pcCtu->getSlice()->getSPS()->getMaxCUWidth(); for (UInt ch = 0; ch < uiNumValidComponents; ch++) { ComponentID cId = ComponentID(ch); UInt uiPicWidth = pcOrgYuv->getWidth(cId); UInt uiPicHeight = pcOrgYuv->getHeight(cId); UInt uiStride = pcOrgYuv->getStride(cId); UInt uiCUPelX = pcCtu->getCUPelX() >> (pcOrgYuv->getComponentScaleX(cId)); // x of upper left corner of the cu UInt uiCUPelY = pcCtu->getCUPelY() >> (pcOrgYuv->getComponentScaleY(cId));; // y of upper left corner of the UInt uiCBWidth = uiMaxCUWidth >> (pcOrgYuv->getComponentScaleX(cId)); UInt uiCBHeight = uiMaxCUHeight >> (pcOrgYuv->getComponentScaleY(cId)); uiCBWidth = Clip3((UInt)0, uiPicWidth - uiCUPelX, uiCBWidth); uiCBHeight = Clip3((UInt)0, uiPicHeight - uiCUPelY, uiCBHeight); // statistics PelCount* pPixelCount[256]; for (int i = 0; i < 256; i++) pPixelCount[i] = new PelCount(i); Pel* pOrg = pcOrgYuv->getAddr(cId, pcCtu->getCtuRsAddr()); for (UInt uiY = 0; uiY < uiCBHeight; uiY++) { for (UInt uiX = 0; uiX < uiCBWidth; uiX++) { pPixelCount[pOrg[uiX]]->m_uiCount++; } pOrg += uiStride; } // sort sort(pPixelCount, pPixelCount + 256, cmpPelCount); g_ppCTUPalette[cId].m_uiSize = 0; // insert entry for (int i = 0, k = 0; k < 4; i++) { bool bDuplicate = false; for (int j = 0; j < 4; j++) { // duplicate if (g_ppCTUPalette[cId].m_pEntry[i] == g_ppPalette[cId].m_pEntry[j]) { bDuplicate = true; break; } } if (!bDuplicate) { g_ppCTUPalette[cId].m_pEntry[k++] = pPixelCount[i]->m_uiVal; g_ppCTUPalette[cId].m_uiSize++; } } for (int i = 0; i < 256; i++) delete pPixelCount[i]; } }
/** \param pcListPic list of pictures to be written to file \todo DYN_REF_FREE should be revised */ Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic, Int viewDepthId ) { if(!pcListPic) { return; } TComList<TComPic*>::iterator iterPic = pcListPic->begin(); iterPic = pcListPic->begin(); while (iterPic != pcListPic->end()) { TComPic* pcPic = *(iterPic); TComSPS *sps = pcPic->getSlice(0)->getSPS(); if ( pcPic->getOutputMark() ) { // write to file if ( m_pchReconFile ) { m_tVideoIOYuvReconFile[viewDepthId]->write( pcPic->getPicYuvRec(), sps->getPicCropLeftOffset(), sps->getPicCropRightOffset(), sps->getPicCropTopOffset(), sps->getPicCropBottomOffset() ); } // update POC of display order m_pocLastDisplay[viewDepthId] = pcPic->getPOC(); // erase non-referenced picture in the reference picture list after display if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true ) { #if !DYN_REF_FREE pcPic->setReconMark(false); // mark it should be extended later pcPic->getPicYuvRec()->setBorderExtension( false ); #else pcPic->destroy(); pcListPic->erase( iterPic ); iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised! continue; #endif } pcPic->setOutputMark(false); } iterPic++; } pcListPic->clear(); m_pocLastDisplay[viewDepthId] = -MAX_INT; }
Void matchTemplate(TComDataCU*& rpcTempCU, Pixel** ppPixel) { // template matching UInt uiCUPelX = rpcTempCU->getCUPelX(); // x of upper left corner of the cu UInt uiCUPelY = rpcTempCU->getCUPelY(); // y of upper left corner of the cu UInt uiMaxCUWidth = rpcTempCU->getSlice()->getSPS()->getMaxCUWidth(); // max cu width UInt uiMaxCUHeight = rpcTempCU->getSlice()->getSPS()->getMaxCUHeight(); // max cu height // pic TComPic* pcPic = rpcTempCU->getPic(); TComPicYuv* pcPredYuv = pcPic->getPicYuvPred(); TComPicYuv* pcResiYuv = pcPic->getPicYuvResi(); UInt uiNumValidCopmonent = pcPic->getNumberValidComponents(); vector<PixelTemplate> vInsertList; for (UInt ch = 0; ch < uiNumValidCopmonent; ch++) { int all = 0; int average = 0; int afind = 0; int maxfind = 0, minfind = INT_MAX; int ax = 0, ay = 0; int adiff = 0; ComponentID cId = ComponentID(ch); // picture description UInt uiStride = pcPredYuv->getStride(cId); // stride for a certain component UInt uiPicWidth = pcPredYuv->getWidth(cId); // picture width for a certain component UInt uiPicHeight = pcPredYuv->getHeight(cId); // picture height for a certain component UInt uiCBWidth = uiMaxCUWidth >> (pcPredYuv->getComponentScaleX(cId)); // code block width for a certain component UInt uiCBHeight = uiMaxCUHeight >> (pcPredYuv->getComponentScaleY(cId)); // code block height for a certain component // rectangle of the code block UInt uiTopX = Clip3((UInt)0, uiPicWidth, uiCUPelX); UInt uiTopY = Clip3((UInt)0, uiPicHeight, uiCUPelY); UInt uiBottomX = Clip3((UInt)0, uiPicWidth, uiCUPelX + uiCBWidth); UInt uiBottomY = Clip3((UInt)0, uiPicHeight, uiCUPelY + uiCBHeight); for (UInt uiY = uiTopY; uiY < uiBottomY; uiY++) { for (UInt uiX = uiTopX; uiX < uiBottomX; uiX++) { UInt uiOrgX, uiOrgY; uiOrgX = g_auiRsmpldToOrg[cId][0][uiX]; uiOrgY = g_auiRsmpldToOrg[cId][1][uiY]; // template match UInt uiHashValue1, uiHashValue2; // get hash values getHashValue(uiOrgX, uiOrgY, uiPicWidth, ppPixel[cId],uiHashValue1,uiHashValue2); Pixel* pCurPixel = ppPixel[cId] + getSerialIndex(uiOrgX, uiOrgY, uiPicWidth); //pCurPixel->m_uiHashValue = uiHashValue1; assert(uiHashValue1 >= 0 && uiHashValue1 < MAX_PT_NUM); // lookup table PixelTemplate* pLookupTable = g_pLookupTable[cId][uiHashValue1]; // number of available template pixels UInt uiNumTemplate = getNumTemplate(uiOrgX, uiOrgY, uiPicWidth, ppPixel[cId]); // if uiNumTemplate < 1, predict target with default value and do not insert template if (uiNumTemplate < 1) { UInt uiIdx = uiY * uiStride + uiX; pcPredYuv->getAddr(cId)[uiIdx] = pCurPixel->m_uiPred; pcResiYuv->getAddr(cId)[uiIdx] = pCurPixel->m_iResi = pCurPixel->m_uiOrg - pCurPixel->m_uiPred; continue; } // if lookuptable is empty, predict target with default value and insert template if (pLookupTable == NULL) { // vInsertList.push_back(PixelTemplate(uiOrgX, uiOrgY, uiHashValue1,uiHashValue2,uiNumTemplate,NEW)); UInt uiIdx = uiY*uiStride + uiX; pcPredYuv->getAddr(cId)[uiIdx] = pCurPixel->m_uiPred; pcResiYuv->getAddr(cId)[uiIdx] = pCurPixel->m_iResi = pCurPixel->m_uiOrg - pCurPixel->m_uiPred; continue; } MatchMetric mmBestMetric; UInt uiListLength = 0; PixelTemplate* pBestMatch = NULL; PixelTemplate* pPixelTemplate = pLookupTable; #if PGR_DEBUG int length = 0; int a = 0; int find = 0; int fx = 0, fy = 0; int diff = 0; #endif UInt uiRemoved = 0; // find best matched template while (pPixelTemplate != NULL) { UInt uiCX = pPixelTemplate->m_PX; UInt uiCY = pPixelTemplate->m_PY; MatchMetric mmTmp; #if PGR_DEBUG length++; #endif tryMatch(uiOrgX, uiOrgY, uiCX, uiCY, mmTmp, uiPicWidth, ppPixel[cId]); // set best matched template if (mmTmp.m_uiAbsDiff < mmBestMetric.m_uiAbsDiff || (mmTmp.m_uiAbsDiff == mmBestMetric.m_uiAbsDiff)&&(mmTmp.m_uiNumValidPoints > mmBestMetric.m_uiNumValidPoints)) { mmBestMetric = mmTmp; pBestMatch = pPixelTemplate; find = length; fx = abs(int(uiOrgX - uiCX)) / 64; fy = abs(int(uiOrgY - uiCY)) / 64; diff = mmTmp.m_uiAbsDiff; } // replace useless template if (mmTmp.m_uiAbsDiff < INSERT_LIMIT && (uiNumTemplate > pPixelTemplate->m_uiNumTemplate || uiNumTemplate == 21) && pPixelTemplate->m_uiState != TO_BE_REMOVED) { pPixelTemplate->m_uiState = TO_BE_REMOVED; uiRemoved++; } pPixelTemplate = pPixelTemplate->m_pptNext; } // predict target with best matched candidate if (pBestMatch != NULL) { UInt uiCX = pBestMatch->m_PX; UInt uiCY = pBestMatch->m_PY; if ((ppPixel[cId] + getSerialIndex(uiCX, uiCY, uiPicWidth))->m_bIsRec) { pCurPixel->m_mmMatch = mmBestMetric; pBestMatch->m_uiNumUsed++; Pixel* pRefPixel = ppPixel[cId] + getSerialIndex(mmBestMetric.m_uiX, mmBestMetric.m_uiY, uiPicWidth); pCurPixel->m_uiPred = pRefPixel->m_uiReco; // prediction pCurPixel->m_iResi = pCurPixel->m_uiOrg - pCurPixel->m_uiPred; // residue } } // insert new template if (mmBestMetric.m_uiAbsDiff > INSERT_LIMIT) vInsertList.push_back(PixelTemplate(uiOrgX, uiOrgY, uiHashValue1,uiHashValue2,uiNumTemplate,NEW)); // replace old template if(uiNumTemplate < 21 && uiRemoved>0 || uiNumTemplate == 21 && uiRemoved > 1) vInsertList.push_back(PixelTemplate(uiOrgX, uiOrgY, uiHashValue1, uiHashValue2, uiNumTemplate, DISPLACE)); UInt uiIdx = uiY*uiStride + uiX; pcPredYuv->getAddr(cId)[uiIdx] = pCurPixel->m_uiPred; pcResiYuv->getAddr(cId)[uiIdx] = pCurPixel->m_iResi = pCurPixel->m_uiOrg - pCurPixel->m_uiPred; #if PGR_DEBUG all += length; afind += find; ax += fx; ay += fy; adiff += diff; minfind = min(minfind, find); maxfind = max(maxfind, find); #endif }// end for x }// end for y //fc.close(); #if PGR_DEBUG cout <<"search:" <<all / 4096 << endl; cout << "find:" << afind / 4096 << endl; cout << "max:" << maxfind << "\t" << "min:" << minfind << endl; cout << "x:" << ax/4096 << "\t" << "y:" << ay/4096 << endl; cout << "diff:" << adiff / 4096 << endl; #endif // insert template for (vector<PixelTemplate>::iterator it = vInsertList.begin(); it != vInsertList.end(); it++) { UInt uiHashValue = it->m_uiHashValue1; if (it->m_uiState == DISPLACE) { PixelTemplate* p = g_pLookupTable[cId][uiHashValue]; PixelTemplate* pre = NULL; while (p != NULL) { if (p->m_uiState == TO_BE_REMOVED) { PixelTemplate* q = p; if (pre == NULL) { g_pLookupTable[cId][uiHashValue] = p = p->m_pptNext; } else { pre->m_pptNext = p = p->m_pptNext; } delete q; q = NULL; } else { pre = p; p = p->m_pptNext; } } } it->m_uiState = NEW; PixelTemplate* pNewTemplate = new PixelTemplate(*it); pNewTemplate->m_pptNext = g_pLookupTable[cId][uiHashValue]; g_pLookupTable[cId][uiHashValue] = pNewTemplate; } vInsertList.clear(); }// end for ch }
/** Function for applying picture marking based on the Reference Picture Set in pReferencePictureSet */ void DPB::applyReferencePictureSet(TComReferencePictureSet *rps, int curPoc) { TComPic* outPic; int i, isReference; // loop through all pictures in the reference picture buffer TComPic* iterPic = m_picList.first(); while (iterPic) { outPic = iterPic; iterPic = iterPic->m_next; if (!outPic->getSlice()->isReferenced()) { continue; } isReference = 0; // loop through all pictures in the Reference Picture Set // to see if the picture should be kept as reference picture for (i = 0; i < rps->getNumberOfPositivePictures() + rps->getNumberOfNegativePictures(); i++) { if (!outPic->getIsLongTerm() && outPic->getPicSym()->getSlice()->getPOC() == curPoc + rps->getDeltaPOC(i)) { isReference = 1; outPic->setUsedByCurr(rps->getUsed(i) == 1); outPic->setIsLongTerm(0); } } for (; i < rps->getNumberOfPictures(); i++) { if (rps->getCheckLTMSBPresent(i) == true) { if (outPic->getIsLongTerm() && (outPic->getPicSym()->getSlice()->getPOC()) == rps->getPOC(i)) { isReference = 1; outPic->setUsedByCurr(rps->getUsed(i) == 1); } } else { if (outPic->getIsLongTerm() && (outPic->getPicSym()->getSlice()->getPOC() % (1 << outPic->getPicSym()->getSlice()->getSPS()->getBitsForPOC())) == rps->getPOC(i) % (1 << outPic->getPicSym()->getSlice()->getSPS()->getBitsForPOC())) { isReference = 1; outPic->setUsedByCurr(rps->getUsed(i) == 1); } } } // mark the picture as "unused for reference" if it is not in // the Reference Picture Set if (outPic->getPicSym()->getSlice()->getPOC() != curPoc && isReference == 0) { outPic->getSlice()->setReferenced(false); outPic->setUsedByCurr(0); outPic->setIsLongTerm(0); } // TODO: Do we require this check here // check that pictures of higher or equal temporal layer are not in the RPS if the current picture is a TSA picture /*if (this->getNalUnitType() == NAL_UNIT_CODED_SLICE_TLA_R || this->getNalUnitType() == NAL_UNIT_CODED_SLICE_TSA_N) { assert(outPic->getSlice()->isReferenced() == 0); }*/ } }
/** \param pcListPic list of pictures to be written to file \todo DYN_REF_FREE should be revised */ Void TAppDecTop::xFlushOutput( TComList<TComPic*>* pcListPic ) { if(!pcListPic || pcListPic->empty()) { return; } TComList<TComPic*>::iterator iterPic = pcListPic->begin(); iterPic = pcListPic->begin(); TComPic* pcPic = *(iterPic); if (pcPic->isField()) //Field Decoding { TComList<TComPic*>::iterator endPic = pcListPic->end(); endPic--; TComPic *pcPicTop, *pcPicBottom = NULL; while (iterPic != endPic) { pcPicTop = *(iterPic); iterPic++; pcPicBottom = *(iterPic); if ( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() && !(pcPicTop->getPOC()%2) && (pcPicBottom->getPOC() == pcPicTop->getPOC()+1) ) { // write to file if ( m_pchReconFile ) { const Window &conf = pcPicTop->getConformanceWindow(); const Window &defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window(); const Bool isTff = pcPicTop->isTopField(); m_cTVideoIOYuvReconFile.write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(), m_outputColourSpaceConvert, conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(), conf.getWindowRightOffset() + defDisp.getWindowRightOffset(), conf.getWindowTopOffset() + defDisp.getWindowTopOffset(), conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, isTff ); } // update POC of display order m_iPOCLastDisplay = pcPicBottom->getPOC(); // erase non-referenced picture in the reference picture list after display if ( !pcPicTop->getSlice(0)->isReferenced() && pcPicTop->getReconMark() == true ) { #if !DYN_REF_FREE pcPicTop->setReconMark(false); // mark it should be extended later pcPicTop->getPicYuvRec()->setBorderExtension( false ); #else pcPicTop->destroy(); pcListPic->erase( iterPic ); iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised! continue; #endif } if ( !pcPicBottom->getSlice(0)->isReferenced() && pcPicBottom->getReconMark() == true ) { #if !DYN_REF_FREE pcPicBottom->setReconMark(false); // mark it should be extended later pcPicBottom->getPicYuvRec()->setBorderExtension( false ); #else pcPicBottom->destroy(); pcListPic->erase( iterPic ); iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised! continue; #endif } pcPicTop->setOutputMark(false); pcPicBottom->setOutputMark(false); #if !DYN_REF_FREE if(pcPicTop) { pcPicTop->destroy(); delete pcPicTop; pcPicTop = NULL; } #endif } } if(pcPicBottom) { pcPicBottom->destroy(); delete pcPicBottom; pcPicBottom = NULL; } } else //Frame decoding { while (iterPic != pcListPic->end()) { pcPic = *(iterPic); if ( pcPic->getOutputMark() ) { // write to file if ( m_pchReconFile ) { const Window &conf = pcPic->getConformanceWindow(); const Window &defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window(); m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(), m_outputColourSpaceConvert, conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(), conf.getWindowRightOffset() + defDisp.getWindowRightOffset(), conf.getWindowTopOffset() + defDisp.getWindowTopOffset(), conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset() ); } // update POC of display order m_iPOCLastDisplay = pcPic->getPOC(); // erase non-referenced picture in the reference picture list after display if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true ) { #if !DYN_REF_FREE pcPic->setReconMark(false); // mark it should be extended later pcPic->getPicYuvRec()->setBorderExtension( false ); #else pcPic->destroy(); pcListPic->erase( iterPic ); iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised! continue; #endif } pcPic->setOutputMark(false); } #if !DYN_REF_FREE if(pcPic != NULL) { pcPic->destroy(); delete pcPic; pcPic = NULL; } #endif iterPic++; } } pcListPic->clear(); m_iPOCLastDisplay = -MAX_INT; }
/** \param pcListPic list of pictures to be written to file \todo DYN_REF_FREE should be revised */ Void TAppDecTop::xWriteOutput( TComList<TComPic*>* pcListPic, UInt tId ) { if (pcListPic->empty()) { return; } TComList<TComPic*>::iterator iterPic = pcListPic->begin(); Int numPicsNotYetDisplayed = 0; Int dpbFullness = 0; TComSPS* activeSPS = m_cTDecTop.getActiveSPS(); UInt numReorderPicsHighestTid; UInt maxDecPicBufferingHighestTid; UInt maxNrSublayers = activeSPS->getMaxTLayers(); if(m_iMaxTemporalLayer == -1 || m_iMaxTemporalLayer >= maxNrSublayers) { numReorderPicsHighestTid = activeSPS->getNumReorderPics(maxNrSublayers-1); maxDecPicBufferingHighestTid = activeSPS->getMaxDecPicBuffering(maxNrSublayers-1); } else { numReorderPicsHighestTid = activeSPS->getNumReorderPics(m_iMaxTemporalLayer); maxDecPicBufferingHighestTid = activeSPS->getMaxDecPicBuffering(m_iMaxTemporalLayer); } while (iterPic != pcListPic->end()) { TComPic* pcPic = *(iterPic); if(pcPic->getOutputMark() && pcPic->getPOC() > m_iPOCLastDisplay) { numPicsNotYetDisplayed++; dpbFullness++; } else if(pcPic->getSlice( 0 )->isReferenced()) { dpbFullness++; } iterPic++; } iterPic = pcListPic->begin(); if (numPicsNotYetDisplayed>2) { iterPic++; } TComPic* pcPic = *(iterPic); if (numPicsNotYetDisplayed>2 && pcPic->isField()) //Field Decoding { TComList<TComPic*>::iterator endPic = pcListPic->end(); endPic--; iterPic = pcListPic->begin(); while (iterPic != endPic) { TComPic* pcPicTop = *(iterPic); iterPic++; TComPic* pcPicBottom = *(iterPic); if ( pcPicTop->getOutputMark() && pcPicBottom->getOutputMark() && (numPicsNotYetDisplayed > numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid) && (!(pcPicTop->getPOC()%2) && pcPicBottom->getPOC() == pcPicTop->getPOC()+1) && (pcPicTop->getPOC() == m_iPOCLastDisplay+1 || m_iPOCLastDisplay < 0)) { // write to file numPicsNotYetDisplayed = numPicsNotYetDisplayed-2; if ( m_pchReconFile ) { const Window &conf = pcPicTop->getConformanceWindow(); const Window &defDisp = m_respectDefDispWindow ? pcPicTop->getDefDisplayWindow() : Window(); const Bool isTff = pcPicTop->isTopField(); Bool display = true; if( m_decodedNoDisplaySEIEnabled ) { SEIMessages noDisplay = getSeisByType(pcPic->getSEIs(), SEI::NO_DISPLAY ); const SEINoDisplay *nd = ( noDisplay.size() > 0 ) ? (SEINoDisplay*) *(noDisplay.begin()) : NULL; if( (nd != NULL) && nd->m_noDisplay ) { display = false; } } if (display) { m_cTVideoIOYuvReconFile.write( pcPicTop->getPicYuvRec(), pcPicBottom->getPicYuvRec(), m_outputColourSpaceConvert, conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(), conf.getWindowRightOffset() + defDisp.getWindowRightOffset(), conf.getWindowTopOffset() + defDisp.getWindowTopOffset(), conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset(), NUM_CHROMA_FORMAT, isTff ); } } // update POC of display order m_iPOCLastDisplay = pcPicBottom->getPOC(); // erase non-referenced picture in the reference picture list after display if ( !pcPicTop->getSlice(0)->isReferenced() && pcPicTop->getReconMark() == true ) { #if !DYN_REF_FREE pcPicTop->setReconMark(false); // mark it should be extended later pcPicTop->getPicYuvRec()->setBorderExtension( false ); #else pcPicTop->destroy(); pcListPic->erase( iterPic ); iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised! continue; #endif } if ( !pcPicBottom->getSlice(0)->isReferenced() && pcPicBottom->getReconMark() == true ) { #if !DYN_REF_FREE pcPicBottom->setReconMark(false); // mark it should be extended later pcPicBottom->getPicYuvRec()->setBorderExtension( false ); #else pcPicBottom->destroy(); pcListPic->erase( iterPic ); iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised! continue; #endif } pcPicTop->setOutputMark(false); pcPicBottom->setOutputMark(false); } } } else if (!pcPic->isField()) //Frame Decoding { iterPic = pcListPic->begin(); while (iterPic != pcListPic->end()) { pcPic = *(iterPic); if(pcPic->getOutputMark() && pcPic->getPOC() > m_iPOCLastDisplay && (numPicsNotYetDisplayed > numReorderPicsHighestTid || dpbFullness > maxDecPicBufferingHighestTid)) { // write to file numPicsNotYetDisplayed--; if(pcPic->getSlice(0)->isReferenced() == false) { dpbFullness--; } if ( m_pchReconFile ) { const Window &conf = pcPic->getConformanceWindow(); const Window &defDisp = m_respectDefDispWindow ? pcPic->getDefDisplayWindow() : Window(); m_cTVideoIOYuvReconFile.write( pcPic->getPicYuvRec(), m_outputColourSpaceConvert, conf.getWindowLeftOffset() + defDisp.getWindowLeftOffset(), conf.getWindowRightOffset() + defDisp.getWindowRightOffset(), conf.getWindowTopOffset() + defDisp.getWindowTopOffset(), conf.getWindowBottomOffset() + defDisp.getWindowBottomOffset() ); } // update POC of display order m_iPOCLastDisplay = pcPic->getPOC(); // erase non-referenced picture in the reference picture list after display if ( !pcPic->getSlice(0)->isReferenced() && pcPic->getReconMark() == true ) { #if !DYN_REF_FREE pcPic->setReconMark(false); // mark it should be extended later pcPic->getPicYuvRec()->setBorderExtension( false ); #else pcPic->destroy(); pcListPic->erase( iterPic ); iterPic = pcListPic->begin(); // to the beginning, non-efficient way, have to be revised! continue; #endif } pcPic->setOutputMark(false); } iterPic++; } } }
Void TEncTop::encode(Bool flush, TComPicYuv* pcPicYuvOrg, TComPicYuv* pcPicYuvTrueOrg, const InputColourSpaceConversion snrCSC, TComList<TComPicYuv*>& rcListPicYuvRecOut, std::list<AccessUnit>& accessUnitsOut, Int& iNumEncoded, Bool isTff) { iNumEncoded = 0; for (Int fieldNum=0; fieldNum<2; fieldNum++) { if (pcPicYuvOrg) { /* -- field initialization -- */ const Bool isTopField=isTff==(fieldNum==0); TComPic *pcField; xGetNewPicBuffer( pcField ); pcField->setReconMark (false); // where is this normally? if (fieldNum==1) // where is this normally? { TComPicYuv* rpcPicYuvRec; // org. buffer if ( rcListPicYuvRecOut.size() >= (UInt)m_iGOPSize+1 ) // need to maintain field 0 in list of RecOuts while processing field 1. Hence +1 on m_iGOPSize. { rpcPicYuvRec = rcListPicYuvRecOut.popFront(); } else { rpcPicYuvRec = new TComPicYuv; rpcPicYuvRec->create( m_iSourceWidth, m_iSourceHeight, m_chromaFormatIDC, m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, true); } rcListPicYuvRecOut.pushBack( rpcPicYuvRec ); } pcField->getSlice(0)->setPOC( m_iPOCLast ); // superfluous? pcField->getPicYuvRec()->setBorderExtension(false);// where is this normally? pcField->setTopField(isTopField); // interlaced requirement for (UInt componentIndex = 0; componentIndex < pcPicYuvOrg->getNumberValidComponents(); componentIndex++) { const ComponentID component = ComponentID(componentIndex); const UInt stride = pcPicYuvOrg->getStride(component); separateFields((pcPicYuvOrg->getBuf(component) + pcPicYuvOrg->getMarginX(component) + (pcPicYuvOrg->getMarginY(component) * stride)), pcField->getPicYuvOrg()->getAddr(component), pcPicYuvOrg->getStride(component), pcPicYuvOrg->getWidth(component), pcPicYuvOrg->getHeight(component), isTopField); separateFields((pcPicYuvTrueOrg->getBuf(component) + pcPicYuvTrueOrg->getMarginX(component) + (pcPicYuvTrueOrg->getMarginY(component) * stride)), pcField->getPicYuvTrueOrg()->getAddr(component), pcPicYuvTrueOrg->getStride(component), pcPicYuvTrueOrg->getWidth(component), pcPicYuvTrueOrg->getHeight(component), isTopField); } // compute image characteristics if ( getUseAdaptiveQP() ) { m_cPreanalyzer.xPreanalyze( dynamic_cast<TEncPic*>( pcField ) ); } } if ( m_iNumPicRcvd && ((flush&&fieldNum==1) || (m_iPOCLast/2)==0 || m_iNumPicRcvd==m_iGOPSize ) ) { // compress GOP m_cGOPEncoder.compressGOP(m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut, accessUnitsOut, true, isTff, snrCSC, m_printFrameMSE,&m_cSearch); iNumEncoded += m_iNumPicRcvd; m_uiNumAllPicCoded += m_iNumPicRcvd; m_iNumPicRcvd = 0; } } }
/** Function for applying picture marking based on the Reference Picture Set in pReferencePictureSet */ void DPB::applyReferencePictureSet(TComReferencePictureSet *rps, int curPoc) { TComPic* outPic; int i, isReference; // loop through all pictures in the reference picture buffer TComPic* iterPic = m_picList.first(); while (iterPic) { outPic = iterPic; iterPic = iterPic->m_next; if (!outPic->getSlice()->isReferenced()) { continue; } isReference = 0; // loop through all pictures in the Reference Picture Set // to see if the picture should be kept as reference picture for (i = 0; i < rps->getNumberOfPositivePictures() + rps->getNumberOfNegativePictures(); i++) { if (!outPic->getIsLongTerm() && outPic->getPicSym()->getSlice()->getPOC() == curPoc + rps->getDeltaPOC(i)) { isReference = 1; outPic->setUsedByCurr(rps->getUsed(i) == 1); outPic->setIsLongTerm(0); } } for (; i < rps->getNumberOfPictures(); i++) { if (rps->getCheckLTMSBPresent(i) == true) { if (outPic->getIsLongTerm() && (outPic->getPicSym()->getSlice()->getPOC()) == rps->getPOC(i)) { isReference = 1; outPic->setUsedByCurr(rps->getUsed(i) == 1); } } else { if (outPic->getIsLongTerm() && (outPic->getPicSym()->getSlice()->getPOC() % (1 << outPic->getPicSym()->getSlice()->getSPS()->getBitsForPOC())) == rps->getPOC(i) % (1 << outPic->getPicSym()->getSlice()->getSPS()->getBitsForPOC())) { isReference = 1; outPic->setUsedByCurr(rps->getUsed(i) == 1); } } } // mark the picture as "unused for reference" if it is not in // the Reference Picture Set if (outPic->getPicSym()->getSlice()->getPOC() != curPoc && isReference == 0) { outPic->getSlice()->setReferenced(false); outPic->setUsedByCurr(0); outPic->setIsLongTerm(0); } } }
TComPic* TComSlice::xGetRefPic (TComList<TComPic*>& rcListPic, Bool bDRBFlag, ERBIndex eERBIndex, UInt uiPOCCurr, RefPicList eRefPicList, UInt uiNthRefPic, UInt uiTLayer) { // find current position TComList<TComPic*>::iterator iterPic = rcListPic.begin(); TComPic* pcRefPic = NULL; TComPic* pcPic = *(iterPic); while ( (pcPic->getPOC() != (Int)uiPOCCurr) && (iterPic != rcListPic.end()) ) { iterPic++; pcPic = *(iterPic); } assert (pcPic->getPOC() == (Int)uiPOCCurr); // find n-th reference picture with bDRBFlag and eERBIndex UInt uiCount = 0; if( eRefPicList == REF_PIC_LIST_0 ) { while(1) { if (iterPic == rcListPic.begin()) break; iterPic--; pcPic = *(iterPic); if( ( !pcPic->getReconMark() ) || ( bDRBFlag != pcPic->getSlice(0)->getDRBFlag() ) || ( eERBIndex != pcPic->getSlice(0)->getERBIndex() ) ) continue; if( !pcPic->getSlice(0)->isReferenced() ) continue; if ( pcPic->getTLayer() > uiTLayer ) continue; uiCount++; if (uiCount == uiNthRefPic) { pcRefPic = pcPic; return pcRefPic; } } if ( !m_pcSPS->getUseLDC() ) { iterPic = rcListPic.begin(); pcPic = *(iterPic); while ( (pcPic->getPOC() != (Int)uiPOCCurr) && (iterPic != rcListPic.end()) ) { iterPic++; pcPic = *(iterPic); } assert (pcPic->getPOC() == (Int)uiPOCCurr); while(1) { iterPic++; if (iterPic == rcListPic.end()) break; pcPic = *(iterPic); if( ( !pcPic->getReconMark() ) || ( bDRBFlag != pcPic->getSlice(0)->getDRBFlag() ) || ( eERBIndex != pcPic->getSlice(0)->getERBIndex() ) ) continue; if( !pcPic->getSlice(0)->isReferenced() ) continue; if ( pcPic->getTLayer() > uiTLayer ) continue; uiCount++; if (uiCount == uiNthRefPic) { pcRefPic = pcPic; return pcRefPic; } } } } else { while(1) { iterPic++; if (iterPic == rcListPic.end()) break; pcPic = *(iterPic); if( ( !pcPic->getReconMark() ) || ( bDRBFlag != pcPic->getSlice(0)->getDRBFlag() ) || ( eERBIndex != pcPic->getSlice(0)->getERBIndex() ) ) continue; if( !pcPic->getSlice(0)->isReferenced() ) continue; if ( pcPic->getTLayer() > uiTLayer ) continue; uiCount++; if (uiCount == uiNthRefPic) { pcRefPic = pcPic; return pcRefPic; } } iterPic = rcListPic.begin(); pcPic = *(iterPic); while ( (pcPic->getPOC() != (Int)uiPOCCurr) && (iterPic != rcListPic.end()) ) { iterPic++; pcPic = *(iterPic); } assert (pcPic->getPOC() == (Int)uiPOCCurr); while(1) { if (iterPic == rcListPic.begin()) break; iterPic--; pcPic = *(iterPic); if( ( !pcPic->getReconMark() ) || ( bDRBFlag != pcPic->getSlice(0)->getDRBFlag() ) || ( eERBIndex != pcPic->getSlice(0)->getERBIndex() ) ) continue; if( !pcPic->getSlice(0)->isReferenced() ) continue; if ( pcPic->getTLayer() > uiTLayer ) continue; uiCount++; if (uiCount == uiNthRefPic) { pcRefPic = pcPic; return pcRefPic; } } } return pcRefPic; }
// Function will arrange the long-term pictures in the decreasing order of poc_lsb_lt, // and among the pictures with the same lsb, it arranges them in increasing delta_poc_msb_cycle_lt value void DPB::arrangeLongtermPicturesInRPS(TComSlice *slice) { TComReferencePictureSet *rps = slice->getRPS(); if (!rps->getNumberOfLongtermPictures()) { return; } // Arrange long-term reference pictures in the correct order of LSB and MSB, // and assign values for pocLSBLT and MSB present flag int longtermPicsPoc[MAX_NUM_REF_PICS], longtermPicsLSB[MAX_NUM_REF_PICS], indices[MAX_NUM_REF_PICS]; int longtermPicsMSB[MAX_NUM_REF_PICS]; bool mSBPresentFlag[MAX_NUM_REF_PICS]; ::memset(longtermPicsPoc, 0, sizeof(longtermPicsPoc)); // Store POC values of LTRP ::memset(longtermPicsLSB, 0, sizeof(longtermPicsLSB)); // Store POC LSB values of LTRP ::memset(longtermPicsMSB, 0, sizeof(longtermPicsMSB)); // Store POC LSB values of LTRP ::memset(indices, 0, sizeof(indices)); // Indices to aid in tracking sorted LTRPs ::memset(mSBPresentFlag, 0, sizeof(mSBPresentFlag)); // Indicate if MSB needs to be present // Get the long-term reference pictures int offset = rps->getNumberOfNegativePictures() + rps->getNumberOfPositivePictures(); int i, ctr = 0; int maxPicOrderCntLSB = 1 << slice->getSPS()->getBitsForPOC(); for (i = rps->getNumberOfPictures() - 1; i >= offset; i--, ctr++) { longtermPicsPoc[ctr] = rps->getPOC(i); // LTRP POC longtermPicsLSB[ctr] = getLSB(longtermPicsPoc[ctr], maxPicOrderCntLSB); // LTRP POC LSB indices[ctr] = i; longtermPicsMSB[ctr] = longtermPicsPoc[ctr] - longtermPicsLSB[ctr]; } int numLongPics = rps->getNumberOfLongtermPictures(); assert(ctr == numLongPics); // Arrange pictures in decreasing order of MSB; for (i = 0; i < numLongPics; i++) { for (int j = 0; j < numLongPics - 1; j++) { if (longtermPicsMSB[j] < longtermPicsMSB[j + 1]) { std::swap(longtermPicsPoc[j], longtermPicsPoc[j + 1]); std::swap(longtermPicsLSB[j], longtermPicsLSB[j + 1]); std::swap(longtermPicsMSB[j], longtermPicsMSB[j + 1]); std::swap(indices[j], indices[j + 1]); } } } for (i = 0; i < numLongPics; i++) { // Check if MSB present flag should be enabled. // Check if the buffer contains any pictures that have the same LSB. TComPic* iterPic = m_picList.first(); while (iterPic) { if ((getLSB(iterPic->getPOC(), maxPicOrderCntLSB) == longtermPicsLSB[i]) && // Same LSB (iterPic->getSlice()->isReferenced()) && // Reference picture (iterPic->getPOC() != longtermPicsPoc[i])) // Not the LTRP itself { mSBPresentFlag[i] = true; break; } iterPic = iterPic->m_next; } } // tempArray for usedByCurr flag bool tempArray[MAX_NUM_REF_PICS]; ::memset(tempArray, 0, sizeof(tempArray)); for (i = 0; i < numLongPics; i++) { tempArray[i] = rps->getUsed(indices[i]) ? true : false; } // Now write the final values; ctr = 0; int currMSB = 0, currLSB = 0; // currPicPoc = currMSB + currLSB currLSB = getLSB(slice->getPOC(), maxPicOrderCntLSB); currMSB = slice->getPOC() - currLSB; for (i = rps->getNumberOfPictures() - 1; i >= offset; i--, ctr++) { rps->setPOC(i, longtermPicsPoc[ctr]); rps->setDeltaPOC(i, -slice->getPOC() + longtermPicsPoc[ctr]); rps->setUsed(i, tempArray[ctr]); rps->setPocLSBLT(i, longtermPicsLSB[ctr]); rps->setDeltaPocMSBCycleLT(i, (currMSB - (longtermPicsPoc[ctr] - longtermPicsLSB[ctr])) / maxPicOrderCntLSB); rps->setDeltaPocMSBPresentFlag(i, mSBPresentFlag[ctr]); assert(rps->getDeltaPocMSBCycleLT(i) >= 0); // Non-negative value } for (i = rps->getNumberOfPictures() - 1, ctr = 1; i >= offset; i--, ctr++) { for (int j = rps->getNumberOfPictures() - 1 - ctr; j >= offset; j--) { // Here at the encoder we know that we have set the full POC value for the LTRPs, hence we // don't have to check the MSB present flag values for this constraint. assert(rps->getPOC(i) != rps->getPOC(j)); // If assert fails, LTRP entry repeated in RPS!!! } } }
Void TComSlice::setRefPicList ( TComList<TComPic*>& rcListPic ) { if (m_eSliceType == I_SLICE) { ::memset( m_apcRefPicList, 0, sizeof (m_apcRefPicList)); ::memset( m_aiNumRefIdx, 0, sizeof ( m_aiNumRefIdx )); return; } m_aiNumRefIdx[0] = min ( m_aiNumRefIdx[0], (Int)(rcListPic.size())-1 ); m_aiNumRefIdx[1] = min ( m_aiNumRefIdx[1], (Int)(rcListPic.size())-1 ); sortPicList(rcListPic); TComPic* pcRefPic; for (Int n = 0; n < 2; n++) { RefPicList eRefPicList = (RefPicList)n; UInt uiOrderDRB = 1; UInt uiOrderERB = 1; Int iRefIdx = 0; UInt uiActualListSize = 0; if ( m_eSliceType == P_SLICE && eRefPicList == REF_PIC_LIST_1 ) { m_aiNumRefIdx[eRefPicList] = 0; ::memset( m_apcRefPicList[eRefPicList], 0, sizeof(m_apcRefPicList[eRefPicList])); break; } // First DRB pcRefPic = xGetRefPic(rcListPic, true, ERB_NONE, m_iPOC, eRefPicList, uiOrderDRB, m_uiTLayer); if (pcRefPic != NULL) { m_apcRefPicList[eRefPicList][iRefIdx] = pcRefPic; pcRefPic->getPicYuvRec()->extendPicBorder(); iRefIdx++; uiOrderDRB++; uiActualListSize++; } if ( (Int)uiActualListSize >= m_aiNumRefIdx[eRefPicList] ) { m_aiNumRefIdx[eRefPicList] = uiActualListSize; continue; } // Long term reference // Should be enabled to support long term refernce //* // First ERB pcRefPic = xGetRefPic(rcListPic, false, ERB_LTR, m_iPOC, eRefPicList, uiOrderERB, m_uiTLayer); if (pcRefPic != NULL) { Bool bChangeDrbErb = false; if (iRefIdx > 0 && eRefPicList == REF_PIC_LIST_0 && pcRefPic->getPOC() > m_apcRefPicList[eRefPicList][iRefIdx-1]->getPOC()) { bChangeDrbErb = true; } else if (iRefIdx > 0 && eRefPicList == REF_PIC_LIST_1 && pcRefPic->getPOC() < m_apcRefPicList[eRefPicList][iRefIdx-1]->getPOC()) { bChangeDrbErb = true; } if ( bChangeDrbErb) { m_apcRefPicList[eRefPicList][iRefIdx] = m_apcRefPicList[eRefPicList][iRefIdx-1]; m_apcRefPicList[eRefPicList][iRefIdx-1] = pcRefPic; } else { m_apcRefPicList[eRefPicList][iRefIdx] = pcRefPic; } pcRefPic->getPicYuvRec()->extendPicBorder(); iRefIdx++; uiOrderERB++; uiActualListSize++; } //*/ // Short term reference // Residue DRB UInt uiBreakCount = 17 - iRefIdx; while (1) { uiBreakCount--; if ( (Int)uiActualListSize >= m_aiNumRefIdx[eRefPicList] || uiBreakCount == 0 ) { break; } pcRefPic = xGetRefPic(rcListPic, true, ERB_NONE, m_iPOC, eRefPicList, uiOrderDRB, m_uiTLayer); if (pcRefPic != NULL) { uiOrderDRB++; } if (pcRefPic != NULL) { m_apcRefPicList[eRefPicList][iRefIdx] = pcRefPic; pcRefPic->getPicYuvRec()->extendPicBorder(); iRefIdx++; uiActualListSize++; } } m_aiNumRefIdx[eRefPicList] = uiActualListSize; } }