AMVP候选理论回顾
根据图像中块与块的相关性计算,针对当前块,空域上与其相关性最强的块的位置如下图所示:

时域上相关性的最强的块如下图所示:

HM中该MVP填充流程如下:

  1. 计算得到当前PU左上、左下、右上的4x4块的索引值.将ZScan转换成Raster来找更好计算位置
  2. 预先判断当前PU左方的CU能不能获取,不能获取的话 isScaledFlagLX=false
  3. 依次找无需缩放的A0、A1。根据当前参考帧以及所选块参考帧来确定,若两个参考帧相同,则就无需缩放。如果无需缩放的MVP找不到,则寻找可以缩放的MVP。
  4. 依次找上方的CU:B0、B1、B2(此步只找无需缩放的MVP)
  5. 如果左方的CU不能用,再依次找可以缩放的 B0 B1 B2填入AMVP候选
  6. 判断当前MVP候选个数,同时去冗余
  7. 去完冗余后,若还不满足AMVP候选个数最大值,则寻找时域同位块的MV。
  8. 先找右下方的CU、右下方CU不可用或者是当前PU右下角的4x4块在当前CTU角落、在最后一行不在最后一列时也不可用。就开始寻找中心块
  9. 若还填不满 则填充0矢量.

代码如下:

/** Constructs a list of candidates for AMVP (See specification, section "Derivation process for motion vector predictor candidates")* \param uiPartIdx -当前处理PU的索引* \param uiPartAddr - 当前处理PU的起始地址(后续需要根据当前CU的地址来判断)* \param eRefPicList - 当前参考图像列表* \param iRefIdx - 当前参考帧* \param pInfo - 要存入的MVP信息*/
Void TComDataCU::fillMvpCand ( const UInt partIdx, const UInt partAddr, const RefPicList eRefPicList, const Int refIdx, AMVPInfo* pInfo ) const
{pInfo->iN = 0;if (refIdx < 0){return;}//-- Get Spatial MV// 得到当前PU左上,右上,左下4x4CU块的索引(4x4为默认最小CU)// Zscan为Z扫, Raster为逐行扫描UInt partIdxLT, partIdxRT, partIdxLB;deriveLeftRightTopIdx( partIdx, partIdxLT, partIdxRT ); //要以当前CU起始位置开始找deriveLeftBottomIdx( partIdx, partIdxLB );Bool isScaledFlagLX = false; /// variable name from specification; true when the PUs below left or left are available (availableA0 || availableA1).//判断左方的CTU,左下方CU能不能获取{UInt idx;const TComDataCU* tmpCU = getPUBelowLeft(idx, partIdxLB);isScaledFlagLX = (tmpCU != NULL) && (tmpCU->isInter(idx));if (!isScaledFlagLX){tmpCU = getPULeft(idx, partIdxLB);isScaledFlagLX = (tmpCU != NULL) && (tmpCU->isInter(idx));}}// Left predictor search// 先按照左下,左方的顺序搜索可用的CU,先找不用缩放的,再找需要缩放的// 不用缩放:邻居块与当前PU参考同一帧if (isScaledFlagLX){Bool bAdded = xAddMVPCandUnscaled( *pInfo, eRefPicList, refIdx, partIdxLB, MD_BELOW_LEFT);if (!bAdded){bAdded = xAddMVPCandUnscaled( *pInfo, eRefPicList, refIdx, partIdxLB, MD_LEFT );if(!bAdded){bAdded = xAddMVPCandWithScaling( *pInfo, eRefPicList, refIdx, partIdxLB, MD_BELOW_LEFT);if (!bAdded){xAddMVPCandWithScaling( *pInfo, eRefPicList, refIdx, partIdxLB, MD_LEFT );}}}}// Above predictor search{Bool bAdded = xAddMVPCandUnscaled( *pInfo, eRefPicList, refIdx, partIdxRT, MD_ABOVE_RIGHT);if (!bAdded){bAdded = xAddMVPCandUnscaled( *pInfo, eRefPicList, refIdx, partIdxRT, MD_ABOVE);if(!bAdded){xAddMVPCandUnscaled( *pInfo, eRefPicList, refIdx, partIdxLT, MD_ABOVE_LEFT);}}}if(!isScaledFlagLX){Bool bAdded = xAddMVPCandWithScaling( *pInfo, eRefPicList, refIdx, partIdxRT, MD_ABOVE_RIGHT);if (!bAdded){bAdded = xAddMVPCandWithScaling( *pInfo, eRefPicList, refIdx, partIdxRT, MD_ABOVE);if(!bAdded){xAddMVPCandWithScaling( *pInfo, eRefPicList, refIdx, partIdxLT, MD_ABOVE_LEFT);}}}// 判断空域候选是否填满了AMVP候选列表// 去除冗余MVP,如两个MV相同,则去除掉一个if ( pInfo->iN == 2 ){if ( pInfo->m_acMvCand[ 0 ] == pInfo->m_acMvCand[ 1 ] ){pInfo->iN = 1;}}// 若未填满,则开启时域候选if (pInfo->iN < AMVP_MAX_NUM_CANDS && getSlice()->getEnableTMVPFlag() ){// Get Temporal Motion Predictorconst UInt numPartInCtuWidth  = m_pcPic->getNumPartInCtuWidth(); //一个CTU的宽中可以有多少个4x4的块const UInt numPartInCtuHeight = m_pcPic->getNumPartInCtuHeight();const Int refIdx_Col = refIdx;TComMv cColMv;UInt partIdxRB;UInt absPartIdx;deriveRightBottomIdx( partIdx, partIdxRB ); //找到右下方的4x4块UInt absPartAddr = m_absZIdxInCtu + partAddr; //当前PU起始位置//----  co-located RightBottom Temporal Predictor (H) ---//absPartIdx = g_auiZscanToRaster[partIdxRB]; //Zscan to RasterInt ctuRsAddr = -1;//找右下角的CU块起始位置,由于CTU的划分每一帧都相同,所以若右下角的块是下一个CTU了,那么还要获取下一个CTU的地址if (  ( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelX() + g_auiRasterToPelX[absPartIdx] + m_pcPic->getMinCUWidth () ) < m_pcSlice->getSPS()->getPicWidthInLumaSamples () )  // image boundary check&& ( ( m_pcPic->getCtu(m_ctuRsAddr)->getCUPelY() + g_auiRasterToPelY[absPartIdx] + m_pcPic->getMinCUHeight() ) < m_pcSlice->getSPS()->getPicHeightInLumaSamples() ) ){if ( ( absPartIdx % numPartInCtuWidth < numPartInCtuWidth - 1 ) &&  // is not at the last column of CTU( absPartIdx / numPartInCtuWidth < numPartInCtuHeight - 1 ) )  // is not at the last row    of CTU{absPartAddr = g_auiRasterToZscan[ absPartIdx + numPartInCtuWidth + 1 ]; //用逐行扫描的索引更容易计算相对位置ctuRsAddr = getCtuRsAddr();}else if ( absPartIdx % numPartInCtuWidth < numPartInCtuWidth - 1 )  // is not at the last column of CTU But is last row of CTU{absPartAddr = g_auiRasterToZscan[ (absPartIdx + numPartInCtuWidth + 1) % m_pcPic->getNumPartitionsInCtu() ];}else if ( absPartIdx / numPartInCtuWidth < numPartInCtuHeight - 1 ) // is not at the last row of CTU But is last column of CTU{absPartAddr = g_auiRasterToZscan[ absPartIdx + 1 ];ctuRsAddr = getCtuRsAddr() + 1;}else //is the right bottom corner of CTU{absPartAddr = 0;}}//若当前PU右下角的位置在当前CTU内且不是最后一行也不是角落位置if ( ctuRsAddr >= 0 && xGetColMVP( eRefPicList, ctuRsAddr, absPartAddr, cColMv, refIdx_Col ) ){pInfo->m_acMvCand[pInfo->iN++] = cColMv;}//中心同位帧else{UInt uiPartIdxCenter;xDeriveCenterIdx( partIdx, uiPartIdxCenter );if (xGetColMVP( eRefPicList, getCtuRsAddr(), uiPartIdxCenter,  cColMv, refIdx_Col )){pInfo->m_acMvCand[pInfo->iN++] = cColMv;}}//----  co-located RightBottom Temporal Predictor  ---//}while (pInfo->iN < AMVP_MAX_NUM_CANDS){pInfo->m_acMvCand[pInfo->iN].set(0,0);pInfo->iN++;}return ;
}

