HEVC代码学习32:getInterMergeCandidates函数

本文深入探讨了HEVC编码中的getInterMergeCandidates函数,该函数负责创建merge候选列表,特别是如何建立空域候选列表。空域候选列表从A1到B2顺序遍历,选取有效PU并记录MV,最终可能包含4个候选。同时,函数还涉及时域候选列表的构建以及B Slice的组合列表处理。通过代码分析,理解该过程的工作流程。
摘要由CSDN通过智能技术生成

今天来看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() )       //双向预测时,获取list1MV
    {
      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
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值