【转载】HEVC帧间预测之一——TComDataCU::getInterMergeCandidates函数分析

转载自

从今天开始,正式转入到帧间预测方向。由于帧间预测涉及到的方面广且复杂,所以我的理解出现错误的情况可能会更多,请大家以辩证的眼光来看待我的帖子,有问题欢迎大家批评指正。

 

大家都知道xCompressCU是实际进行预测编码的函数,故很容易就能锁定帧间预测的一个大致范围,在研究了帧内预测的基础上,相信很快就能在该函数中找到与帧间预测相关的函数:xCheckRDCostInter,xCheckRDCostMerge2Nx2N。前者进行除了merge模式以外的所有帧间预测,后者则是针对merge模式的。由于merge模式相对于H.264来说是个新事物,我们考虑先从研究它入手。

 

进入到xCheckRDCostMerge2Nx2N函数后,开头有一个比较重要的函数getInterMergeCandidates,它的功能是创建一个merge list,在该模式中是个很重要的函数,故我们先讨论它。下面按照惯例,给出我对这个函数的注释:

[cpp]  view plain copy
  1. Void TComDataCU::getInterMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMvFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, Int mrgCandIdx )  
  2. {  
  3.   UInt uiAbsPartAddr = m_uiAbsIdxInLCU + uiAbsPartIdx; //!< 当前CU的ZScan地址  
  4.   UInt uiIdx = 1;  
  5.   Bool abCandIsInter[ MRG_MAX_NUM_CANDS ];  
  6.   for( UInt ui = 0; ui < getSlice()->getMaxNumMergeCand(); ++ui ) //!< m_maxNumMergeCand = 5  
  7.   {  
  8.     abCandIsInter[ui] = false;  
  9.   }  
  10.   numValidMergeCand = getSlice()->getMaxNumMergeCand(); //!< 5  
  11.   // compute the location of the current PU  
  12.   Int xP, yP, nPSW, nPSH;  
  13.   this->getPartPosition(uiPUIdx, xP, yP, nPSW, nPSH); //!< 获得当前PU的地址和大小  
  14.   
  15.   Int iCount = 0; //!< 统计Merge candidate的个数  
  16.   
  17.   UInt uiPartIdxLT, uiPartIdxRT, uiPartIdxLB;  
  18.   PartSize cCurPS = getPartitionSize( uiAbsPartIdx ); //!< CU的分割模式  
  19.   deriveLeftRightTopIdxGeneral( uiAbsPartIdx, uiPUIdx, uiPartIdxLT, uiPartIdxRT ); //!< 左上部,右上部  
  20.   deriveLeftBottomIdxGeneral  ( uiAbsPartIdx, uiPUIdx, uiPartIdxLB ); //!< 左下部  
  21.   
  22.   //left  
  23.   UInt uiLeftPartIdx = 0;  
  24.   TComDataCU* pcCULeft = 0;  
  25.   pcCULeft = getPULeft( uiLeftPartIdx, uiPartIdxLB, truefalse );  
  26. #if MERGE_CLEANUP_AND_K0197 //!< 在有多个PU在一个CU中的时候,去除第二个PU对A1和B1的依赖性  
  27.   Bool isAvailableA1 = pcCULeft &&  
  28.   pcCULeft->isDiffMER(xP -1, yP+nPSH-1, xP, yP) && //!< 当前PU和它的相邻PU不在同一个ME区域  
  29.   !( uiPUIdx == 1 && (cCurPS == SIZE_Nx2N || cCurPS == SIZE_nLx2N || cCurPS == SIZE_nRx2N) ) &&  
  30.   !pcCULeft->isIntra( uiLeftPartIdx ) ;  
  31.   if ( isAvailableA1 )  
  32. #else  
  33.   if (pcCULeft)  
  34.   {  
  35.     if (!pcCULeft->isDiffMER(xP -1, yP+nPSH-1, xP, yP))  
  36.     {  
  37.       pcCULeft = NULL;  
  38.     }  
  39.   }  
  40.   PartSize partSize = getPartitionSize( uiAbsPartIdx );  
  41.   if (!(uiPUIdx == 1 && (partSize == SIZE_Nx2N || partSize == SIZE_nLx2N || partSize == SIZE_nRx2N)))  
  42.   {  
  43.   if ( pcCULeft && !pcCULeft->isIntra( uiLeftPartIdx ) )  
  44. #endif  
  45.   {  
  46.     abCandIsInter[iCount] = true;  
  47.     // get Inter Dir  
  48.     puhInterDirNeighbours[iCount] = pcCULeft->getInterDir( uiLeftPartIdx ); //!< inter dir分L0,L1,Bi  
  49.     // get Mv from Left,将pcCULeft的MV存放到pcMvFieldNeighbours中  
  50.     pcCULeft->getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );  
  51.     if ( getSlice()->isInterB() )  
  52.     {  
  53.       pcCULeft->getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] );  
  54.     }  
  55.     if ( mrgCandIdx == iCount )  
  56.     {  
  57.       return;  
  58.     }  
  59.     iCount ++;  
  60.   }  
  61. #if !MERGE_CLEANUP_AND_K0197  
  62.   }  
  63. #endif  
  64.     
  65.   // early termination  
  66.   if (iCount == getSlice()->getMaxNumMergeCand())   
  67.   {  
  68.     return;  
  69.   }  
  70.   // above  
  71.   UInt uiAbovePartIdx = 0;  
  72.   TComDataCU* pcCUAbove = 0;  
  73. #if LINEBUF_CLEANUP  
  74.   pcCUAbove = getPUAbove( uiAbovePartIdx, uiPartIdxRT, truefalse );  
  75. #else  
  76.   pcCUAbove = getPUAbove( uiAbovePartIdx, uiPartIdxRT, truefalsetrue );  
  77. #endif  
  78. #if MERGE_CLEANUP_AND_K0197 //!<   
  79.   Bool isAvailableB1 = pcCUAbove &&  
  80.   pcCUAbove->isDiffMER(xP+nPSW-1, yP-1, xP, yP) &&  
  81.   !( uiPUIdx == 1 && (cCurPS == SIZE_2NxN || cCurPS == SIZE_2NxnU || cCurPS == SIZE_2NxnD) ) &&  
  82.   !pcCUAbove->isIntra( uiAbovePartIdx );  
  83.   if ( isAvailableB1 && (!isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAbove, uiAbovePartIdx ) ) )  
  84. #else//!< 如果A1可用,则检查A1和B1的MV是否相同,否则不需要检查  
  85.   if (pcCUAbove)  
  86.   {  
  87.     if (!pcCUAbove->isDiffMER(xP+nPSW-1, yP-1, xP, yP))  
  88.     {  
  89.       pcCUAbove = NULL;  
  90.     }  
  91.   }  
  92.   if ( pcCUAbove && !pcCUAbove->isIntra( uiAbovePartIdx )   
  93.     && !(uiPUIdx == 1 && (cCurPS == SIZE_2NxN || cCurPS == SIZE_2NxnU || cCurPS == SIZE_2NxnD))  
  94.     && ( !pcCULeft || pcCULeft->isIntra( uiLeftPartIdx ) || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAbove, uiAbovePartIdx ) ) )  
  95. #endif  
  96.   {  
  97.     abCandIsInter[iCount] = true;  
  98.     // get Inter Dir  
  99.     puhInterDirNeighbours[iCount] = pcCUAbove->getInterDir( uiAbovePartIdx );  
  100.     // get Mv from Above  
  101.     pcCUAbove->getMvField( pcCUAbove, uiAbovePartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );  
  102.     if ( getSlice()->isInterB() )  
  103.     {  
  104.       pcCUAbove->getMvField( pcCUAbove, uiAbovePartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] );  
  105.     }  
  106.     if ( mrgCandIdx == iCount )  
  107.     {  
  108.       return;  
  109.     }  
  110.     iCount ++;  
  111.   }  
  112.   // early termination  
  113.   if (iCount == getSlice()->getMaxNumMergeCand())   
  114.   {  
  115.     return;  
  116.   }  
  117.   
  118.   // above right  
  119.   UInt uiAboveRightPartIdx = 0;  
  120.   TComDataCU* pcCUAboveRight = 0;  
  121. #if LINEBUF_CLEANUP  
  122.   pcCUAboveRight = getPUAboveRight( uiAboveRightPartIdx, uiPartIdxRT, truefalse );  
  123. #else  
  124.   pcCUAboveRight = getPUAboveRight( uiAboveRightPartIdx, uiPartIdxRT, truefalsetrue );  
  125. #endif  
  126. #if MERGE_CLEANUP_AND_K0197  
  127.   Bool isAvailableB0 = pcCUAboveRight &&  
  128.   pcCUAboveRight->isDiffMER(xP+nPSW, yP-1, xP, yP) &&  
  129.   !pcCUAboveRight->isIntra( uiAboveRightPartIdx );  
  130.   if ( isAvailableB0 && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveRight, uiAboveRightPartIdx ) ) )  
  131. #else//!< 如果B1可用,则检查B1和B0的MV是否相同,否则不需要检查  
  132.   if (pcCUAboveRight)  
  133.   {  
  134.     if (!pcCUAboveRight->isDiffMER(xP+nPSW, yP-1, xP, yP))  
  135.     {  
  136.       pcCUAboveRight = NULL;  
  137.     }  
  138.   }  
  139.   if ( pcCUAboveRight && !pcCUAboveRight->isIntra( uiAboveRightPartIdx ) && ( !pcCUAbove || pcCUAbove->isIntra( uiAbovePartIdx ) || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveRight, uiAboveRightPartIdx ) ) )  
  140. #endif  
  141.   {  
  142.     abCandIsInter[iCount] = true;  
  143.     // get Inter Dir  
  144.     puhInterDirNeighbours[iCount] = pcCUAboveRight->getInterDir( uiAboveRightPartIdx );  
  145.     // get Mv from AboveRight  
  146.     pcCUAboveRight->getMvField( pcCUAboveRight, uiAboveRightPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );  
  147.     if ( getSlice()->isInterB() )  
  148.     {  
  149.       pcCUAboveRight->getMvField( pcCUAboveRight, uiAboveRightPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] );  
  150.     }  
  151.     if ( mrgCandIdx == iCount )  
  152.     {  
  153.       return;  
  154.     }  
  155.     iCount ++;  
  156.   }  
  157.   // early termination  
  158.   if (iCount == getSlice()->getMaxNumMergeCand())   
  159.   {  
  160.     return;  
  161.   }  
  162.   
  163.   //left bottom  
  164.   UInt uiLeftBottomPartIdx = 0;  
  165.   TComDataCU* pcCULeftBottom = 0;  
  166.   pcCULeftBottom = this->getPUBelowLeft( uiLeftBottomPartIdx, uiPartIdxLB, truefalse );  
  167. #if MERGE_CLEANUP_AND_K0197  
  168.   Bool isAvailableA0 = pcCULeftBottom &&  
  169.   pcCULeftBottom->isDiffMER(xP-1, yP+nPSH, xP, yP) &&  
  170.   !pcCULeftBottom->isIntra( uiLeftBottomPartIdx ) ;  
  171.   if ( isAvailableA0 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCULeftBottom, uiLeftBottomPartIdx ) ) )  
  172. #else//!< 如果A1可用,则检查A1和A0的MV是否相同,否则不需要检查  
  173.   if (pcCULeftBottom)  
  174.   {  
  175.     if (!pcCULeftBottom->isDiffMER(xP-1, yP+nPSH, xP, yP))  
  176.     {  
  177.       pcCULeftBottom = NULL;  
  178.     }  
  179.   }  
  180.   if ( pcCULeftBottom && !pcCULeftBottom->isIntra( uiLeftBottomPartIdx ) && ( !pcCULeft || pcCULeft->isIntra( uiLeftPartIdx ) || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCULeftBottom, uiLeftBottomPartIdx ) ) )  
  181. #endif  
  182.   {  
  183.     abCandIsInter[iCount] = true;  
  184.     // get Inter Dir  
  185.     puhInterDirNeighbours[iCount] = pcCULeftBottom->getInterDir( uiLeftBottomPartIdx );  
  186.     // get Mv from LeftBottom  
  187.     pcCULeftBottom->getMvField( pcCULeftBottom, uiLeftBottomPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );  
  188.     if ( getSlice()->isInterB() )  
  189.     {  
  190.       pcCULeftBottom->getMvField( pcCULeftBottom, uiLeftBottomPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] );  
  191.     }  
  192.     if ( mrgCandIdx == iCount )  
  193.     {  
  194.       return;  
  195.     }  
  196.     iCount ++;  
  197.   }  
  198.   // early termination  
  199.   if (iCount == getSlice()->getMaxNumMergeCand())   
  200.   {  
  201.     return;  
  202.   }  
  203.   // above left   
  204.   if( iCount < 4 )  
  205.   {  
  206.     UInt uiAboveLeftPartIdx = 0;  
  207.     TComDataCU* pcCUAboveLeft = 0;  
  208. #if LINEBUF_CLEANUP  
  209.     pcCUAboveLeft = getPUAboveLeft( uiAboveLeftPartIdx, uiAbsPartAddr, truefalse );  
  210. #else  
  211.     pcCUAboveLeft = getPUAboveLeft( uiAboveLeftPartIdx, uiAbsPartAddr, truefalsetrue );  
  212. #endif  
  213. #if MERGE_CLEANUP_AND_K0197  
  214.     Bool isAvailableB2 = pcCUAboveLeft &&  
  215.     pcCUAboveLeft->isDiffMER(xP-1, yP-1, xP, yP) &&  
  216.     !pcCUAboveLeft->isIntra( uiAboveLeftPartIdx );  
  217.     if ( isAvailableB2 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) )  
  218.         && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) ) )  
  219. #else//!< 分别将B2与A1、B1的mv进行比较  
  220.     if (pcCUAboveLeft)  
  221.     {  
  222.       if (!pcCUAboveLeft->isDiffMER(xP-1, yP-1, xP, yP))  
  223.       {  
  224.         pcCUAboveLeft = NULL;  
  225.       }  
  226.     }  
  227.     if( pcCUAboveLeft && !pcCUAboveLeft->isIntra( uiAboveLeftPartIdx )  
  228.      && ( !pcCULeft || pcCULeft->isIntra( uiLeftPartIdx ) || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) )  
  229.      && ( !pcCUAbove || pcCUAbove->isIntra( uiAbovePartIdx ) || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveLeft, uiAboveLeftPartIdx ) )  
  230.      )  
  231. #endif  
  232.     {  
  233.       abCandIsInter[iCount] = true;  
  234.       // get Inter Dir  
  235.       puhInterDirNeighbours[iCount] = pcCUAboveLeft->getInterDir( uiAboveLeftPartIdx );  
  236.       // get Mv from AboveLeft  
  237.       pcCUAboveLeft->getMvField( pcCUAboveLeft, uiAboveLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );  
  238.       if ( getSlice()->isInterB() )  
  239.       {  
  240.         pcCUAboveLeft->getMvField( pcCUAboveLeft, uiAboveLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] );  
  241.       }  
  242.       if ( mrgCandIdx == iCount )  
  243.       {  
  244.         return;  
  245.       }  
  246.       iCount ++;  
  247.     }  
  248.   }  
  249.   // early termination  
  250.   if (iCount == getSlice()->getMaxNumMergeCand()) //!< 如果可用的merge candidates达到预设的最大值(5),则提前退出  
  251.   {  
  252.     return;  
  253.   }  
  254.   if ( getSlice()->getEnableTMVPFlag()) //!< default is 1  
  255.   {  
  256.     //>> MTK colocated-RightBottom  
  257.     UInt uiPartIdxRB;  
  258.     Int uiLCUIdx = getAddr();  
  259.   
  260.     deriveRightBottomIdx( uiPUIdx, uiPartIdxRB ); //!< 当前PU的右下部的地址  
  261.   
  262.     UInt uiAbsPartIdxTmp = g_auiZscanToRaster[uiPartIdxRB];  
  263.     UInt uiNumPartInCUWidth = m_pcPic->getNumPartInWidth(); //!< CU以partition为单位的宽度  
  264.   
  265.     TComMv cColMv;  
  266.     Int iRefIdx;  
  267.   
  268.     if      ( ( m_pcPic->getCU(m_uiCUAddr)->getCUPelX() + g_auiRasterToPelX[uiAbsPartIdxTmp] + m_pcPic->getMinCUWidth() ) >= m_pcSlice->getSPS()->getPicWidthInLumaSamples() )  // image boundary check  
  269.     {  
  270.       uiLCUIdx = -1;  
  271.     }//!< 横坐标超出图像边界  
  272.     else if ( ( m_pcPic->getCU(m_uiCUAddr)->getCUPelY() + g_auiRasterToPelY[uiAbsPartIdxTmp] + m_pcPic->getMinCUHeight() ) >= m_pcSlice->getSPS()->getPicHeightInLumaSamples() )  
  273.     {  
  274.       uiLCUIdx = -1;  
  275.     }//!< 纵坐标超出图像边界  
  276.     else  
  277.     {  
  278.       if ( ( uiAbsPartIdxTmp % uiNumPartInCUWidth < uiNumPartInCUWidth - 1 ) &&           // is not at the last column of LCU   
  279.         ( uiAbsPartIdxTmp / uiNumPartInCUWidth < m_pcPic->getNumPartInHeight() - 1 ) ) // is not at the last row    of LCU  
  280.       {//!< 不在LCU的最后一列且不在LCU的最后一行,SIZE_NxN的第1个PU  
  281.         uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + uiNumPartInCUWidth + 1 ]; //!< 下一行+1  
  282.         uiLCUIdx = getAddr(); //!< 与当前PU属于相同的CU  
  283.       }  
  284.       else if ( uiAbsPartIdxTmp % uiNumPartInCUWidth < uiNumPartInCUWidth - 1 )           // is not at the last column of LCU But is last row of LCU  
  285.       {//!< 不在LCU的最后一列但在LCU的最后一行,SIZE_Nx2N的第1个PU,SIZE_NxN的第3个PU,SIZE_nLx2N的第1个PU,SIZE_nRx2N的第1个PU  
  286.         uiAbsPartAddr = g_auiRasterToZscan[ (uiAbsPartIdxTmp + uiNumPartInCUWidth + 1) % m_pcPic->getNumPartInCU() ];  
  287.         uiLCUIdx = -1 ;   
  288.       }  
  289.       else if ( uiAbsPartIdxTmp / uiNumPartInCUWidth < m_pcPic->getNumPartInHeight() - 1 ) // is not at the last row of LCU But is last column of LCU  
  290.       {//!< 不在LCU的最后一行但在LCU的最后一列,SIZE_2NxN的第1个PU,SIZE_NxN的第2个PU,SIZE_2NxnU的第1个PU,SIZE_2NxnD的第1个PU  
  291.         uiAbsPartAddr = g_auiRasterToZscan[ uiAbsPartIdxTmp + 1 ];  
  292.         uiLCUIdx = getAddr() + 1;  
  293.       }  
  294.       else //is the right bottom corner of LCU,SIZE_2Nx2N                         
  295.       {  
  296.         uiAbsPartAddr = 0;  
  297.         uiLCUIdx = -1 ;   
  298.       }  
  299.     }  
  300.     iRefIdx = 0;  
  301.   
  302.     Bool bExistMV = false;  
  303.     UInt uiPartIdxCenter;  
  304.     UInt uiCurLCUIdx = getAddr();  
  305.     xDeriveCenterIdx( uiPUIdx, uiPartIdxCenter ); //!< 根据uiPUIdx计算PU的中心地址uiPartIdxCenter  
  306.     //! 获取colocated CU的mv,并经scaled过的。  
  307.     bExistMV = uiLCUIdx >= 0 && xGetColMVP( REF_PIC_LIST_0, uiLCUIdx, uiAbsPartAddr, cColMv, iRefIdx );  
  308.     if( bExistMV == false )  
  309.     {  
  310.       bExistMV = xGetColMVP( REF_PIC_LIST_0, uiCurLCUIdx, uiPartIdxCenter,  cColMv, iRefIdx );  
  311.     }  
  312.     if( bExistMV )  
  313.     {  
  314.       UInt uiArrayAddr = iCount;  
  315.       abCandIsInter[uiArrayAddr] = true;  
  316.       pcMvFieldNeighbours[uiArrayAddr << 1].setMvField( cColMv, iRefIdx );  
  317.   
  318.       if ( getSlice()->isInterB() )  
  319.       {         
  320.         iRefIdx = 0;  
  321.         bExistMV = uiLCUIdx >= 0 && xGetColMVP( REF_PIC_LIST_1, uiLCUIdx, uiAbsPartAddr, cColMv, iRefIdx);  
  322.         if( bExistMV == false )  
  323.         {  
  324.           bExistMV = xGetColMVP( REF_PIC_LIST_1, uiCurLCUIdx, uiPartIdxCenter,  cColMv, iRefIdx );  
  325.         }  
  326.         if( bExistMV )  
  327.         {  
  328.           pcMvFieldNeighbours[ ( uiArrayAddr << 1 ) + 1 ].setMvField( cColMv, iRefIdx );  
  329.           puhInterDirNeighbours[uiArrayAddr] = 3; //!< Bi  
  330.         }  
  331.         else  
  332.         {  
  333.           puhInterDirNeighbours[uiArrayAddr] = 1; //!< L0  
  334.         }  
  335.       }  
  336.       else  
  337.       {  
  338.         puhInterDirNeighbours[uiArrayAddr] = 1; //!< L0  
  339.       }  
  340.       if ( mrgCandIdx == iCount )  
  341.       {  
  342.         return;  
  343.       }  
  344.       iCount++;  
  345.     }  
  346.     uiIdx++;  
  347.   
  348.   }  
  349.   // early termination  
  350.   if (iCount == getSlice()->getMaxNumMergeCand())   
  351.   {  
  352.     return;  
  353.   }  
  354.   UInt uiArrayAddr = iCount;  
  355.   UInt uiCutoff = uiArrayAddr;  
  356.       
  357.   if ( getSlice()->isInterB())  
  358.   {//! 参考draft Table 8-6 ---- Specification of l0CandIdx and l1CandIdx  
  359.     UInt uiPriorityList0[12] = {0 , 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3};  
  360.     UInt uiPriorityList1[12] = {1 , 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2};  
  361.   
  362.     for (Int idx=0; idx<uiCutoff*(uiCutoff-1) && uiArrayAddr!= getSlice()->getMaxNumMergeCand(); idx++)  
  363.     {  
  364.       Int i = uiPriorityList0[idx]; Int j = uiPriorityList1[idx];  
  365.       if (abCandIsInter[i] && abCandIsInter[j]&& (puhInterDirNeighbours[i]&0x1)&&(puhInterDirNeighbours[j]&0x2))  
  366.       {  
  367.         abCandIsInter[uiArrayAddr] = true;  
  368.         puhInterDirNeighbours[uiArrayAddr] = 3;  
  369.   
  370.         // get Mv from cand[i] and cand[j]  
  371.         pcMvFieldNeighbours[uiArrayAddr << 1].setMvField(pcMvFieldNeighbours[i<<1].getMv(), pcMvFieldNeighbours[i<<1].getRefIdx());  
  372.         pcMvFieldNeighbours[( uiArrayAddr << 1 ) + 1].setMvField(pcMvFieldNeighbours[(j<<1)+1].getMv(), pcMvFieldNeighbours[(j<<1)+1].getRefIdx());  
  373.   
  374.         Int iRefPOCL0 = m_pcSlice->getRefPOC( REF_PIC_LIST_0, pcMvFieldNeighbours[(uiArrayAddr<<1)].getRefIdx() );  
  375.         Int iRefPOCL1 = m_pcSlice->getRefPOC( REF_PIC_LIST_1, pcMvFieldNeighbours[(uiArrayAddr<<1)+1].getRefIdx() );  
  376.         if (iRefPOCL0 == iRefPOCL1 && pcMvFieldNeighbours[(uiArrayAddr<<1)].getMv() == pcMvFieldNeighbours[(uiArrayAddr<<1)+1].getMv())  
  377.         {  
  378.           abCandIsInter[uiArrayAddr] = false;  
  379.         }  
  380.         else  
  381.         {  
  382.           uiArrayAddr++;  
  383.         }  
  384.       }  
  385.     }  
  386.   }  
  387.   // early termination  
  388.   if (uiArrayAddr == getSlice()->getMaxNumMergeCand())   
  389.   {  
  390.     return;  
  391.   }  
  392.   //! 当可用的merge candidates数目仍小于预设值时,将余量均设置为零运动矢量  
  393.   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);  
  394.   Int r = 0;  
  395.   Int refcnt = 0;  
  396.   while (uiArrayAddr < getSlice()->getMaxNumMergeCand())  
  397.   {  
  398.     abCandIsInter[uiArrayAddr] = true;  
  399.     puhInterDirNeighbours[uiArrayAddr] = 1;  
  400.     pcMvFieldNeighbours[uiArrayAddr << 1].setMvField( TComMv(0, 0), r); //!< 设置为零运动矢量  
  401.   
  402.     if ( getSlice()->isInterB() )  
  403.     {  
  404.       puhInterDirNeighbours[uiArrayAddr] = 3;  
  405.       pcMvFieldNeighbours[(uiArrayAddr << 1) + 1].setMvField(TComMv(0, 0), r);  
  406.     }  
  407.     uiArrayAddr++;  
  408.     if ( refcnt == iNumRefIdx - 1 ) //!< 达到参考帧列表的参考帧数  
  409.     {  
  410.       r = 0;  
  411.     }  
  412.     else  
  413.     {  
  414.       ++r;  
  415.       ++refcnt;  
  416.     }  
  417.   }  
  418.   
  419.   numValidMergeCand = uiArrayAddr;  
  420. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值