HM代码阅读3:AMVP候选填充函数Void TComDataCU::fillMvpCand ()相关推荐

  1. HM代码阅读1: 帧间预测函数Void TEncSearch::predInterSearch()

    AMVP理论知识简单回顾(含GPB) MVP主要是为了给当前PU提供一个运动矢量的预测,可加快ME的计算速度以及提升准确性.并且在后续编码中也只用编码MVD,减少了传输bit数. HM中获取每个参考图 ...

  2. HM代码阅读2:AMVP预测函数Void TEncSearch::xEstimateMvPredAMVP()

    AMVP预测函数:根据AMVP候选准则为该帧建立MVP候选列表,调用pcCU->fillMvpCand( uiPartIdx, uiPartAddr, eRefPicList, iRefIdx, ...

  3. HM代码阅读0:Win10下安装HM16.23,编码一个视频,main函数阅读

    HEVC理论知识的学习告了一段落了,说实话脑子里还是嗡嗡的,剩下的部分就一边阅读代码一边掌握吧. 1. HM16.23安装 首先需要安装Cmake,参考以下博客,照步骤安装即可 https://blo ...

  4. VTM1.0代码阅读:CodingStructure类主要函数

    CodingStructure类中的各个函数对于cu.pu和tu的函数处理,其实大致流程都是差不多一样的,所以这里只对cu的相应函数进行分析. 对于下面CodingStructure类中的各个函数的阅 ...

  5. VVC代码阅读(2)compressGOP函数(2)

    注意:本次代码运用的是encoder_intra_vtm的设置,所以GOP_size  只有一帧 // store sub-picture numbers, sizes, and locations ...

  6. HM编码器代码阅读(16)——帧间预测之AMVP模式(四)预测MV的获取

    帧间预测的原理 AMVP的原理 帧间预测的实质就是为当前的PU在参考帧中寻找一块最相似块(相似度的判断准则有SAD等方法).但是参考图像通常都比较大,我们直接去搜索的话就太费时了,应该使用某种方法在参 ...

  7. 【二十一】 H.266/VVC | 仿射运动估计AMVP候选列表的构建 | fillAffineMvpCand函数

    /* 函数的作用: 构建Affine AMVP list候选列表 函数的参数说明: 1.PredictionUnit &pu 当前编码的PU 2.const RefPicList &e ...

  8. 【二十二】 H.266/VVC | 选择最优的仿射AMVP候选项 | xEstimateAffineAMVP函数

    /* 函数的所用:从构建的仿射AMVP候选列表中选择最优的候选项 函数的参数说明: 1.PredictionUnit& pu, 当前编码的PU 2.AffineAMVPInfo& af ...

  9. VTM3.0代码阅读:xEstimateMvPredAMVP函数

    AMVP运用于inter_ME模式的时候. xEstimateMvPredAMVP进行AMVP,获得当前pu的相邻运动信息,构建AMVP列表,最终选择出最优的MVP.AMVP最终获得的MVP作为ME的 ...

最新文章

  1. 关于运算符重载的问题
  2. java并发排序_Java并发(三):重排序
  3. 如何使用 SQL Server FILESTREAM 存储非结构化数据?这篇文章告诉你!
  4. 开源数据库再创里程碑,PingCAP 获 2.7 亿美元融资
  5. linux NFS共享
  6. 自旋锁,偏向锁,轻量级锁 和 重量级锁
  7. 爬虫mm131明星照片
  8. Url重写——伪静态实现
  9. mnist数据集python导入_Python读取MNIST数据集
  10. VB2010的串口能正常接收数据,但无法发送数值大于127的数据
  11. 使用vld查看OPCode
  12. UE5——材质学习笔记(4):溶解材质
  13. 使用Python及SMTP协议发送邮件(以163邮箱为例)
  14. 《程序员》走近创新工场 解密李开复如何寻找创业之星
  15. VTK读取序列DCM格式医学图像
  16. Android系统定制开机logo和开机动画
  17. Linux·工作队列
  18. Tensorflow2 图像分类-Flowers数据及分类代码详解
  19. linux raid 找回文件,linux – 恢复已经在降级模式下运行的RAID-5(丢失了第二个磁盘)...
  20. logback根据业务分开打印日志

热门文章

  1. 955/965公司名单
  2. vim tutorial 101 hacks(一)
  3. 计算机用户组怎么更改权限,win7系统用户组权限怎么设置
  4. 前端怎么画三角形_用CSS画一个三角形
  5. 神经网络传递函数的选择,卷积神经网络风格迁移
  6. 从零开始的MYSQL数据库命令行使用指南
  7. (OS 10038)在一个非套接字上尝试了一个操作 的解决办法
  8. 计算机二级考试题库vb知识点,国家计算机二级考试题库 VB上机试题第13套
  9. 关于LSB图片隐写的解法
  10. 【装机必备】电脑优化清理工具