H.266/VVC代码学习笔记17:VTM6.0中的xWeightedTriangleBlk()函数

在之前的博客详细讲了一下目前VVC中的TPM技术的详细原理,其中涉及到了三角预测模式中对角线周围加权区域的自适应权重加权过程,链接为: H.266/VVC相关技术学习笔记:帧间预测中的TPM技术(Triangle partition Mode) 本篇博客将加权融合过程的函数xWeightedTriangleBlk()的代码附上,本人加了基本的注释,如果有错误或者有疑问的地方可以私信我。

//三角预测模式真正的加权过程在该函数中
void InterpolationFilter::xWeightedTriangleBlk( const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 )
{
  Pel*    dst        = predDst .get(compIdx).buf;//加权区的加权预测值
  Pel*    src0       = predSrc0.get(compIdx).buf;//分区一对应颜色分量的单向预测值
  Pel*    src1       = predSrc1.get(compIdx).buf;//分区二对应颜色分量的单向预测值
  int32_t strideDst  = predDst .get(compIdx).stride  - width;//加权预测区的跨度
  int32_t strideSrc0 = predSrc0.get(compIdx).stride  - width;//分区一的跨度
  int32_t strideSrc1 = predSrc1.get(compIdx).stride  - width;//分区二的跨度

  const char    log2WeightBase    = 3;//权重基的log2设置为3,权重基为8,就是除以8,这和三角权重表中一致,权重表中的权重基本都为8分之几
  const ClpRng  clipRng           = pu.cu->slice->clpRngs().comp[compIdx];
  const int32_t clipbd            = clipRng.bd;
  const int32_t shiftDefault      = std::max<int>(2, (IF_INTERNAL_PREC - clipbd));//默认移位值
  const int32_t offsetDefault     = (1<<(shiftDefault-1)) + IF_INTERNAL_OFFS;//默认偏移值
  const int32_t shiftWeighted     = std::max<int>(2, (IF_INTERNAL_PREC - clipbd)) + log2WeightBase;//加权移位值
  const int32_t offsetWeighted    = (1 << (shiftWeighted - 1)) + (IF_INTERNAL_OFFS << log2WeightBase);//加权偏移值

  const int32_t ratioWH           = (width > height) ? (width / height) : 1;//PU宽高比
  const int32_t ratioHW           = (width > height) ? 1 : (height / width);//PU高宽比

  const bool    longWeight        = (compIdx == COMPONENT_Y);//是否是长权重,即亮度分量的预测权重会设置大一些,色度的话会小一些
  const int32_t weightedLength    = longWeight ? 7 : 3;//如果是亮度分量,设置为7,即7/8
        int32_t weightedStartPos  = ( splitDir == 0 ) ? ( 0 - (weightedLength >> 1) * ratioWH ) : ( width - ((weightedLength + 1) >> 1) * ratioWH );//加权的开始位置
        int32_t weightedEndPos    = weightedStartPos + weightedLength * ratioWH - 1;//加权的结束位置。
        int32_t weightedPosoffset = ( splitDir == 0 ) ? ratioWH : -ratioWH;//加权位置的偏置。

        Pel     tmpPelWeighted;//临时的像素加权值
        int32_t weightIdx;//权重索引
        int32_t x, y, tmpX, tmpY, tmpWeightedStart, tmpWeightedEnd;
        //X ,Y分量,以及X、Y分量的缓存,加权开始的缓存以及加权结束的缓存

  for( y = 0; y < height; y+= ratioHW )//逐行遍历,然后对逐行上逐个像素点进行遍历
  {
    for( tmpY = ratioHW; tmpY > 0; tmpY-- )
    {
      for( x = 0; x < weightedStartPos; x++ )//从行上的0位置到加权开始的位置,逐像素遍历,将非加权区的预测值直接嵌位后保存到最终预测值的缓存predDst中
      {
        *dst++ = ClipPel( rightShift( (splitDir == 0 ? *src1 : *src0) + offsetDefault, shiftDefault), clipRng );//得到各自分区的预测值(未加权)
        src0++;
        src1++;
      }

      tmpWeightedStart = std::max((int32_t)0, weightedStartPos);
      tmpWeightedEnd   = std::min(weightedEndPos, (int32_t)(width - 1));
      weightIdx        = 1;
      if( weightedStartPos < 0 )
      {
        weightIdx     += abs(weightedStartPos) / ratioWH;
      }
      for( x = tmpWeightedStart; x <= tmpWeightedEnd; x+= ratioWH )//从行上的加权开始位置到该行加权结束位置,逐像素遍历,利用两个分区的预测值加权计算加权区的预测值,嵌位后保存到predDst中
      {
        for( tmpX = ratioWH; tmpX > 0; tmpX-- )
        {
          tmpPelWeighted = Clip3( 1, 7, longWeight ? weightIdx : (weightIdx * 2));//根据离分割线的距离得到不同的加权权重
          tmpPelWeighted = splitDir ? ( 8 - tmpPelWeighted ) : tmpPelWeighted;
          *dst++         = ClipPel( rightShift( (tmpPelWeighted*(*src0++) + ((8 - tmpPelWeighted) * (*src1++)) + offsetWeighted), shiftWeighted ), clipRng );
        }
        weightIdx ++;
      }

      for( x = weightedEndPos + 1; x < width; x++ )//从行上的加权结束位置到该行末尾的位置,逐像素遍历,将非加权区的预测值直接嵌位后保存到最终预测值的缓存predDst中
      {
        *dst++ = ClipPel( rightShift( (splitDir == 0 ? *src0 : *src1) + offsetDefault, shiftDefault ), clipRng );
        src0++;
        src1++;
      }

      dst  += strideDst;
      src0 += strideSrc0;
      src1 += strideSrc1;
    }
    weightedStartPos += weightedPosoffset;
    weightedEndPos   += weightedPosoffset;
  }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值