HEVC代码学习32:getInterMergeCandidates函数
来源:互联网 发布:cmm软件内涵 编辑:程序博客网 时间:2024/05/19 04:51
今天来看xCheckRDCostMerge2Nx2N函数中提到的重要函数getInterMergeCandidates,其功能是创建merge候选列表,这里重点来看空域候选列表的建立。
首先来回忆一下merge的空域候选列表。merge候选列表长度为5,空域最多提供4个候选,按顺序依次遍历A1-B1-B0-A0-B2,选出4个候选填入候选列表。注意,空域最终可能提供的候选数量可能少于4个。
下面来看getInterMergeCandidates工作流程:
1.初始化准备工作。
2.建立空域候选列表,按顺序依次遍历A1-B1-B0-A0-B2位置PU,对每个位置进行以下操作,选出最多4个候选。
(1)检测是否有效
(2)若有效则写入候选列表记录其MV
(3)检测列表是否已满
3.建立时域候选列表。
4.为B Slice建立组合列表。
5.候选列表未满时,用0填充。
代码分析:
//! Construct a list of merging candidates 构造merge候选列表Void TComDataCU::getInterMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMvFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, Int mrgCandIdx ){ /******************************************初始化准备工作**************************************/ UInt uiAbsPartAddr = m_absZIdxInCtu + uiAbsPartIdx; //当前CU的ZScan地址 Bool abCandIsInter[ MRG_MAX_NUM_CANDS ]; //MRG_MAX_NUM_CANDS最大候选数为5 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(); //最大有效候选数为5 // compute the location of the current PU 计算当前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 ); //左上右上块索引 deriveLeftBottomIdxGeneral( uiAbsPartIdx, uiPUIdx, uiPartIdxLB ); //左下块索引 /******************************************建立空域候选列表**************************************/ //left 左侧 UInt uiLeftPartIdx = 0; TComDataCU* pcCULeft = 0; pcCULeft = getPULeft( uiLeftPartIdx, uiPartIdxLB ); //获取左侧PU //判断A1有效性 Bool isAvailableA1 = pcCULeft && //左侧PU是否有效 pcCULeft->isDiffMER(xP -1, yP+nPSH-1, xP, yP) && //左侧PU与当前PU是否在同一运动估计区域 !( uiPUIdx == 1 && (cCurPS == SIZE_Nx2N || cCurPS == SIZE_nLx2N || cCurPS == SIZE_nRx2N) ) && //分割模式判断 pcCULeft->isInter( uiLeftPartIdx ) ; //帧间预测是否有效 if ( isAvailableA1 ) //A1有效 { abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCULeft->getInterDir( uiLeftPartIdx ); //获取帧间预测方向 // get Mv from Left pcCULeft->getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); //获取左侧PU list0的MV if ( getSlice()->isInterB() ) //双向预测时,获取list1的MV { pcCULeft->getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] ); } if ( mrgCandIdx == iCount ) { return; } iCount ++; } // early termination 达到最大候选数则退出 if (iCount == getSlice()->getMaxNumMergeCand()) { return; } // above 上方 UInt uiAbovePartIdx = 0; TComDataCU* pcCUAbove = 0; 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 ); if ( isAvailableB1 && (!isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCUAbove, uiAbovePartIdx ) ) ) { abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCUAbove->getInterDir( uiAbovePartIdx ); // get Mv from Left pcCUAbove->getMvField( pcCUAbove, uiAbovePartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); if ( getSlice()->isInterB() ) { pcCUAbove->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 右上 UInt uiAboveRightPartIdx = 0; TComDataCU* pcCUAboveRight = 0; pcCUAboveRight = getPUAboveRight( uiAboveRightPartIdx, uiPartIdxRT ); //判断B0有效性 Bool isAvailableB0 = pcCUAboveRight && pcCUAboveRight->isDiffMER(xP+nPSW, yP-1, xP, yP) && pcCUAboveRight->isInter( uiAboveRightPartIdx ); if ( isAvailableB0 && ( !isAvailableB1 || !pcCUAbove->hasEqualMotion( uiAbovePartIdx, pcCUAboveRight, uiAboveRightPartIdx ) ) ) { abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCUAboveRight->getInterDir( uiAboveRightPartIdx ); // get Mv from Left pcCUAboveRight->getMvField( pcCUAboveRight, uiAboveRightPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); if ( getSlice()->isInterB() ) { pcCUAboveRight->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 左下 UInt uiLeftBottomPartIdx = 0; TComDataCU* pcCULeftBottom = 0; pcCULeftBottom = this->getPUBelowLeft( uiLeftBottomPartIdx, uiPartIdxLB ); //判断A0有效性 Bool isAvailableA0 = pcCULeftBottom && pcCULeftBottom->isDiffMER(xP-1, yP+nPSH, xP, yP) && pcCULeftBottom->isInter( uiLeftBottomPartIdx ) ; if ( isAvailableA0 && ( !isAvailableA1 || !pcCULeft->hasEqualMotion( uiLeftPartIdx, pcCULeftBottom, uiLeftBottomPartIdx ) ) ) { abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCULeftBottom->getInterDir( uiLeftBottomPartIdx ); // get Mv from Left pcCULeftBottom->getMvField( pcCULeftBottom, uiLeftBottomPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); if ( getSlice()->isInterB() ) { pcCULeftBottom->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 左上 if( iCount < 4 ) //空域最多提供4个候选 { UInt uiAboveLeftPartIdx = 0; TComDataCU* pcCUAboveLeft = 0; pcCUAboveLeft = getPUAboveLeft( uiAboveLeftPartIdx, uiAbsPartAddr ); //判断B2有效性 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 ) ) ) { abCandIsInter[iCount] = true; // get Inter Dir puhInterDirNeighbours[iCount] = pcCUAboveLeft->getInterDir( uiAboveLeftPartIdx ); // get Mv from Left pcCUAboveLeft->getMvField( pcCUAboveLeft, uiAboveLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] ); if ( getSlice()->isInterB() ) { pcCUAboveLeft->getMvField( pcCUAboveLeft, uiAboveLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] ); } if ( mrgCandIdx == iCount ) { return; } iCount ++; } } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { return; } /******************************************建立时域候选列表**************************************/ //由时域列表最多提供1个候选 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() ) ) { 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 ); bExistMV = ctuRsAddr >= 0 && xGetColMVP( REF_PIC_LIST_0, ctuRsAddr, uiAbsPartAddr, cColMv, iRefIdx ); if( bExistMV == false ) { bExistMV = xGetColMVP( REF_PIC_LIST_0, getCtuRsAddr(), uiPartIdxCenter, cColMv, iRefIdx ); } if( bExistMV ) { dir |= 1; pcMvFieldNeighbours[ 2 * uiArrayAddr ].setMvField( cColMv, iRefIdx ); } if ( getSlice()->isInterB() ) { 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 ( mrgCandIdx == iCount ) { return; } iCount++; } } // early termination if (iCount == getSlice()->getMaxNumMergeCand()) { return; } UInt uiArrayAddr = iCount; UInt uiCutoff = uiArrayAddr; /******************************************为B Slice建立组合列表**************************************/ //给B Slice建立组合列表 if ( getSlice()->isInterB() ) { 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); /******************************************列表未满,用0填充**************************************/ Int r = 0; Int refcnt = 0; while (uiArrayAddr < getSlice()->getMaxNumMergeCand()) { 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;}
阅读全文
0 0
- HEVC代码学习32:getInterMergeCandidates函数
- HEVC代码学习9:getInterMergeCandidates函数
- HEVC帧间预测之一——TComDataCU::getInterMergeCandidates函数分析
- 【转载】HEVC帧间预测之一——TComDataCU::getInterMergeCandidates函数分析
- HEVC代码学习2:TAppEncTop::encode函数
- HEVC代码学习3:TEncTop::encode函数
- HEVC代码学习7:xPatternSearchFracDIF函数
- HEVC代码学习8:xMotionEstimation函数
- HEVC代码学习11:xCompressCU函数
- HEVC代码学习12:xCheckRDCostInter函数
- HEVC代码学习13:predInterSearch函数
- HEVC代码学习14:motionCompensation函数
- HEVC代码学习15:AMVP相关函数
- HEVC代码学习20:xPatternSearchFast函数
- HEVC代码学习21:xTZSearch函数
- HEVC代码学习22:xTZSearchHelp函数
- HEVC代码学习23:xTZ8PointDiamondSearch函数
- HEVC代码学习24:encodeResAndCalcRdInterCU函数
- C++多态(virtual)(2)
- DevOps的八荣八耻
- 【python学习记录】--1--对图片的基本操作
- 存储器(四) -- 汉明码
- Sass and Compass in Action.pdf 英文原版 免费下载
- HEVC代码学习32:getInterMergeCandidates函数
- upLoadFileTest
- Android framework学习笔记 -- 原生分屏原理
- UVA 11889 Benefit——gcd
- 油田问题 UVA 572
- 类的构造函数、拷贝构造函数、赋值函数、析构函数,分别在何时调用。
- 一张图读懂 Java 多线程
- Java ImageIO图片操作
- 自制嵌入式GUI-基于freeRTOS