Quadtree plus binary tree (QTBT) block structure

来源:互联网 发布:酒店市场数据分析 编辑:程序博客网 时间:2024/06/06 03:02
  • 回顾HEVC
    • CTU可四叉划分成多个CU,CU是编码的基本单元
    • CU可以划分成1个或2个或4个不同的PU,且对帧内、帧间预测有不同的划分方式,PU是预测的基本单元
    • CU还可以四叉划分成多个不同的TU对残差进行变换,TU是变换的基本单元
    • 推荐HEVC块结构划分博客https://yq.aliyun.com/articles/31214
    • 推荐HM划分结构解释博客http://blog.csdn.net/u012409883/article/details/42059141

  • QTBT简介
    • 简化了HEVC中的块类型,即去除了CU、PU、TU的概念,减少了CU划分为PU和TU的步骤
    • 支持更加零活的CU划分方式,以适应纹理结构
    • CU可为方形,也可为长方形,如下图所示,先四叉划分,再二叉划分,且二叉划分有horizontal,vertical两种不同的方向
      这里写图片描述
    • 因此,有以下几个变量来规定QTBT树的形状
      • CTU size:概念和在HEVC中一样,可以理解为最初、最大的待编码块,是编码块的根节点块大小。
      • MinQTSize:最小的四叉划分块大小,即允许做为叶子节点的四叉块的大小
      • MaxBTSize:最大允许的二叉块大小,即允许二叉树的根节点块大小
      • MaxBTDepth:最大允许的二叉树划分深度
      • MinBTSize:最小允许的二叉块大小,即允许最小的二叉树叶子节点的块大小
      • 默认设置为:
        这里写图片描述
    • 因此,四叉树的叶子节点也即二叉树的根节点(如果四叉树叶子节点的大小<= MaxBTSize的话;否则,不进行二叉树划分),且当前四叉树叶子节点所在块对应的二叉树划分深度为0
    • 此外,当二叉树划分深度达到MaxBTDepth时,停止二叉树划分;当二叉块的宽度达到MinBTSize时,停止horizontal划分;同理,当二叉块的高度达到MinBTSize时,停止vertical划分。需要注意的是,horizontal 划分是横向划分两个块,vertical划分是纵向划分两个块,需要1bit表示。最终二叉树划分的叶子节点块,即CU,是预测、变换等编码技术的基本单元。
    • 需要注意的是,亮度块和色度块的QTBT划分结构不一定一致。在PB帧中,采用相同的划分结构;而在I帧中,不一致
    • QTBT块的RDO过程伪代码:
      这里写图片描述
      从伪代码来看,我们之前讲述的horizontal划分和vertical划分,与注释中表达的horizontal binary tree partitioning和vertical binary tree partitioning的概念正好相反。当然,这个不重要,理清即可。且对于每个划分的子块(来自二叉划分或四叉划分),都需递归调用该函数进行块划分决策。
    • 由于QTBT带来的块划分的灵活性,使得划分过程中计算复杂度较高,且也可能存在块计算的冗余,即每一个块可能在不同的划分中均出现过。
      • 情况一、当前块RDO过程中,发现CostNoPart比CostHorBT和CostVerBT都小,且CostHorBT和CostVerBT计算过程也尝试过更深深度的划分,此时,可以发现CostQT很大可能大于CostNoPart,因此,在这种情况下将会跳过CostQT的计算。
      • 情况二、在划分过程中一个块可能出现不止一次。如下图所示,左图中先进行vertical Binary tree split,再对右侧子块进行horizontal binary tree split;右图中则先进行horizontal binary tree split,再对上侧子块进行vertical Binary tree split。可以发现,右上角的子块出现了两次,若不约束,则会进行两次RDO。因此,优化时,保存块在第一次RDO过程时的结果,以方便后续被划分到时使用,避免重复计算
        这里写图片描述
      • 如果当前块的最佳模式的skip模式,且当前块的划分深度已经足够深,则将不进行深入的四叉或二叉划分。
    • 此外,由于MaxBTSize和MinQTSize对RD性能以及编码时间具有重要影响,因此,在帧级对其有所限制。即对于P、B帧,统计已编码同时间分级的帧内CU的平均大小,根据该值适当缩放MaxBTSize和MinQTSize。

  • JEM相关代码解读
    • 参考软件选择branch HM13.0+QTBT:https://hevc.hhi.fraunhofer.de/trac/jem/browser/branches/HM-13.0-QTBT
    • TypeDef.h宏定义,包括前面提到的重要参数,以及一些快速算法
       
      #define CTU_LOG2 7 //1<<CTU_LOG2: 64x64 or 128x128
      #define MIN_CU_LOG2 2 //1<<MIN_CU_LOG2: 2x2 or 4x4
      #if MIN_CU_LOG2==1
      #define DF_MODIFY 1 //deblocking modifications
      #else
      #define DF_MODIFY 0
      #endif
      //QTBT high level parameters
      //for I slice luma CTB configuration para.
      #define MAX_BT_DEPTH 4 // <=7
      #define MAX_BT_SIZE 32 / /[1<<MIN_QT_SIZE, 1<<CTU_LOG2]
      #define MIN_QT_SIZE 16
      #define MIN_BT_SIZE 4 // can be set down to 1<<MIN_CU_LOG2
      //for I slice chroma CTB configuration para. (in luma samples)
      #define MAX_BT_DEPTH_C 0 //<=7
      #define MAX_BT_SIZE_C 32 //[1<<MIN_QT_SIZE_C, 1<<CTU_LOG2]
      #define MIN_QT_SIZE_C 4
      #define MIN_BT_SIZE_C 4 //can be set down to 4
      //for P/B slice CTU config. para.
      #define MAX_BT_DEPTH_INTER 4 //<=7
      #define MAX_BT_SIZE_INTER 128 //for initialization, [1<<MIN_BT_SIZE_INTER, 1<<CTU_LOG2]
      #define MIN_QT_SIZE_INTER 16 //for initialization
      #define MIN_BT_SIZE_INTER 4 //
      //end of QTBT high level parameters
      //fast algorithms
      #define AMAX_BT 1 //slice level adaptive maxBT for P/B slice
      #define AMAXBT_TH32 15.0
      #define AMAXBT_TH64 30.0
      #define AMIN_QT 1 //slice level adaptive minQT for P/B slice
      #define AMINQT_TH32 40.0
      #define SKIP_DEPTH 3
      #define SKIPHORNOVERQT_DEPTH_TH 2
      #define BT_RMV_REDUNDANT 1 ///< Remove redundant BT structure for B/P slice
      #define MRG_FAST 1 //merge mode RDO, first SATD select <=3 candidates, then full RDO.
      #define NUM_MRG_SATD_CAND 4
      #define MRG_FAST_RATIO 1.25
      #define NEIGHBOR_FAST 1
      #define PBINTRA_FAST 1 //Intra CU fast for B/P slice
      #define PBINTRA_RATIO 1.1
      #define ITSKIP 1 //inverse transform not used for zero-line, for transform size > 32
    • 关键参数设置
       
      printf("CTU size : %d \n", 1<<CTU_LOG2);//128
      printf("I slice (LS=luma samples, CS=chroma samples) \n");
      printf("maxBTSize(L,C) : %d LS, %d CS\n", MAX_BT_SIZE, MAX_BT_SIZE_C>>1);//32, 16
      printf("minQTSize(L,C) : %dx%d LS, %dx%d CS\n", MIN_QT_SIZE, MIN_QT_SIZE, MIN_QT_SIZE_C>>1, MIN_QT_SIZE_C>>1);//16x16, 2x2
      printf("minBTSize(L,C) : %d LS, %d CS\n", MIN_BT_SIZE, MIN_BT_SIZE_C>>1);//4, 2
      printf("maxBTDepth(L,C) : %d, %d\n", MAX_BT_DEPTH, MAX_BT_DEPTH_C);//4,0
      printf("P, B slice \n");
      printf("maxBTSize(init) : %d \n", MAX_BT_SIZE_INTER);//128
      printf("minQTSize(init) : %dx%d\n", MIN_QT_SIZE_INTER, MIN_QT_SIZE_INTER);//16, 16
      printf("minBTSize : %d\n", MIN_BT_SIZE_INTER);//4
      printf("maxBTDepth : %d\n", MAX_BT_DEPTH_INTER);//4
    • compressCU伪代码
       
      initCU();
      xCompressCU(Luma)
      if(isISlice)
      xCompressCU(Chroma)
    • xCompressCU伪代码(符合上文中的图片描述)
       
      //no part
      xCheckRDCostInter(2Nx2N)
      xCheckRDCostMerge2Nx2N()
      xCheckRDCostIntra(2Nx2N)
      xCheckIntraPCM()
      //figure the possibility of BT
      //test horizontal split
      2 * xCompressCU(uiWidth, uiHeight>>1)
      //test vertical split
      2 * xCompressCU(uiWidth>>1, uiHeight)
      //QT
      4 * xCompressCU(uiWidth>>1, uiHeight>>1)
    • xQuantTU2(),对2 * X / X*2的变换系数块量化,不使用RDOQ,也不使用signBitHiding
    • 宏AMAX_BT,对于非Islice,利用同一layer上CU的平均边长,对当前BT的最大划分尺寸约束
       
      Double dBlkSize = sqrt((Double)g_uiBlkSize[refLayer]/g_uiNumBlk[refLayer]);
      if (dBlkSize < AMAXBT_TH32)
      {
      pcSlice->setMaxBTSize(32>MAX_BT_SIZE_INTER ? MAX_BT_SIZE_INTER: 32);
      }
      else if (dBlkSize < AMAXBT_TH64)
      {
      pcSlice->setMaxBTSize(64>MAX_BT_SIZE_INTER ? MAX_BT_SIZE_INTER: 64);
      }
      else
      {
      pcSlice->setMaxBTSize(128>MAX_BT_SIZE_INTER? MAX_BT_SIZE_INTER: 128);
      ...
    • 宏AMIN_QT,对于非I Slice,利用同一layer上CU的平均边长,对当前QT的最小划分尺寸进行约束。
       
      if (dBlkSize > AMINQT_TH32 && MAX_BT_DEPTH_INTER>=4)
      {
      pcSlice->setMinQTSize(32);
      }
    • 宏SKIP_DEPTH,当当前最佳预测模式为skip模式时,且BT深度大于等于SKIP_DEPTH时,则跳过BT和QT划分。
       
      if (rpcBestCU->getSkipFlag(0) && (bTestHorSplit || bTestVerSplit) && uiBTDepth>=SKIP_DEPTH)
      {
      bTestHorSplit = bTestVerSplit = bQTSplit = false;
      }
    • 宏SKIPHORNOVERQT_DEPTH_TH,当当前CU允许Horizontal划分,且当前最佳预测模式为skip模式,且最佳BT划分深度是当前深度,且当前BT深度大于等于SKIPHORNOVERQT_DEPTH_TH时,则
      跳过Vertical划分和QT。
       
      if (bTestHorSplit && rpcBestCU->isSkipped(0) && rpcBestCU->getBTDepth(0)==uiBTDepth && uiBTDepth>=SKIPHORNOVERQT_DEPTH_TH)
      {
      bTestVerSplit = bQTSplit = false;
      }
    • 宏BT_RMV_REDUNDANT,减少BT和QT重复计算,如下图所示,若CU划分为horizontal BT,则当第一个BT块做完xCompressCU后,得到最佳划分模式是vertical BT,那么,当第二个BT块做xCompressCU时,则直接跳过vertical BT的划分。原因在于,当前CU支持QT划分,那么QT划分时的块预测和第一个BT再进行vertical BT划分+第二个BT再进行verticalBT划分是一样的。因此,对于第二个BT而言,存在冗余的BT划分,即可跳过。同理,对于先Vertical划分BT而言,第二个块也可能存在类似的冗余。
      这里写图片描述
    • 宏MRG_FAST,根据SATD的代价先对merge candidate排序,并选择SATD较小的几个进行RDO。个数由即使SATD的大小与阈值MRG_FAST_RATIO决定。
    • 宏NEIGHBOR_FAST,先计算相邻块left, bottom, top, top right的depth(需满足所有相邻块都存在)的最小和最大depth,只有当当前CUdepth大于等于最小depth,则不做不划分;当当前CUdepth小于等于最大depth,则不做QT & BT。
    • 宏PBITNTRA_FAST,是PB Slice内的intra2Nx2N模式的一种加速算法。利用HAD计算RMD,并保存最小的三个HADcost,从小到大依次记为HAD1,HAD2,HAD3。与帧间预测得到的HAD0比较,当HAD1 > HAD0*阈值时,则跳过所有mode的full RDO,并结束帧内预测。当HAD2 > HAD0*阈值时,则仅对最小HAD的模式做full RDO。当HAD3 > HAD0 * 阈值时,则仅对最小的两个HAD对应的模式做full RDO。
    • 宏ITSKIP,当变换块大于32x32时,跳过所有全零行的反变换
原创粉丝点击