HTM-16.2代码(13)——getInterMergeCandidates
2016-12-28 16:33
253 查看
getInterMergeCandidates是Merge技术候选列表的实现。空域:选取的顺序为A1->B1->B0->A0->(B2)。其中,B2只有在A1,B1,B0,A0中有一个不存在或者帧内预测的情况才可使用。时域:一般情况下首先考虑的是H位置,当H位置不存在或者编码模式使用的是帧内编码模式或者超出了CTU的边界时,选择C3位置。
//! Construct a list of merging candidates #if NH_3D Void TComDataCU::getInterMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMvFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, Int mrgCandIdx ) #else Void TComDataCU::getInterMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMvFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, Int mrgCandIdx ) const #endif { UInt uiAbsPartAddr = m_absZIdxInCtu + uiAbsPartIdx; //!< 当前CU的ZScan地址 #if NH_3D_MLC Bool abCandIsInter[ MRG_MAX_NUM_CANDS_MEM ]; #else Bool abCandIsInter[ MRG_MAX_NUM_CANDS ]; #endif for( UInt ui = 0; ui < getSlice()->getMaxNumMergeCand(); ++ui ) { abCandIsInter[ui] = false; pcMvFieldNeighbours[ ( ui << 1 ) ].setRefIdx(NOT_VALID); pcMvFieldNeighbours[ ( ui << 1 ) + 1 ].setRefIdx(NOT_VALID); } numValidMergeCand = getSlice()->getMaxNumMergeCand();//候选列表的数目 // compute the location of the current PU Int xP, yP, nPSW, nPSH; this->getPartPosition(uiPUIdx, xP, yP, nPSW, nPSH);//!< 获得当前PU的地址和大小 Int iCount = 0;//标记候选列表的数目 UInt uiPartIdxLT, uiPartIdxRT, uiPartIdxLB; PartSize cCurPS = getPartitionSize( uiAbsPartIdx );//!< CU的分割模式 deriveLeftRightTopIdxGeneral( uiAbsPartIdx, uiPUIdx, uiPartIdxLT, uiPartIdxRT );//!< 左上部uiPartIdxLT,右上部uiPartIdxRT deriveLeftBottomIdxGeneral( uiAbsPartIdx, uiPUIdx, uiPartIdxLB );//!< 左下部uiPartIdxLB //left A1 UInt uiLeftPartIdx = 0; const TComDataCU *pcCULeft = getPULeft( uiLeftPartIdx, uiPartIdxLB );//A1 Bool isAvailableA1 = pcCULeft && pcCULeft->isDiffMER(xP -1, yP+nPSH-1, xP, yP) && !( uiPUIdx == 1 && (cCurPS == SIZE_Nx2N || cCurPS == SIZE_nLx2N || cCurPS == SIZE_nRx2N) ) && pcCULeft->isInter( uiLeftPartIdx ) ;//A1是否可用。。 当CU的划分模式为SIZE_Nx2N、SIZE_nLx2N或SIZE_nRx2N,PU2不能使用A1的mv if ( isAvailableA1 )//A1可用 { #if NH_3D_MLC m_bAvailableFlagA1 = 1; #endif abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCULeft->getInterDir( uiLeftPartIdx ); // get Mv from Left TComDataCU::getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );//从A1中得到mv,存入pcMvFieldNeighbours[iCount<<1] if ( getSlice()->isInterB() ) { TComDataCU::getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] ); } if ( mrgCandIdx == iCount ) { return; } iCount ++; } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { return; } // above B1 UInt uiAbovePartIdx = 0; const TComDataCU *pcCUAbove = getPUAbove( uiAbovePartIdx, uiPartIdxRT );//B1 Bool isAvailableB1 = pcCUAbove && pcCUAbove->isDiffMER(xP+nPSW-1, yP-1, xP, yP) && !( uiPUIdx == 1 && (cCurPS == SIZE_2NxN || cCurPS == SIZE_2NxnU || cCurPS == SIZE_2NxnD) ) && pcCUAbove->isInter( uiAbovePartIdx );//B1是否可用。。 当CU的划分模式为SIZE_2NxN、SIZE_2NxnU或SIZE_2NxnD,PU2不能使用B1的mv if ( isAvailableB1 && (!isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAbove, uiAbovePartIdx ) ) )//B1可用,且与A1的mv不相同 { #if NH_3D_MLC m_bAvailableFlagB1 = 1; #endif abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCUAbove->getInterDir( uiAbovePartIdx ); // get Mv from Left TComDataCU::getMvField( pcCUAbove, uiAbovePartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );//从B1中得到mv,存入pcMvFieldNeighbours[iCount<<1] if ( getSlice()->isInterB() ) { TComDataCU::getMvField( pcCUAbove, uiAbovePartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] ); } if ( mrgCandIdx == iCount ) { return; } iCount ++; } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { return; } // above right B0 UInt uiAboveRightPartIdx = 0; const TComDataCU *pcCUAboveRight = getPUAboveRight( uiAboveRightPartIdx, uiPartIdxRT ); Bool isAvailableB0 = pcCUAboveRight && pcCUAboveRight->isDiffMER(xP+nPSW, yP-1, xP, yP) && pcCUAboveRight->isInter( uiAboveRightPartIdx ); if ( isAvailableB0 && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveRight, uiAboveRightPartIdx ) ) ) { #if NH_3D_MLC m_bAvailableFlagB0 = 1; #endif abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCUAboveRight->getInterDir( uiAboveRightPartIdx ); // get Mv from Left TComDataCU::getMvField( pcCUAboveRight, uiAboveRightPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); if ( getSlice()->isInterB() ) { TComDataCU::getMvField( pcCUAboveRight, uiAboveRightPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] ); } if ( mrgCandIdx == iCount ) { return; } iCount ++; } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { return; } //left bottom A0 UInt uiLeftBottomPartIdx = 0; const TComDataCU *pcCULeftBottom = this->getPUBelowLeft( uiLeftBottomPartIdx, uiPartIdxLB ); Bool isAvailableA0 = pcCULeftBottom && pcCULeftBottom->isDiffMER(xP-1, yP+nPSH, xP, yP) && pcCULeftBottom->isInter( uiLeftBottomPartIdx ) ; if ( isAvailableA0 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCULeftBottom, uiLeftBottomPartIdx ) ) ) { #if NH_3D_MLC m_bAvailableFlagA0 = 1; #endif abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCULeftBottom->getInterDir( uiLeftBottomPartIdx ); // get Mv from Left TComDataCU::getMvField( pcCULeftBottom, uiLeftBottomPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); if ( getSlice()->isInterB() ) { TComDataCU::getMvField( pcCULeftBottom, uiLeftBottomPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] ); } if ( mrgCandIdx == iCount ) { return; } iCount ++; } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { return; } // above left B2 if( iCount < 4 ) { UInt uiAboveLeftPartIdx = 0; const TComDataCU *pcCUAboveLeft = getPUAboveLeft( uiAboveLeftPartIdx, uiAbsPartAddr ); Bool isAvailableB2 = pcCUAboveLeft && pcCUAboveLeft->isDiffMER(xP-1, yP-1, xP, yP) && pcCUAboveLeft->isInter( uiAboveLeftPartIdx ); if ( isAvailableB2 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) ) && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) ) ) { #if NH_3D_MLC m_bAvailableFlagB2 = 1; #endif abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCUAboveLeft->getInterDir( uiAboveLeftPartIdx ); // get Mv from Left TComDataCU::getMvField( pcCUAboveLeft, uiAboveLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); if ( getSlice()->isInterB() ) { TComDataCU::getMvField( pcCUAboveLeft, uiAboveLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] ); } if ( mrgCandIdx == iCount ) { return; } iCount ++; } } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { return; } //时域候选列表的建立 if ( getSlice()->getEnableTMVPFlag() ) { //>> MTK colocated-RightBottom UInt uiPartIdxRB; deriveRightBottomIdx( uiPUIdx, uiPartIdxRB ); UInt uiAbsPartIdxTmp = g_auiZscanToRaster[uiPartIdxRB]; const UInt numPartInCtuWidth = m_pcPic->getNumPartInCtuWidth(); const UInt numPartInCtuHeight = m_pcPic->getNumPartInCtuHeight(); TComMv cColMv; Int iRefIdx; Int ctuRsAddr = -1; if ( ( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelX() + g_auiRasterToPelX[uiAbsPartIdxTmp] + m_pcPic->getMinCUWidth () ) < m_pcSlice->getSPS()->getPicWidthInLumaSamples () ) // image boundary check && ( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelY() + g_auiRasterToPelY[uiAbsPartIdxTmp] + m_pcPic->getMinCUHeight() ) < m_pcSlice->getSPS()->getPicHeightInLumaSamples() ) ) {//得到H的索引uiAbsPartAddr if ( ( uiAbsPartIdxTmp % numPartInCtuWidth < numPartInCtuWidth - 1 ) && // is not at the last column of CTU ( uiAbsPartIdxTmp / numPartInCtuWidth < numPartInCtuHeight - 1 ) ) // is not at the last row of CTU { uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + numPartInCtuWidth + 1 ]; ctuRsAddr = getCtuRsAddr(); } else if ( uiAbsPartIdxTmp % numPartInCtuWidth < numPartInCtuWidth - 1 ) // is not at the last column of CTU But is last row of CTU { uiAbsPartAddr = g_auiRasterToZscan[ (uiAbsPartIdxTmp + numPartInCtuWidth + 1) % m_pcPic->getNumPartitionsInCtu() ]; } else if ( uiAbsPartIdxTmp / numPartInCtuWidth < numPartInCtuHeight - 1 ) // is not at the last row of CTU But is last column of CTU { uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + 1 ]; ctuRsAddr = getCtuRsAddr() + 1; } else //is the right bottom corner of CTU { uiAbsPartAddr = 0; } } iRefIdx = 0; Bool bExistMV = false; UInt uiPartIdxCenter; Int dir = 0; UInt uiArrayAddr = iCount; xDeriveCenterIdx( uiPUIdx, uiPartIdxCenter );//得到C3的索引uiPartIdxCenter bExistMV = ctuRsAddr >= 0 && xGetColMVP( REF_PIC_LIST_0, ctuRsAddr, uiAbsPartAddr, cColMv, iRefIdx );//根据H的索引uiAbsPartAddr,得到H的scaled mv if( bExistMV == false ) { bExistMV = xGetColMVP( REF_PIC_LIST_0, getCtuRsAddr(), uiPartIdxCenter, cColMv, iRefIdx );//根据C3的索引uiPartIdxCenter,得到C3的scaled mv } if( bExistMV ) { dir |= 1; pcMvFieldNeighbours[ 2 * uiArrayAddr ].setMvField( cColMv, iRefIdx ); } if ( getSlice()->isInterB() )//考虑list1 { #if NH_3D_TMVP iRefIdx = 0; #endif bExistMV = ctuRsAddr >= 0 && xGetColMVP( REF_PIC_LIST_1, ctuRsAddr, uiAbsPartAddr, cColMv, iRefIdx); if( bExistMV == false ) { bExistMV = xGetColMVP( REF_PIC_LIST_1, getCtuRsAddr(), uiPartIdxCenter, cColMv, iRefIdx ); } if( bExistMV ) { dir |= 2; pcMvFieldNeighbours[ 2 * uiArrayAddr + 1 ].setMvField( cColMv, iRefIdx ); } } if (dir != 0) { puhInterDirNeighbours[uiArrayAddr] = dir; abCandIsInter[uiArrayAddr] = true; #if NH_3D_NBDV pcMvFieldNeighbours[iCount<<1 ].getMv().setIDVFlag (false); pcMvFieldNeighbours[(iCount<<1)+1].getMv().setIDVFlag (false); #endif if ( mrgCandIdx == iCount ) { return; } iCount++; } } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { return; } UInt uiArrayAddr = iCount; UInt uiCutoff = uiArrayAddr; //组合列表的建立 #if NH_3D_MLC if ( getSlice()->isInterB() && iCount<5) #else if ( getSlice()->isInterB() ) #endif { static const UInt NUM_PRIORITY_LIST=12; static const UInt uiPriorityList0[NUM_PRIORITY_LIST] = {0 , 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3}; static const UInt uiPriorityList1[NUM_PRIORITY_LIST] = {1 , 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2}; for (Int idx=0; idx<uiCutoff*(uiCutoff-1) && uiArrayAddr!= getSlice()->getMaxNumMergeCand(); idx++) { assert(idx<NUM_PRIORITY_LIST); Int i = uiPriorityList0[idx]; Int j = uiPriorityList1[idx]; if (abCandIsInter[i] && abCandIsInter[j]&& (puhInterDirNeighbours[i]&0x1)&&(puhInterDirNeighbours[j]&0x2)) { abCandIsInter[uiArrayAddr] = true; puhInterDirNeighbours[uiArrayAddr] = 3; // get Mv from cand[i] and cand[j] pcMvFieldNeighbours[uiArrayAddr << 1].setMvField(pcMvFieldNeighbours[i<<1].getMv(), pcMvFieldNeighbours[i<<1].getRefIdx()); pcMvFieldNeighbours[( uiArrayAddr << 1 ) + 1].setMvField(pcMvFieldNeighbours[(j<<1)+1].getMv(), pcMvFieldNeighbours[(j<<1)+1].getRefIdx()); Int iRefPOCL0 = m_pcSlice->getRefPOC( REF_PIC_LIST_0, pcMvFieldNeighbours[(uiArrayAddr<<1)].getRefIdx() ); Int iRefPOCL1 = m_pcSlice->getRefPOC( REF_PIC_LIST_1, pcMvFieldNeighbours[(uiArrayAddr<<1)+1].getRefIdx() ); if (iRefPOCL0 == iRefPOCL1 && pcMvFieldNeighbours[(uiArrayAddr<<1)].getMv() == pcMvFieldNeighbours[(uiArrayAddr<<1)+1].getMv()) { abCandIsInter[uiArrayAddr] = false; } else { uiArrayAddr++; } } } } // early termination if (uiArrayAddr == getSlice()->getMaxNumMergeCand()) { return; } Int iNumRefIdx = (getSlice()->isInterB()) ? min(m_pcSlice->getNumRefIdx(REF_PIC_LIST_0), m_pcSlice->getNumRefIdx(REF_PIC_LIST_1)) : m_pcSlice->getNumRefIdx(REF_PIC_LIST_0); Int r = 0; Int refcnt = 0; while (uiArrayAddr < getSlice()->getMaxNumMergeCand())//! 当可用的merge candidates数目仍小于预设值时,将余量均设置为零运动矢量 { abCandIsInter[uiArrayAddr] = true; puhInterDirNeighbours[uiArrayAddr] = 1; pcMvFieldNeighbours[uiArrayAddr << 1].setMvField( TComMv(0, 0), r); if ( getSlice()->isInterB() ) { puhInterDirNeighbours[uiArrayAddr] = 3; pcMvFieldNeighbours[(uiArrayAddr << 1) + 1].setMvField(TComMv(0, 0), r); } uiArrayAddr++; if ( refcnt == iNumRefIdx - 1 )//!< 达到参考帧列表的参考帧数 { r = 0; } else { ++r; ++refcnt; } } numValidMergeCand = uiArrayAddr; }
相关文章推荐
- 帧间预测(一)Void TComDataCU ::getInterMergeCandidates
- HTM-16.2代码(10)——xPatternSearch和xPatternSearchFast
- Android Audio代码分析13 - AudioTrack::getPosition函数
- HTM-16.2代码(12)——xTZ8PointDiamondSearch和xTZ2PointSearch
- HTM-16.2代码(2)——帧间预测(理论)
- HTM-16.2代码(7)——motionCompensation
- HTM-16.2代码(11)——xTZSearch
- HTM-16.2代码(4)——xCheckRDCostInter
- HTM-16.2代码(1)——编码端一些函数的说明
- Android Audio代码分析13 - AudioTrack::getPosition函数
- HTM-16.2代码(9)——fillMvpCand
- HTM-16.2代码(3)——xCompressCU
- 补上一篇 EXT Tree 中遗漏的get-node.php代码
- 生成flash的set get代码的小工具
- ASP生成静态htm页面基本代码
- GetKernelBase代码收集
- 【译】注释代码的13技巧
- ASP生成静态htm页面基本代码!