H.266/VVC-VTM代码学习24-根据当前块位置与尺寸确定隐藏划分模式getImplicitSplit()

H.266/VVC专栏传送

上一篇:H.266/VVC-VTM代码学习23-编码块RDO选择模式(Intra与Inter)initCULevel()
下一篇:

前言

VTM是H.266/VVC视频编码标准的参考软件,研究VTM代码给研究人员解释了VVC编码标准的详细标准规范与细节。

本文是笔者对VTM代码的一点学习记录,成文于笔者刚开始接触VVC期间,期间很多概念和理论框架还很不成熟,若文中存在错误欢迎批评指正,也欢迎广大视频编码学习者沟通交流、共同进步。

VTM代码的下载及编译请参考博文:
【视频编码学习】H.266/VVC参考软件VTM配置运行(VTM-6.0版本)

一、简介

getImplicitSplit() 函数是在 partitioner.canSplit 函数中调用的重要函数,该函数的作用是根据当前块位置和尺寸确定其隐藏划分模式。若存在隐藏划分模式,则在当前块 RDO 列表加入 split 模式时直接添加隐藏划分模式对应划分模式。

二、代码详解

PartSplit QTBTPartitioner::getImplicitSplit( const CodingStructure &cs )
{
  // 若已存在隐藏划分模式,则直接返回存在的隐藏划分模式
  if( m_partStack.back().checkdIfImplicit )
  {
    return m_partStack.back().implicitSplit;
  }

  // 划分模式初始化为不划分
  PartSplit split = CU_DONT_SPLIT;

  if( split == CU_DONT_SPLIT )
  {
    // 当前区域的左下角是否包含在图片中
    const bool isBlInPic = cs.picture->Y().contains( currArea().Y().bottomLeft() );
    // 当前区域的右上角是否包含在图片中
    const bool isTrInPic = cs.picture->Y().contains( currArea().Y().topRight() );

    // 当前亮度区域
    const CompArea& area      = currArea().Y();
    // 最大二叉树划分尺寸
    const unsigned maxBtSize  = cs.pcv->getMaxBtSize( *cs.slice, chType );
    // 当前区域宽度、高度均小于等于最大BT尺寸,当前MT深度小于最大BT深度+当前隐藏BT深度,则允许BT
    const bool isBtAllowed    = area.width <= maxBtSize && area.height <= maxBtSize && currMtDepth < (cs.pcv->getMaxBtDepth(*cs.slice, chType) + currImplicitBtDepth);
    // 最小QT尺寸
    const unsigned minQtSize  = cs.pcv->getMinQtSize( *cs.slice, chType );
    // 当前区域宽度、高度均大于最小QT尺寸,且当前BT深度为0,则允许QT
    const bool isQtAllowed    = area.width >  minQtSize && area.height >  minQtSize && currBtDepth == 0;

    // 若当前块左下角不在当前帧 且 当前块右上角不在当前帧 且 允许QT
    // 则划分模式设置为QT
    if( !isBlInPic && !isTrInPic && isQtAllowed )
    {
      split = CU_QUAD_SPLIT;
    }
    // 若当前块左下角不在当前帧 且 允许BT 且 当前区域宽小于等于最大TB尺寸
    // 则划分模式设置为BH
    else if( !isBlInPic && isBtAllowed && area.width <= MAX_TB_SIZEY )
    {
      split = CU_HORZ_SPLIT;
    }
    // 若当前块右上角不在当前帧 且 允许BT 且 当前区域高小于等于最大TB尺寸
    // 则划分模式设置为VT
    else if( !isTrInPic && isBtAllowed && area.height <= MAX_TB_SIZEY )
    {
      split = CU_VERT_SPLIT;
    }
    // 若当前块左下角或右上角还不在当前帧
    // 则划分模式设置为QT
    else if( !isBlInPic || !isTrInPic )
    {
      split = CU_QUAD_SPLIT;
    }
    // 若当前为 DualTree 且 当前区域宽或高大于64
    // 则划分模式设置为QT
    if (CS::isDualITree(cs) && (currArea().Y().width > 64 || currArea().Y().height > 64))
    {
      split = CU_QUAD_SPLIT;
    }
    // 若当前块左下角或右上角不在当前帧 且 划分模式仍为初始的不划分
    // 则划分模式设置为QT
    if( (!isBlInPic || !isTrInPic) && split == CU_DONT_SPLIT )
    {
      split = CU_QUAD_SPLIT;
    }
  }
  // 将划分模式存储为隐藏划分模式
  m_partStack.back().checkdIfImplicit = true;
  m_partStack.back().isImplicit = split != CU_DONT_SPLIT;
  m_partStack.back().implicitSplit = split;

  return split;
}
}

上一篇:H.266/VVC-VTM代码学习23-编码块RDO选择模式(Intra与Inter)initCULevel()
下一篇:H.266/VVC-VTM代码学习25-VTM中RDcost的计算与λ的设定(一)

posted @ 2021-04-21 19:52  liaojq2020  阅读(122)  评论(0)    收藏  举报