主要过程: 1、首选调用selectReferencePictureSet来选择一个参考图像集,参考图像集(最多有有9个),全部放在SPS中,可以根据索引来取得
(1)默认把当前帧在当前GOP中的相对poc设置为参考图像集的索引
(2)如果当前帧的poc对I帧周期求余等于m_GOPList(注意这个列表存放的是帧对应的GOP信息,以及参考帧等信息)某个元素的gop
那么就把这个元素的下标设置为参考图像集的索引!
2、每帧的第一个片中包含一个RPS的信息
3、根据步骤1选中的参考图像集,调用createExplicitReferencePictureSetFromReference 创建本地参考图像集,然后把参考的图像集设置为本地参考图像集
(1)遍历参考集中所有的帧(参考集只存放这些参考帧的相对poc),在图像列表中找到其对应的帧,然后转往(2)
(2)把相对poc存放到本地参考图像集的m_deltaPOC中
(3)在本地参考图像集设置该帧(即参考帧)的被使用的标志(在m_used中)
(4)如果相对poc小于0,那么统计为前向参考帧;如果相对poc大于0,那么统计为后向参考帧
(5)把本地参考集设置为参考集
4、根据参考图像集调用applyReferencePictureSet 应用参考图像集,主要是设置里面的帧是否允许被参考,是否允许被当前帧所参考
(1)对图像列表进行遍历,对于图像列表的每一帧pic,进行下面的操作
(2)遍历参考集中的前向和后向参考帧(前向和后向参考帧的poc都是相对poc),如果pic在参考集中,那么设置pic的被参考标志
(3)遍历参考集中其他参考帧(即长期参考帧),如果pic在参考集中,那么设置pic被参考的标志
(4)保证pic所在的时域层比当前帧的时域层小
5、排列参考图像集中的帧,arrangeLongtermPicturesInRPS,主要是对长期参考帧进行排序,并设置相应的标志信息的过程
(1)在参考图像集中先存放前向参考帧,然后存放后向参考帧,再放长期参考帧
(2)MSB和LSB分别表示最高有效位和最低有效位,按照MSB从大到小排序长期参考帧
(3)记录长期参考帧MSB出现的标志
(4)记录长期参考帧被当前帧使用的情况
(5)记录长期参考帧的各种信息(即上面出现的标志,使用情况等)
(6)确保长期参考帧不会重复
6、调用 setRefPicList来设置参考图像列表(m_apcRefPicList),根据参考图像集设置list0和list1
(1)m_aiNumRefIdx记录两个参考列表的元素个数
(2)遍历参考集中的每一个前向参考帧,根据相对poc取得真实的帧的指针,然后放入临时的list0中
(3)遍历每一个后向参考帧,把真实的帧的指针放入临时的list1中
(4)遍历每一个长期参考帧,把真实的帧的指针放入临时的list中
(5)按照前向、后向、长期的顺序,把这些参考帧都放进list0和list1中!(list0和list都放了前向和后向、长期参考帧;如果不是B帧,不需要list1)
7、调用setRefPOCList函数,设置m_aiRefPOCList
(1)m_apcRefPicList中存放的是帧的指针,而m_aiRefPOCList中存放的是帧的poc
(2)同样m_aiRefPOCList也是列表数组,m_aiRefPOCList[0]表示list0,m_aiRefPOCList[1]表示list1
8、调用setList1IdxToList0Idx,设置list0到list1的映射,根据poc相等来判断。
// 为当前帧选择一个参考图像集
// 额外的参考图像集有9个
Void TEncTop::selectReferencePictureSet(TComSlice* slice, Int POCCurr, Int GOPid )
{
// GOPid是该帧在GOP中的相对poc
// POCCurr是该帧的绝对poc
slice->setRPSidx(GOPid); // 设置默认的参考集的索引
// 对于额外的RPS
for(Int extraNum=m_iGOPSize; extraNum<m_extraRPSs+m_iGOPSize; extraNum++)
{
// 如果I帧的周期大于0
if(m_uiIntraPeriod > 0 && getDecodingRefreshType() > 0)
{
// 当前帧的poc(这个poc是绝对的poc)对IntraPeriod求余(求余之后就是IntraPeriod周期内的相对poc)
Int POCIndex = POCCurr%m_uiIntraPeriod;
if(POCIndex == 0)
{
POCIndex = m_uiIntraPeriod;
}
if(POCIndex == m_GOPList[extraNum].m_POC)
{
slice->setRPSidx(extraNum); // 如果IntraPeriod周期内的相对poc刚好等于额外参考集的poc,那么就把这个额外的参考集选为参考集
}
}
else
{
if(POCCurr==m_GOPList[extraNum].m_POC)
{
slice->setRPSidx(extraNum);
}
}
}
if(POCCurr == 1 && slice->getPic()->isField())
{
slice->setRPSidx(m_iGOPSize+m_extraRPSs);
}
slice->setRPS(getSPS()->getRPSList()->getReferencePictureSet(slice->getRPSidx()));
slice->getRPS()->setNumberOfPictures(slice->getRPS()->getNumberOfNegativePictures()+slice->getRPS()->getNumberOfPositivePictures());
}
// 明确的创建一个参考图像集(从参考图像中)#if ALLOW_RECOVERY_POINT_AS_RAPVoid TComSlice::createExplicitReferencePictureSetFromReference( TComList<TComPic*>& rcListPic, TComReferencePictureSet *pReferencePictureSet, Bool isRAP, Int pocRandomAccess, Bool bUseRecoveryPoint)#elseVoid TComSlice::createExplicitReferencePictureSetFromReference( TComList<TComPic*>& rcListPic, TComReferencePictureSet *pReferencePictureSet, Bool isRAP)#endif{TComPic* rpcPic;Int i, j; // k就是参考图像的计数Int k = 0;Int nrOfNegativePictures = 0;Int nrOfPositivePictures = 0; // 当前帧(片)的参考图像及TComReferencePictureSet* pcRPS = this->getLocalRPS();// loop through all pictures in the Reference Picture Set // 遍历所有的参考图像(存放在参考图像集中的)for(i=0;i<pReferencePictureSet->getNumberOfPictures();i++){j = 0;// loop through all pictures in the reference picture bufferTComList<TComPic*>::iterator iterPic = rcListPic.begin();while ( iterPic != rcListPic.end()){j++;rpcPic = *(iterPic++); // 该条件成立表示找到了参考图像 // 在图像列表中找到了当前片的参考图像 if(rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getPOC() + pReferencePictureSet->getDeltaPOC(i) && rpcPic->getSlice(0)->isReferenced()){// This picture exists as a reference picture// and should be added to the explicit Reference Picture Set // 设置第k个图像的相对pocpcRPS->setDeltaPOC(k, pReferencePictureSet->getDeltaPOC(i)); // 设置该参考图像是否允许被使用pcRPS->setUsed(k, pReferencePictureSet->getUsed(i) && (!isRAP));#if ALLOW_RECOVERY_POINT_AS_RAPpcRPS->setUsed(k, pcRPS->getUsed(k) && !(bUseRecoveryPoint && this->getPOC() > pocRandomAccess && this->getPOC() + pReferencePictureSet->getDeltaPOC(i) < pocRandomAccess) ); #endif // 如果相对poc小于0,表示是前向参考if(pcRPS->getDeltaPOC(k) < 0){ // 统计前向参考帧的数量nrOfNegativePictures++;} // 如果相对poc大于0,表示是后向参考else{ // 统计后向参考帧的数量nrOfPositivePictures++;}k++;}}}#if EFFICIENT_FIELD_IRAP // 是否使用新的参考图像集Bool useNewRPS = false;// if current picture is complimentary field associated to IRAP, add the IRAP to its RPS. if(m_pcPic->isField()){TComList<TComPic*>::iterator iterPic = rcListPic.begin();while ( iterPic != rcListPic.end()){rpcPic = *(iterPic++);if(rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getAssociatedIRAPPOC() && this->getAssociatedIRAPPOC() == this->getPOC()+1){pcRPS->setDeltaPOC(k, 1);pcRPS->setUsed(k, true);nrOfPositivePictures++;k ++;useNewRPS = true;}}}#endif // EFFICIENT_FIELD_IRAP // 设置前向参考帧的数量,后向参考帧的数量,以及参考帧的总数pcRPS->setNumberOfNegativePictures(nrOfNegativePictures);pcRPS->setNumberOfPositivePictures(nrOfPositivePictures);pcRPS->setNumberOfPictures(nrOfNegativePictures+nrOfPositivePictures);// This is a simplistic inter rps example. A smarter encoder will look for a better reference RPS to do the// inter RPS prediction with. Here we just use the reference used by pReferencePictureSet.// If pReferencePictureSet is not inter_RPS_predicted, then inter_RPS_prediction is for the current RPS also disabled. if (!pReferencePictureSet->getInterRPSPrediction() //如果是帧内预测#if EFFICIENT_FIELD_IRAP|| useNewRPS#endif){ pcRPS->setInterRPSPrediction(false); // pcRPS->setNumRefIdc(0);} // 帧间预测else{ // 参考图像集的索引,以传进来的参考图像集为基础,得到当前参考图像集的相对索引Int rIdx = this->getRPSidx() - pReferencePictureSet->getDeltaRIdxMinus1() - 1; // 相对的参考图像集Int deltaRPS = pReferencePictureSet->getDeltaRPS(); // 根据参考图像集的索引得到参考图像集(参考图像集可能有多个,存放在SPS的列表中),这个得到的图像集就是当前片的参考图像集TComReferencePictureSet* pcRefRPS = this->getSPS()->getRPSList()->getReferencePictureSet(rIdx); // 得到参考图像集中图像的数量Int iRefPics = pcRefRPS->getNumberOfPictures();Int iNewIdc=0; // 对参考图像集的每一个图像for(i=0; i<= iRefPics; i++) { // 得到相对的pocInt deltaPOC = ((i != iRefPics)? pcRefRPS->getDeltaPOC(i) : 0); // check if the reference abs POC is >= 0Int iRefIdc = 0; // 遍历本地的参考图像集的每一帧图像for (j=0; j < pcRPS->getNumberOfPictures(); j++) // loop through the pictures in the new RPS{ // 如果本参考图像集的某一帧和SPS的参考图像集中的某一帧匹配if ( (deltaPOC + deltaRPS) == pcRPS->getDeltaPOC(j)){ // 如果该帧可以被参考if (pcRPS->getUsed(j)){iRefIdc = 1;}else{iRefIdc = 2;}}} // 设置本地参考图像集的这一帧的idcpcRPS->setRefIdc(i, iRefIdc);iNewIdc++;} // 帧间预测pcRPS->setInterRPSPrediction(true); // 参考帧的数量pcRPS->setNumRefIdc(iNewIdc); // 相对的参考图像集的pcRPS->setDeltaRPS(deltaRPS); pcRPS->setDeltaRIdxMinus1(pReferencePictureSet->getDeltaRIdxMinus1() + this->getSPS()->getRPSList()->getNumberOfReferencePictureSets() - this->getRPSidx());} // 设置参考图像集this->setRPS(pcRPS);this->setRPSidx(-1);}
// 应用参考图像集Void TComSlice::applyReferencePictureSet( TComList<TComPic*>& rcListPic, TComReferencePictureSet *pReferencePictureSet){TComPic* rpcPic;Int i, isReference; // 检测leading 帧的限制checkLeadingPictureRestrictions(rcListPic);// loop through all pictures in the reference picture bufferTComList<TComPic*>::iterator iterPic = rcListPic.begin(); // 对图像列表的每一帧图像进行循环处理while ( iterPic != rcListPic.end()){rpcPic = *(iterPic++); // 如果不能被参考,那么跳过if(!rpcPic->getSlice( 0 )->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<pReferencePictureSet->getNumberOfPositivePictures()+pReferencePictureSet->getNumberOfNegativePictures();i++){ // 如果图像列表中的某一帧不是长期参考的帧 并且 它是当前帧的参考帧 if(!rpcPic->getIsLongTerm() && rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getPOC() + pReferencePictureSet->getDeltaPOC(i)){ // 把标志设置为1,表明是参考其他帧的isReference = 1; // 设置列表中的这一帧被其他人参考rpcPic->setUsedByCurr(pReferencePictureSet->getUsed(i));rpcPic->setIsLongTerm(0);}} // 对于参考图像集的其他图像(注意i没有设置从0开始)(这些参考帧(属于长期参考帧)的poc都是绝对的poc)for(;i<pReferencePictureSet->getNumberOfPictures();i++){if(pReferencePictureSet->getCheckLTMSBPresent(i)==true){if(rpcPic->getIsLongTerm() && (rpcPic->getPicSym()->getSlice(0)->getPOC()) == pReferencePictureSet->getPOC(i)){isReference = 1;rpcPic->setUsedByCurr(pReferencePictureSet->getUsed(i));}}else {Int pocCycle = 1<<rpcPic->getPicSym()->getSlice(0)->getSPS()->getBitsForPOC();Int curPoc = rpcPic->getPicSym()->getSlice(0)->getPOC() & (pocCycle-1);Int refPoc = pReferencePictureSet->getPOC(i) & (pocCycle-1);if(rpcPic->getIsLongTerm() && curPoc == refPoc){isReference = 1;rpcPic->setUsedByCurr(pReferencePictureSet->getUsed(i));}}}// mark the picture as "unused for reference" if it is not in// the Reference Picture Set // 对参考图像集遍历完成之后,就可以知道这个帧是否被被其他帧参考if(rpcPic->getPicSym()->getSlice(0)->getPOC() != this->getPOC() && isReference == 0){ rpcPic->getSlice( 0 )->setReferenced( false );rpcPic->setUsedByCurr(0);rpcPic->setIsLongTerm(0);}//check that pictures of higher temporal layers are not used // 这里保证了当前帧所在的时域层比参考帧的时域层大assert(rpcPic->getSlice( 0 )->isReferenced()==0||rpcPic->getUsedByCurr()==0||rpcPic->getTLayer()<=this->getTLayer());//check that pictures of higher or equal temporal layer are not in the RPS if the current picture is a TSA pictureif(this->getNalUnitType() == NAL_UNIT_CODED_SLICE_TSA_R || this->getNalUnitType() == NAL_UNIT_CODED_SLICE_TSA_N){assert(rpcPic->getSlice( 0 )->isReferenced()==0||rpcPic->getTLayer()<this->getTLayer());}//check that pictures marked as temporal layer non-reference pictures are not used for referenceif(rpcPic->getPicSym()->getSlice(0)->getPOC() != this->getPOC() && rpcPic->getTLayer()==this->getTLayer()){assert(rpcPic->getSlice( 0 )->isReferenced()==0||rpcPic->getUsedByCurr()==0||rpcPic->getSlice( 0 )->getTemporalLayerNonReferenceFlag()==false);}}}
// 对参考图像集中的长期参考图像进行排序Void TEncGOP::arrangeLongtermPicturesInRPS(TComSlice *pcSlice, TComList<TComPic*>& rcListPic){ TComReferencePictureSet *rps = pcSlice->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 // 长期参考图像的poc,LSB,索引 Int longtermPicsPoc[MAX_NUM_REF_PICS], longtermPicsLSB[MAX_NUM_REF_PICS], indices[MAX_NUM_REF_PICS]; // 长期参考图像的MSB Int longtermPicsMSB[MAX_NUM_REF_PICS]; // msb出现的标志 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 << pcSlice->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; // 按照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] ); } } } // 记录长期参考帧MSB出现的标志 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. TComList<TComPic*>::iterator iterPic = rcListPic.begin(); TComPic* pcPic; while ( iterPic != rcListPic.end() ) { pcPic = *iterPic; if( (getLSB(pcPic->getPOC(), maxPicOrderCntLSB) == longtermPicsLSB[i]) && // Same LSB (pcPic->getSlice(0)->isReferenced()) && // Reference picture (pcPic->getPOC() != longtermPicsPoc[i]) ) // Not the LTRP itself { mSBPresentFlag[i] = true; break; } iterPic++; } } // 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]); } // Now write the final values; ctr = 0; Int currMSB = 0, currLSB = 0; // currPicPoc = currMSB + currLSB currLSB = getLSB(pcSlice->getPOC(), maxPicOrderCntLSB); currMSB = pcSlice->getPOC() - currLSB; // 设置长期参考帧的各种信息 for(i = rps->getNumberOfPictures() - 1; i >= offset; i--, ctr++) { rps->setPOC (i, longtermPicsPoc[ctr]); rps->setDeltaPOC (i, - pcSlice->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, Bool checkNumPocTotalCurr ){if (!checkNumPocTotalCurr){if (m_eSliceType == I_SLICE){::memset( m_apcRefPicList, 0, sizeof (m_apcRefPicList));::memset( m_aiNumRefIdx, 0, sizeof ( m_aiNumRefIdx ));return;}m_aiNumRefIdx[0] = getNumRefIdx(REF_PIC_LIST_0);m_aiNumRefIdx[1] = getNumRefIdx(REF_PIC_LIST_1);}TComPic* pcRefPic= NULL; // 存放前向参考帧(最多16个)TComPic* RefPicSetStCurr0[16]; // 存放后向参考帧(最多16个)TComPic* RefPicSetStCurr1[16]; // 存放长期参考帧TComPic* RefPicSetLtCurr[16];UInt NumPocStCurr0 = 0;UInt NumPocStCurr1 = 0;UInt NumPocLtCurr = 0;Int i; // 遍历每一个前向参考帧for(i=0; i < m_pcRPS->getNumberOfNegativePictures(); i++){if(m_pcRPS->getUsed(i)){ // 取得该帧pcRefPic = xGetRefPic(rcListPic, getPOC()+m_pcRPS->getDeltaPOC(i));pcRefPic->setIsLongTerm(0); // 扩展图像边界pcRefPic->getPicYuvRec()->extendPicBorder(); // 把这个帧存放起来RefPicSetStCurr0[NumPocStCurr0] = pcRefPic;NumPocStCurr0++;pcRefPic->setCheckLTMSBPresent(false); }} // 遍历每一个后向参考帧for(; i < m_pcRPS->getNumberOfNegativePictures()+m_pcRPS->getNumberOfPositivePictures(); i++){if(m_pcRPS->getUsed(i)){pcRefPic = xGetRefPic(rcListPic, getPOC()+m_pcRPS->getDeltaPOC(i));pcRefPic->setIsLongTerm(0);pcRefPic->getPicYuvRec()->extendPicBorder();RefPicSetStCurr1[NumPocStCurr1] = pcRefPic;NumPocStCurr1++;pcRefPic->setCheckLTMSBPresent(false); }} // 遍历每一个长期参考帧for(i = m_pcRPS->getNumberOfNegativePictures()+m_pcRPS->getNumberOfPositivePictures()+m_pcRPS->getNumberOfLongtermPictures()-1; i > m_pcRPS->getNumberOfNegativePictures()+m_pcRPS->getNumberOfPositivePictures()-1 ; i--){if(m_pcRPS->getUsed(i)){pcRefPic = xGetLongTermRefPic(rcListPic, m_pcRPS->getPOC(i), m_pcRPS->getCheckLTMSBPresent(i));pcRefPic->setIsLongTerm(1);pcRefPic->getPicYuvRec()->extendPicBorder();RefPicSetLtCurr[NumPocLtCurr] = pcRefPic;NumPocLtCurr++;}if(pcRefPic==NULL) {pcRefPic = xGetLongTermRefPic(rcListPic, m_pcRPS->getPOC(i), m_pcRPS->getCheckLTMSBPresent(i));}pcRefPic->setCheckLTMSBPresent(m_pcRPS->getCheckLTMSBPresent(i)); }// ref_pic_list_init // 两个参考图像列表(list0和list1)TComPic* rpsCurrList0[MAX_NUM_REF+1];TComPic* rpsCurrList1[MAX_NUM_REF+1];Int numPocTotalCurr = NumPocStCurr0 + NumPocStCurr1 + NumPocLtCurr;if (checkNumPocTotalCurr){// The variable NumPocTotalCurr is derived as specified in subclause 7.4.7.2. It is a requirement of bitstream conformance that the following applies to the value of NumPocTotalCurr:// - If the current picture is a BLA or CRA picture, the value of NumPocTotalCurr shall be equal to 0.// - Otherwise, when the current picture contains a P or B slice, the value of NumPocTotalCurr shall not be equal to 0.if (getRapPicFlag()){assert(numPocTotalCurr == 0);}if (m_eSliceType == I_SLICE){::memset( m_apcRefPicList, 0, sizeof (m_apcRefPicList));::memset( m_aiNumRefIdx, 0, sizeof ( m_aiNumRefIdx ));return;}assert(numPocTotalCurr > 0);m_aiNumRefIdx[0] = getNumRefIdx(REF_PIC_LIST_0);m_aiNumRefIdx[1] = getNumRefIdx(REF_PIC_LIST_1);} // 按照 前向、后向,长期的顺序存放参考帧Int cIdx = 0;for ( i=0; i<NumPocStCurr0; i++, cIdx++){rpsCurrList0[cIdx] = RefPicSetStCurr0[i];}for ( i=0; i<NumPocStCurr1; i++, cIdx++){rpsCurrList0[cIdx] = RefPicSetStCurr1[i];}for ( i=0; i<NumPocLtCurr; i++, cIdx++){rpsCurrList0[cIdx] = RefPicSetLtCurr[i];}assert(cIdx == numPocTotalCurr); // 如果是B片(那么需要向后进行参考,即需要list1)if (m_eSliceType==B_SLICE){cIdx = 0;for ( i=0; i<NumPocStCurr1; i++, cIdx++){rpsCurrList1[cIdx] = RefPicSetStCurr1[i];}for ( i=0; i<NumPocStCurr0; i++, cIdx++){rpsCurrList1[cIdx] = RefPicSetStCurr0[i];}for ( i=0; i<NumPocLtCurr; i++, cIdx++){rpsCurrList1[cIdx] = RefPicSetLtCurr[i];}assert(cIdx == numPocTotalCurr);}::memset(m_bIsUsedAsLongTerm, 0, sizeof(m_bIsUsedAsLongTerm)); // 然后把list0和list1(上面的是临时的)放到当前帧的参考列表中for (Int rIdx = 0; rIdx < m_aiNumRefIdx[0]; rIdx ++){cIdx = m_RefPicListModification.getRefPicListModificationFlagL0() ? m_RefPicListModification.getRefPicSetIdxL0(rIdx) : rIdx % numPocTotalCurr;assert(cIdx >= 0 && cIdx < numPocTotalCurr);m_apcRefPicList[0][rIdx] = rpsCurrList0[ cIdx ];m_bIsUsedAsLongTerm[0][rIdx] = ( cIdx >= NumPocStCurr0 + NumPocStCurr1 );}if ( m_eSliceType != B_SLICE ){m_aiNumRefIdx[1] = 0;::memset( m_apcRefPicList[1], 0, sizeof(m_apcRefPicList[1]));}else{for (Int rIdx = 0; rIdx < m_aiNumRefIdx[1]; rIdx ++){cIdx = m_RefPicListModification.getRefPicListModificationFlagL1() ? m_RefPicListModification.getRefPicSetIdxL1(rIdx) : rIdx % numPocTotalCurr;assert(cIdx >= 0 && cIdx < numPocTotalCurr);m_apcRefPicList[1][rIdx] = rpsCurrList1[ cIdx ];m_bIsUsedAsLongTerm[1][rIdx] = ( cIdx >= NumPocStCurr0 + NumPocStCurr1 );}}}
Void TComSlice::setRefPOCList(){for (Int iDir = 0; iDir < 2; iDir++){for (Int iNumRefIdx = 0; iNumRefIdx < m_aiNumRefIdx[iDir]; iNumRefIdx++){m_aiRefPOCList[iDir][iNumRefIdx] = m_apcRefPicList[iDir][iNumRefIdx]->getPOC();}}}
Void TComSlice::setList1IdxToList0Idx(){Int idxL0, idxL1;for ( idxL1 = 0; idxL1 < getNumRefIdx( REF_PIC_LIST_1 ); idxL1++ ){m_list1IdxToList0Idx[idxL1] = -1;for ( idxL0 = 0; idxL0 < getNumRefIdx( REF_PIC_LIST_0 ); idxL0++ ){if ( m_apcRefPicList[REF_PIC_LIST_0][idxL0]->getPOC() == m_apcRefPicList[REF_PIC_LIST_1][idxL1]->getPOC() ){m_list1IdxToList0Idx[idxL1] = idxL0;break;}}}}