HEVC代码学习15:AMVP相关函数
来源:互联网 发布:大数据平台 联想 网易 编辑:程序博客网 时间:2024/05/16 04:20
在HEVC中,使用了AMVP技术,利用空域和时域上的运动向量的相关性,为当前PU建立候选预测MV(MVP)列表。编码器从中选出最优的预测MV,并对MV进行差分编码;解码端会构造相同的列表,仅需要运动向量残差(MVD)与预测MV在该列表中的序号即可计算当前PU的MV。
简单来说,AMVP的作用就是建立当前PU的候选MVP列表,运动估计ME会从该列表中找到率失真最优的MVP作为起点,进行搜索。
AMVP整体处理在predInterSearch中完成,主要调用的函数有xEstimateMvPredAMVP,xMotionEstimation,xCopyAMVPInfo,xCheckBestMVP。
主要包含4个过程:
1.调用xEstimateMvPredAMVP建立候选列表并选出最优候选MVP。其中候选列表的建立是通过fillMvpCand函数完成,详见:http://blog.csdn.net/lin453701006/article/details/78419479。
2.调用xMotionEstimation进行运动估计找到最优MV。
3.调用xCheckBestMVP比较更新最优MVP。
4.更新失真和bit信息。
xMotionEstimation在之前已经进行了学习,xCopyAMVPInfo代码很少,很容易看懂,就是完成了AMVP信息的复制,不再详细学习了。下面来学习一下另外两个函数。
xEstimateMvPredAMVP
xEstimateMvPredAMVP首先调用fillMvpCand构造候选列表,然后计算每一个候选的Cost,最后比较Cost找到最优MV设为最优MVP。
// AMVPVoid TEncSearch::xEstimateMvPredAMVP( TComDataCU* pcCU, TComYuv* pcOrgYuv, UInt uiPartIdx, RefPicList eRefPicList, Int iRefIdx, TComMv& rcMvPred, Bool bFilled, Distortion* puiDistBiP ){ AMVPInfo* pcAMVPInfo = pcCU->getCUMvField(eRefPicList)->getAMVPInfo(); //获取AMVP信息 TComMv cBestMv; Int iBestIdx = 0; TComMv cZeroMv; TComMv cMvPred; Distortion uiBestCost = std::numeric_limits<Distortion>::max(); UInt uiPartAddr = 0; Int iRoiWidth, iRoiHeight; Int i; pcCU->getPartIndexAndSize( uiPartIdx, uiPartAddr, iRoiWidth, iRoiHeight ); //获取PU的地址和尺寸 // Fill the MV Candidates if (!bFilled) { pcCU->fillMvpCand( uiPartIdx, uiPartAddr, eRefPicList, iRefIdx, pcAMVPInfo ); //构造AMVP候选列表 } // initialize Mvp index & Mvp iBestIdx = 0; cBestMv = pcAMVPInfo->m_acMvCand[0]; //初始化最优MVP为第一个MVP if (pcAMVPInfo->iN <= 1) { rcMvPred = cBestMv; pcCU->setMVPIdxSubParts( iBestIdx, eRefPicList, uiPartAddr, uiPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( pcAMVPInfo->iN, eRefPicList, uiPartAddr, uiPartIdx, pcCU->getDepth(uiPartAddr)); if(pcCU->getSlice()->getMvdL1ZeroFlag() && eRefPicList==REF_PIC_LIST_1) { (*puiDistBiP) = xGetTemplateCost( pcCU, uiPartAddr, pcOrgYuv, &m_cYuvPredTemp, rcMvPred, 0, AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdx, iRoiWidth, iRoiHeight); } return; } if (bFilled) { assert(pcCU->getMVPIdx(eRefPicList,uiPartAddr) >= 0); rcMvPred = pcAMVPInfo->m_acMvCand[pcCU->getMVPIdx(eRefPicList,uiPartAddr)]; return; } m_cYuvPredTemp.clear(); //-- Check Minimum Cost. 比较代价,找到最优MVP for ( i = 0 ; i < pcAMVPInfo->iN; i++) { Distortion uiTmpCost; uiTmpCost = xGetTemplateCost( pcCU, uiPartAddr, pcOrgYuv, &m_cYuvPredTemp, pcAMVPInfo->m_acMvCand[i], i, AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdx, iRoiWidth, iRoiHeight); if ( uiBestCost > uiTmpCost ) { uiBestCost = uiTmpCost; cBestMv = pcAMVPInfo->m_acMvCand[i]; iBestIdx = i; (*puiDistBiP) = uiTmpCost; } } m_cYuvPredTemp.clear(); // Setting Best MVP 设置最优MVP rcMvPred = cBestMv; pcCU->setMVPIdxSubParts( iBestIdx, eRefPicList, uiPartAddr, uiPartIdx, pcCU->getDepth(uiPartAddr)); pcCU->setMVPNumSubParts( pcAMVPInfo->iN, eRefPicList, uiPartAddr, uiPartIdx, pcCU->getDepth(uiPartAddr)); return;}
xCheckBestMVP
在执行完AMVP后,会进行运动估计确定MV。之后通过xCheckBestMVP更新最优MVP。xCheckBestMVP的功能就是在已知MV的情况下,比较当前的MVP和之前最优的MVP的bit数,选择最优MVP。
//已知MV的情况下,找最优MVPVoid TEncSearch::xCheckBestMVP ( TComDataCU* pcCU, RefPicList eRefPicList, TComMv cMv, TComMv& rcMvPred, Int& riMVPIdx, UInt& ruiBits, Distortion& ruiCost ){ AMVPInfo* pcAMVPInfo = pcCU->getCUMvField(eRefPicList)->getAMVPInfo(); //获取AMVP信息 assert(pcAMVPInfo->m_acMvCand[riMVPIdx] == rcMvPred); if (pcAMVPInfo->iN < 2) //候选数小于2直接返回 { return; } m_pcRdCost->getMotionCost( true, 0, pcCU->getCUTransquantBypass(0) ); m_pcRdCost->setCostScale ( 0 ); Int iBestMVPIdx = riMVPIdx; //最优MVP索引置为参考帧MVP索引 m_pcRdCost->setPredictor( rcMvPred ); Int iOrgMvBits = m_pcRdCost->getBits(cMv.getHor(), cMv.getVer()); //计算当前MV的bit数 iOrgMvBits += m_auiMVPIdxCost[riMVPIdx][AMVP_MAX_NUM_CANDS]; //加参考帧MVP的bit数 Int iBestMvBits = iOrgMvBits; for (Int iMVPIdx = 0; iMVPIdx < pcAMVPInfo->iN; iMVPIdx++) { if (iMVPIdx == riMVPIdx) { continue; } m_pcRdCost->setPredictor( pcAMVPInfo->m_acMvCand[iMVPIdx] ); Int iMvBits = m_pcRdCost->getBits(cMv.getHor(), cMv.getVer()); iMvBits += m_auiMVPIdxCost[iMVPIdx][AMVP_MAX_NUM_CANDS]; //计算当前MVP的bit数 if (iMvBits < iBestMvBits) //比较当前MVP和最优MVP,选择最优MVP { iBestMvBits = iMvBits; iBestMVPIdx = iMVPIdx; } } if (iBestMVPIdx != riMVPIdx) //if changed 如果改变,重置AMVP信息 { rcMvPred = pcAMVPInfo->m_acMvCand[iBestMVPIdx]; riMVPIdx = iBestMVPIdx; UInt uiOrgBits = ruiBits; ruiBits = uiOrgBits - iOrgMvBits + iBestMvBits; ruiCost = (ruiCost - m_pcRdCost->getCost( uiOrgBits )) + m_pcRdCost->getCost( ruiBits ); }}
- HEVC代码学习15:AMVP相关函数
- HEVC代码学习2:TAppEncTop::encode函数
- HEVC代码学习3:TEncTop::encode函数
- HEVC代码学习7:xPatternSearchFracDIF函数
- HEVC代码学习8:xMotionEstimation函数
- HEVC代码学习9:getInterMergeCandidates函数
- HEVC代码学习11:xCompressCU函数
- HEVC代码学习12:xCheckRDCostInter函数
- HEVC代码学习13:predInterSearch函数
- HEVC代码学习14:motionCompensation函数
- HEVC代码学习20:xPatternSearchFast函数
- HEVC代码学习21:xTZSearch函数
- HEVC代码学习22:xTZSearchHelp函数
- HEVC代码学习23:xTZ8PointDiamondSearch函数
- HEVC代码学习24:encodeResAndCalcRdInterCU函数
- HEVC代码学习25:xDecompressCU函数
- HEVC代码学习27:calcRdCost函数
- HEVC代码学习28:setLambda函数
- RecyclerView的用法
- leetcode-561(Array Partition I)
- Dropout
- tensorflow 记录保存
- 小米智能插排内部结构
- HEVC代码学习15:AMVP相关函数
- Linux netstat命令详解
- (JAVA) 学生排队 -20170302
- sigar 获取跨平台服务器信息
- Window下使用一行命令kill指定端口
- 存储器,运算器,控制器
- MySQL 可以用localhost 连接,但不能用IP连接的问题,局域网192.168.*.* 无法连接mysql
- 使用继承或接口实现模板方法的方式与函数回调的感悟
- 字符串转utf8编码