H266/VVC 桌面内容编码工具集中 IBC 技术

帧内块拷贝 IBC

  1. IBC是在HEVC扩展中采用的一种工具,它显著提高了屏幕内容材料的编码效率。由于IBC模式作为块级编码模式实现,因此在编码器中执行块匹配(BM)以找到每个编码单元(CU)的最优块向量(或运动向量)。这里,块向量用于指示从当前块到参考块的位移。

  2. IBC编码的CU的亮度块向量以整数精度表示。色度块向量也四舍五入到整数精度。当与AMVR结合使用时,IBC模式可以在1像素和4像素运动向量精度之间切换。IBC编码的CU被视为除帧内预测或帧间预测模式之外的第三种预测模式。IBC模式适用于宽度和高度均小于或等于64个亮度样本的CU。

  3. 在编码器端,为IBC执行基于哈希的运动估计。编码器对宽度或高度不超过16个亮度样本的块执行RD检查。对于非合并模式,首先使用基于哈希的搜索执行块向量搜索。如果哈希搜索没有返回有效候选,则执行基于块匹配的局部搜索。

  4. 在基于哈希的搜索中,当前块与参考块之间的哈希键匹配(32位CRC)扩展到所有允许的块大小。当前图像中每个位置的哈希键计算基于4x4子块。对于较大尺寸的当前块,当所有4x4子块的哈希键与参考位置中的哈希键匹配时,确定一个哈希键以匹配参考块。如果发现多个参考块的哈希键与当前块匹配,则计算每个匹配参考的块向量成本,并选择具有最小成本的一个。

  5. 在块匹配搜索中,搜索范围设置为覆盖先前和当前CTU。

  6. 在CU级别,IBC模式用标志信号传输,并且可以信号传输为IBC AMVP模式或IBC跳过/合并模式,如下所示:
    ○ IBC跳过/合并模式:使用合并候选索引来指示来自邻近候选IBC编码块的块向量列表中的哪一个用于预测当前块。合并列表由空间、HMVP和成对候选组成。
    ○ IBC AMVP模式:块向量差以与运动向量差相同的方式编码。块向量预测方法使用两个候选作为预测器,一个来自左侧邻居,一个来自上方邻居(如果IBC编码)。当任一邻居不可用时,将使用默认块向量作为预测器。用标志信号传输块向量预测器索引。

  7. IBC参考区域:为了减少内存消耗和解码器复杂性,IBC在 VTM8 中仅允许重建当前CTU区域和左侧CTU的一些区域的预定义区域。图57展示了IBC模式的参考区域,其中每个块代表64x64亮度样本单元。
    在这里插入图片描述

    • 根据当前编码CU在当前CTU中的位置,适用以下规则:
      • 如果当前块落入当前CTU的左上64x64块中,则除了当前CTU中已重建的样本外,还可以参考左侧CTU的右下64x64块中的参考样本,使用CPR模式。当前块还可以参考左侧CTU的左下64x64块和右上64x64块中的参考样本,使用CPR模式。
      • 如果当前块落入当前CTU的右上64x64块中,则除了当前CTU中已重建的样本外,如果亮度位置(0,64)相对于当前CTU尚未重建,当前块还可以参考左侧CTU的左下64x64块和右下64x64块中的参考样本,使用CPR模式;否则,当前块还可以参考左侧CTU的右下64x64块中的参考样本。
      • 如果当前块落入当前CTU的左下64x64块中,则除了当前CTU中已重建的样本外,如果亮度位置(64,0)相对于当前CTU尚未重建,当前块还可以参考左侧CTU的右上64x64块和右下64x64块中的参考样本,使用CPR模式。否则,当前块还可以参考左侧CTU的右下64x64块中的参考样本,使用CPR模式。
      • 如果当前块落入当前CTU的右下64x64块中,则只能参考当前CTU中已重建的样本,使用CPR模式。
    • 这种限制允许IBC模式使用本地片上内存进行硬件实现。
  8. IBC与其他编码工具的交互:IBC模式与VTM8中的其他编码工具(如成对合并候选、基于历史的运动向量预测器(HMVP)、结合内/外预测模式(CIP)、带有运动向量差的合并模式(MMVD)和几何分区模式(GPM))的交互如下:

    • IBC可以与成对合并候选和HMVP一起使用。可以通过平均两个IBC合并候选生成一个新的成对IBC合并候选。对于HMVP,IBC运动插入历史缓冲区以供将来参考。

    • IBC不能与以下工具结合使用:仿射运动、CIP、MMVD和GPM。

    • 当使用DUAL_TREE分区时,IBC不允许用于色度编码块。

    • 与HEVC屏幕内容编码扩展不同,当前图像不再作为IBC预测的参考图像列表中的一部分。IBC模式的运动向量推导过程排除了内模式中的所有邻近块,反之亦然。应用以下IBC设计方面:

      • IBC与常规MV合并共享相同的过程,包括成对合并候选和基于历史的运动预测器,但不允许TMVP和零向量,因为它们在IBC模式中无效。
      • 为常规MV和IBC分别使用单独的HMVP缓冲区(每个5个候选)。
      • 块向量约束以比特流一致性约束的形式实现,编码器需要确保比特流中没有无效向量,如果合并候选无效(超出范围或0),则不得使用合并。这种比特流一致性约束以虚拟缓冲区的形式表达,如下所述。
      • 对于去块效应,IBC作为内模式处理。
      • 如果当前块使用IBC预测模式编码,AMVR不使用四分之一像素;相反,AMVR仅用于指示MV是内像素还是4个整数像素。
      • IBC合并候选的数量可以在切片头中与常规、子块和几何合并候选的数量分开信号传输。
    • 使用虚拟缓冲区概念来描述IBC预测模式和有效块向量的允许参考区域。将CTU大小表示为ctbSize,虚拟缓冲区ibcBuf的宽度为wlbcBuf = 128x128/ctbSize,高度为hlbcBuf = ctbSize。例如,对于128x128的CTU大小,ibcBuf的大小也是128x128;对于64x64的CTU大小,ibcBuf的大小为256x64;对于32x32的CTU大小,ibcBuf的大小为512x32。

    • VPDU的大小在每个维度上为min(ctbSize, 64),W = min(ctbSize, 64)。

    • 虚拟IBC缓冲区ibcBuf的维护如下:
      在这里插入图片描述

    • 对于覆盖坐标(x, y)的块,如果以下条件对块向量bx = (bv[0], bv[1])成立,则有效;否则无效:
      在这里插入图片描述

  9. 在 2020 年 1 月的 JVET-Q2002[Algorithm description for Versatile Video Coding and Test Model 8 (VTM 8)] 提案中对 IBC 技术进行了总结描述。
    在这里插入图片描述

  10. 在 VVenC 编码器中 InterSearch.cpp 文件中 searchBvIBC 函数来用于当前编码单元(Coding Unit, CU)在参考块查找最优的块向量,以便从参考块中复制数据。其主要被 xIntraPatternSearchIBC 函数所调用。

