initCULevel()函数部分,cansplit()函数

void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStructure& cs )
{
  // Min/max depth
  unsigned minDepth = 0;
  unsigned maxDepth = floorLog2(cs.sps->getCTUSize()) - floorLog2(cs.sps->getMinQTSize( m_slice->getSliceType(), partitioner.chType ));
  if( m_pcEncCfg->getUseFastLCTU() )
  {
    if( auto adPartitioner = dynamic_cast<AdaptiveDepthPartitioner*>( &partitioner ) )
    {
      // LARGE CTU
      adPartitioner->setMaxMinDepth( minDepth, maxDepth, cs );
    }
  }

  m_ComprCUCtxList.push_back( ComprCUCtx( cs, minDepth, maxDepth, NUM_EXTRA_FEATURES ) );

  const CodingUnit* cuLeft  = cs.getCU( cs.area.blocks[partitioner.chType].pos().offset( -1, 0 ), partitioner.chType );
  const CodingUnit* cuAbove = cs.getCU( cs.area.blocks[partitioner.chType].pos().offset( 0, -1 ), partitioner.chType );

  const bool qtBeforeBt = ( (  cuLeft  &&  cuAbove  && cuLeft ->qtDepth > partitioner.currQtDepth && cuAbove->qtDepth > partitioner.currQtDepth )
                         || (  cuLeft  && !cuAbove  && cuLeft ->qtDepth > partitioner.currQtDepth )
                         || ( !cuLeft  &&  cuAbove  && cuAbove->qtDepth > partitioner.currQtDepth )
                         || ( !cuAbove && !cuLeft   && cs.area.lwidth() >= ( 32 << cs.slice->getDepth() ) ) )
                         && ( cs.area.lwidth() > ( cs.pcv->getMinQtSize( *cs.slice, partitioner.chType ) << 1 ) );

cuLeft:当前CU的左侧cu情况。如是第一个cu,则culeft就为NULL.

offset( -1, 0 ):表示当前CU位置向左移动一个单位的CU情况

qtBeforeBt:

  1. cuLeft,cuabove都存在且culeft的QT深度大于当前cu的QT深度,同时cuabove的QT深度大于当前cu的QT深度
  2. 只有culeft存在且culeft的QT深度大于当前cu的QT深度
  3. 只有cuabove存在且cuabove的QT深度大于当前cu的QT深度
  4. 都不存在且当前CTU的亮度width大于32 X 当前深度

若以上四个条件有任一个满足,且当前CTU的亮度分量width大于MinQtSize的2倍,则qtBeforeBt为真

                          

2. initCULevel 函数调用的 cansplit()函数 

bool QTBTPartitioner::canSplit( const PartSplit split, const CodingStructure &cs )
{
    //当前亮度分量的位置和长宽
  const CompArea area       = currArea().Y();
  const unsigned maxTrSize  = cs.sps->getMaxTbSize();

  bool canNo, canQt, canBh, canTh, canBv, canTv;

  canSplit( cs, canNo, canQt, canBh, canBv, canTh, canTv );
  switch( split )
  {
  case CTU_LEVEL:
    THROW( "Checking if top level split is possible" );
    return true;
    break;
  case TU_MAX_TR_SPLIT:
    return area.width > maxTrSize || area.height > maxTrSize;
    break;
  case SBT_VER_HALF_POS0_SPLIT:
  case SBT_VER_HALF_POS1_SPLIT:
  case SBT_HOR_HALF_POS0_SPLIT:
  case SBT_HOR_HALF_POS1_SPLIT:
  case SBT_VER_QUAD_POS0_SPLIT:
  case SBT_VER_QUAD_POS1_SPLIT:
  case SBT_HOR_QUAD_POS0_SPLIT:
  case SBT_HOR_QUAD_POS1_SPLIT:
    return currTrDepth == 0;
    break;
  case CU_QUAD_SPLIT:
    return canQt;
  case CU_DONT_SPLIT:
    return canNo;
  case CU_HORZ_SPLIT:
    return canBh;
  case CU_VERT_SPLIT:
    return canBv;
  case CU_TRIH_SPLIT:
    return canTh;
  case CU_TRIV_SPLIT:
    return canTv;
  case CU_MT_SPLIT:
    return ( canBh || canTh || canBv || canTv );
  case CU_BT_SPLIT:
    return ( canBh || canBv );
  break;
  default:
    THROW( "Unknown split mode" );
    return false;
    break;
  }

H.264/H.265/H.266三代视频编码的图像划分_@唔问的博客-CSDN博客_h266视频编码对照表

getMaxTbSize():得到最大的TB尺寸 

swicth:根据当前传入的划分模式,判断是否加入测试列表

3.cansplit中调用的决定各个划分模式是否可行的cansplit函数

void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& canQt, bool& canBh, bool& canBv, bool& canTh, bool& canTv )
{
  //隐式分割设置
  const PartSplit implicitSplit = m_partStack.back().checkdIfImplicit ? m_partStack.back().implicitSplit : getImplicitSplit( cs );
  //一些参数获取
  //maxBT深度是要加上当前隐式分割的BT深度
  const unsigned maxBTD         = cs.pcv->getMaxBtDepth( *cs.slice, chType ) + currImplicitBtDepth;
  const unsigned maxBtSize      = cs.pcv->getMaxBtSize ( *cs.slice, chType );
  const unsigned minBtSize      = cs.pcv->getMinBtSize ( *cs.slice, chType );
  const unsigned maxTtSize      = cs.pcv->getMaxTtSize ( *cs.slice, chType );
  const unsigned minTtSize      = cs.pcv->getMinTtSize ( *cs.slice, chType );
  const unsigned minQtSize      = cs.pcv->getMinQtSize ( *cs.slice, chType );

  canNo = canQt = canBh = canTh = canBv = canTv = true;
  //若设置的BT最大深度大于当前MT的深度,则可以BT和TT
  bool canBtt = currMtDepth < maxBTD;

  // the minimal and maximal sizes are given in luma samples
  const CompArea&  area  = currArea().Y();
  const CompArea  *areaC = (chType == CHANNEL_TYPE_CHROMA) ? &(currArea().Cb()) : nullptr;
        PartLevel& level = m_partStack.back();

  const PartSplit lastSplit = level.split;
  const PartSplit parlSplit = lastSplit == CU_TRIH_SPLIT ? CU_HORZ_SPLIT : CU_VERT_SPLIT;

  // don't allow QT-splitting below a BT split
  //如果上次划分模式不是CTU_LEVEL 且不为CU_QUAD_SPLIT ,canQT为fasle
  if( lastSplit != CTU_LEVEL && lastSplit != CU_QUAD_SPLIT ) canQt = false;
  if( area.width <= minQtSize )                              canQt = false;

  if( areaC && areaC->width <= MIN_DUALTREE_CHROMA_WIDTH ) canQt = false;
  // 若当前树类型为色度分离树
  // 则二叉、三叉、四叉划分均不进行
  if( treeType == TREE_C )
  {
    canQt = canBh = canTh = canBv = canTv = false;
    return;
  }
  // 若隐含划分不为不划分
  if( implicitSplit != CU_DONT_SPLIT )
  {
    // 则不划分、三叉树划分均不进行测试
    canNo = canTh = canTv = false;
    // 根据隐含划分决定二叉树划分是否测试
    canBh = implicitSplit == CU_HORZ_SPLIT;
    canBv = implicitSplit == CU_VERT_SPLIT;
    // 若当前色度区域存在且色度区域宽度等于4,则不进行 BV
    if (areaC && areaC->width == 4) canBv = false;
    // 若不BH、BV、QT,则测试 QT
    if( !canBh && !canBv && !canQt ) canQt = true;
    return;
  }
   // 若上一划分模式为 TH,且当前块索引为 1,则不测试 BH,测试 BV
  // 若上一划分模式为 TV,且当前块索引为 1,则不测试 BV,测试 BH
  if( ( lastSplit == CU_TRIH_SPLIT || lastSplit == CU_TRIV_SPLIT ) && currPartIdx() == 1 )
  {
    canBh = parlSplit != CU_HORZ_SPLIT;
    canBv = parlSplit != CU_VERT_SPLIT;
  }
  // 若同时满足当前 MT 深度小于最大 MT 深度、当前区域宽高均小于等于最小 BT 尺寸、当前区域宽高均小于等于最小 TT 尺寸,则将 canBtt 设为 false
  if( canBtt && ( area.width <= minBtSize && area.height <= minBtSize )
      && ( ( area.width <= minTtSize && area.height <= minTtSize ) ) )
  {
    canBtt = false;
  }
   // 若同时满足当前 MT 深度小于最大 MT 深度、当前区域宽或高大于最大 BT 尺寸、当前区域宽或高大于最大 TT 尺寸,则将 canBtt 设为 false
  if( canBtt && ( area.width > maxBtSize || area.height > maxBtSize )
      && ( ( area.width > maxTtSize || area.height > maxTtSize ) ) )
  {
    canBtt = false;
  }

  if( !canBtt )
  {
    canBh = canTh = canBv = canTv = false;

    return;
  }
  // 若当前区域宽或高大于最大 BT 尺寸
  // 则不尝试 BT
  if( area.width > maxBtSize || area.height > maxBtSize )
  {
    canBh = canBv = false;
  }

  // specific check for BT splits
  // 若当前区域高小于等于最小 BT 尺寸,则不尝试 BH
  if( area.height <= minBtSize )                            canBh = false;
  // 若当前区域宽大于最大 TB 尺寸,且当前区域高小于等于最大 TB 尺寸,则不尝试 BH
  if( area.width > MAX_TB_SIZEY && area.height <= MAX_TB_SIZEY ) canBh = false;
  // 若当前色度区域存在,且面积小于等于 16,则不尝试 BH
  if( areaC && areaC->width * areaC->height <= MIN_DUALTREE_CHROMA_SIZE )     canBh = false;
  // 若当前区域宽小于等于最小 BT 尺寸,则不尝试 BV
  if( area.width <= minBtSize )                              canBv = false;
  // 若当前区域宽小于等于最大 TB 尺寸,且当前区域高大于最大 TB 尺寸,则不尝试 BV
  if( area.width <= MAX_TB_SIZEY && area.height > MAX_TB_SIZEY ) canBv = false;
  // 若当前色度区域存在,且面积小于等于 16 或宽为 4,则不尝试 BV
  if (areaC && (areaC->width * areaC->height <= MIN_DUALTREE_CHROMA_SIZE || areaC->width == 4))     canBv = false;
  // 若为 INTER,且当前区域面积为 32,则不尝试 BT
  if( modeType == MODE_TYPE_INTER && area.width * area.height == 32 )  canBv = canBh = false;
  // 若当前区域高小于等于两倍最小 TT 尺寸,或当前区域高大于最大 TT 尺寸,或当前区域宽大于最大 TT 尺寸
  // 则不尝试 TH
  if( area.height <= 2 * minTtSize || area.height > maxTtSize || area.width > maxTtSize )
                                                                                       canTh = false;
  // 若当前区域宽大于最大 TB 尺寸,或当前区域高大于最大 TB 尺寸,则不尝试 TH
  if( area.width > MAX_TB_SIZEY || area.height > MAX_TB_SIZEY )  canTh = false;
  // 若当前色度区域存在,且面积小于等于 32,则不尝试 TH
  if( areaC && areaC->width * areaC->height <= MIN_DUALTREE_CHROMA_SIZE*2 )     canTh = false;
  // 若当前区域宽度小于等于两倍最小 TT 尺寸,或当前区域宽大于最大 TT 尺寸,或当前区域高大于最大 TT 尺寸
  // 则不尝试 TV
  if( area.width <= 2 * minTtSize || area.width > maxTtSize || area.height > maxTtSize )
                                                                                       canTv = false;
  // 若当前区域宽大于最大 TB 尺寸,或当前区域高大于最大 TB 尺寸,则不尝试 TV
  if( area.width > MAX_TB_SIZEY || area.height > MAX_TB_SIZEY )  canTv = false;
  // 若当前色度区域存在,且面积小于等于 32 或 宽度为 8,则不尝试 TV
  if (areaC && (areaC->width * areaC->height <= MIN_DUALTREE_CHROMA_SIZE * 2 || areaC->width == 8))     canTv = false;
  // 若为 INTER,且当前区域面积为 64,则不尝试 TT
  if( modeType == MODE_TYPE_INTER && area.width * area.height == 64 )  canTv = canTh = false;

}

maxBTD:最大BT深度,是psv中设置的maxBTdepth和当前隐式分割BTdepth的相加

PartLevel& level= m_partStack.back():将m_partStack中赋给level。m_partStack里为划分树的具体情况

lastSplit:表示的是上一次使用的划分模式

parlSplit:如果上一次为TH,则这次的划分模式BH,否则为BT,赋给parlSplit

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值