设为首页 加入收藏

TOP

HEVC帧间预测之一――TComDataCU::getInterMergeCandidates函数分析(一)
2014-11-24 07:27:15 】 浏览:417
Tags:HEVC 预测 之一 TComDataCU::getInterMergeCandidates 函数分析
从今天开始,正式转入到帧间预测方向。由于帧间预测涉及到的方面广且复杂,所以我的理解出现错误的情况可能会更多,请大家以辩证的眼光来看待我的帖子,有问题欢迎大家批评指正。
大家都知道xCompressCU是实际进行预测编码的函数,故很容易就能锁定帧间预测的一个大致范围,在研究了帧内预测的基础上,相信很快就能在该函数中找到与帧间预测相关的函数:xCheckRDCostInter,xCheckRDCostMerge2Nx2N。前者进行除了merge模式以外的所有帧间预测,后者则是针对merge模式的。由于merge模式相对于H.264来说是个新事物,我们考虑先从研究它入手。
进入到xCheckRDCostMerge2Nx2N函数后,开头有一个比较重要的函数getInterMergeCandidates,它的功能是创建一个merge list,在该模式中是个很重要的函数,故我们先讨论它。下面按照惯例,给出我对这个函数的注释:
[cpp]
Void TComDataCU::getInterMergeCandidates( UInt uiAbsPartIdx, UInt uiPUIdx, TComMvField* pcMvFieldNeighbours, UChar* puhInterDirNeighbours, Int& numValidMergeCand, Int mrgCandIdx )
{
UInt uiAbsPartAddr = m_uiAbsIdxInLCU + uiAbsPartIdx; //!< 当前CU的ZScan地址
UInt uiIdx = 1;
Bool abCandIsInter[ MRG_MAX_NUM_CANDS ];
for( UInt ui = 0; ui < getSlice()->getMaxNumMergeCand(); ++ui ) //!< m_maxNumMergeCand = 5
{
abCandIsInter[ui] = false;
}
numValidMergeCand = getSlice()->getMaxNumMergeCand(); //!< 5
// compute the location of the current PU
Int xP, yP, nPSW, nPSH;
this->getPartPosition(uiPUIdx, xP, yP, nPSW, nPSH); //!< 获得当前PU的地址和大小
Int iCount = 0; //!< 统计Merge candidate的个数
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, true, false );
#if MERGE_CLEANUP_AND_K0197 //!< 在有多个PU在一个CU中的时候,去除第二个PU对A1和B1的依赖性
Bool isAvailableA1 = pcCULeft &&
pcCULeft->isDiffMER(xP -1, yP+nPSH-1, xP, yP) && //!< 当前PU和它的相邻PU不在同一个ME区域
!( uiPUIdx == 1 && (cCurPS == SIZE_Nx2N || cCurPS == SIZE_nLx2N || cCurPS == SIZE_nRx2N) ) &&
!pcCULeft->isIntra( uiLeftPartIdx ) ;
if ( isAvailableA1 )
#else
if (pcCULeft)
{
if (!pcCULeft->isDiffMER(xP -1, yP+nPSH-1, xP, yP))
{
pcCULeft = NULL;
}
}
PartSize partSize = getPartitionSize( uiAbsPartIdx );
if (!(uiPUIdx == 1 && (partSize == SIZE_Nx2N || partSize == SIZE_nLx2N || partSize == SIZE_nRx2N)))
{
if ( pcCULeft && !pcCULeft->isIntra( uiLeftPartIdx ) )
#endif
{
abCandIsInter[iCount] = true;
// get Inter Dir
puhInterDirNeighbours[iCount] = pcCULeft->getInterDir( uiLeftPartIdx ); //!< inter dir分L0,L1,Bi
// get Mv from Left,将pcCULeft的MV存放到pcMvFieldNeighbours中
pcCULeft->getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_0, pcMvFieldNeighbours[iCount<<1] );
if ( getSlice()->isInterB() )
{
pcCULeft->getMvField( pcCULeft, uiLeftPartIdx, REF_PIC_LIST_1, pcMvFieldNeighbours[(iCount<<1)+1] );
}
if ( mrgCandIdx == iCount )
{
return;
}
iCount ++;
}
#if !MERGE_CLEANUP_AND_K0197
}
#endif
// early termination
if (iCount == getSlice()->getMaxNumMergeCand())
{
return;
}
// above
UInt uiAbovePartIdx = 0;
TComDataCU* pcCUAbove = 0;
#if LINEBUF_CLEANUP
pcCUAbove = getPUAbove( uiAbovePartIdx, uiPartIdxRT, true, false );
#else
pcCUAbove = getPUAbove( uiAbovePartIdx, uiPartIdxRT, true, false, true );
#endif
#if MERGE_CLEANUP_AND_K0197 //!<
Bool isAvailableB1 = pcCUAbove &&
pcCUAbove->isDiffMER(xP+nPSW-1, yP-1, xP, yP) &&
!( uiPUIdx == 1 && (cC
首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇输出对应的那一天是这一年的第几.. 下一篇合并有序链表

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目