bool InterSearch::searchBvIBC(const CodingUnit& cu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xBv, int yBv, int ctuSize) const
{
  const int ctuSizeLog2 = Log2(ctuSize);

  int refRightX  = xPos + xBv + width  - 1;
  int refBottomY = yPos + yBv + height - 1;

  int refLeftX = xPos + xBv;
  int refTopY  = yPos + yBv;

  if ((xPos + xBv) < 0)
  {
    return false;
  }
  if (refRightX >= picWidth)
  {
    return false;
  }

  if ((yPos + yBv) < 0)
  {
    return false;
  }
  if (refBottomY >= picHeight)
  {
    return false;
  }
  if ((xBv + width) > 0 && (yBv + height) > 0)
  {
    return false;
  }

  // Don't search the above CTU row
  if (refTopY >> ctuSizeLog2 < yPos >> ctuSizeLog2)
    return false;

  // Don't search the below CTU row
  if (refBottomY >> ctuSizeLog2 > yPos >> ctuSizeLog2)
  {
    return false;
  }

  unsigned curTileIdx = cu.cs->pps->getTileIdx(cu.lumaPos());
  unsigned refTileIdx = cu.cs->pps->getTileIdx(Position(refLeftX, refTopY));
  if (curTileIdx != refTileIdx)
  {
    return false;
  }
  refTileIdx = cu.cs->pps->getTileIdx(Position(refLeftX, refBottomY));
  if (curTileIdx != refTileIdx)
  {
    return false;
  }
  refTileIdx = cu.cs->pps->getTileIdx(Position(refRightX, refTopY));
  if (curTileIdx != refTileIdx)
  {
    return false;
  }
  refTileIdx = cu.cs->pps->getTileIdx(Position(refRightX, refBottomY));
  if (curTileIdx != refTileIdx)
  {
    return false;
  }

  const Position cuPos{ xPos, yPos };

  //int numLeftCTUs = (1 << ((7 - ctuSizeLog2) << 1)) - ((ctuSizeLog2 < 7) ? 1 : 0);
  static const int numLeftCTUsLUT[3] = { 15, 3, 1 };

  // in the same CTU line
  const int numLeftCTUs = numLeftCTUsLUT[ctuSizeLog2 - 5];

  if( ( refRightX >> ctuSizeLog2 <= xPos >> ctuSizeLog2 ) && ( refLeftX >> ctuSizeLog2 >= ( xPos >> ctuSizeLog2 ) - numLeftCTUs ) )
  {
    // in the same CTU, or left CTU
    // if part of ref block is in the left CTU, some area can be referred from the not-yet updated local CTU buffer
    if( ( ctuSizeLog2 == 7 ) && ( ( refLeftX >> ctuSizeLog2 ) == ( ( xPos >> ctuSizeLog2 ) - 1 ) ) )
    {
      // ref block's collocated block in current CTU
      const Position refPosCol64x64{ ( refLeftX + ctuSize ) & ~63, refTopY & ~63 };
      if( refPosCol64x64 == Position{ xPos & ~63, yPos & ~63 } )
        return false;

      //CodingUnit* curef = cu.cs->getCU(refPosCol64x64, CH_L, cu.treeType);
      //bool isDecomp = curef && ((cu.cs != curef->cs) || cu.idx < curef->idx);
      bool isDecomp = isYPartBefore( cu.splitSeries, ctuSizeLog2, cuPos, refPosCol64x64 );
      if( isDecomp )
      {
        return false;
      }
    }
  }
  else
    return false;

  // in the same CTU, or valid area from left CTU. Check if the reference block is already coded
  const Position refPosBR{ refRightX, refBottomY };
  //CodingUnit* curef = cu.cs->getCU(refPosBR, CH_L, cu.treeType);
  //bool isDecomp = curef && ((cu.cs != curef->cs) || cu.idx < curef->idx);
  bool isDecomp = ( ( refPosBR.x >> ctuSizeLog2 ) < ( cuPos.x >> ctuSizeLog2 ) ) || ( refRightX < xPos && refBottomY < yPos ) || isYPartBefore( cu.splitSeries, ctuSizeLog2, cuPos, refPosBR );

  return isDecomp;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码流怪侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值