HEVC的量化与变换

标准文档中的定义的完整过程如下:

   if( cu_transquant_bypass_flag){

        r[][] = TransCoeffLevel[ xTbY ][ yTbY ][ cIdx ].  cIdx为Y/U/V分量标号.

    }else{

          d[][] = scaling(TransCoeffLevel)

          if(transform_skip_flag){

                 r'[][]=d[][]<<7

           }else{

                r'[][]=transform(d[][])

           }

           bdShift = ( cIdx = = 0 ) ? 20 − BitDepthY : 20 − BitDepthC

             r[ x ][ y ] = ( r'[ x ][ y ] + ( 1 << ( bdShift − 1 ) ) ) >> bdShift

    }

1. scaling过程

  If(cIdx==0){
         bdShift = BitDepthY + Log2( nTbS ) − 5

    }else{
         bdShift = BitDepthC + Log2( nTbS ) − 5

    }

    const levelScale[ 6] = { 40, 45, 51, 57, 64, 72 }

//量化 矩阵的定义如下

If(scaling_list_enabled_flag== 0){
     m[ x ][ y ] = 16

}else{
      m[ x ][ y ] = ScalingFactor[ sizeId ][ matrixId ][ x ][ y ]

}

//反量化过程如下:

d[ x ][ y ] = Clip3( −32768, 32767, ( ( TransCoeffLevel[ xTbY ][ yTbY ][ cIdx ][ x ][ y ] * m[ x ][ y ] * levelScale[ qP%6 ] << (qP / 6 ) ) + ( 1 << ( bdShift − 1 ) ) ) >> bdShift )

在HM的实现代码中,当不使用量化矩阵,即m=16时,并不乘16,只需要在bdShift中少右移4位

2. 变换过程

   If(CuPredMode[ xTbY ][ yTbY ] == MODE_INTRA && nTbS == 4 && cIdx == 0)

          trType  = 1 //使用离散正弦变换
    else

          trType = 0 //使用整数DCT变换

   2.1 变换过程

        1. 先对每列进行列变换得到

                e[][] = transform_col(c[][])

        2.  g[ x ][ y ] = Clip3( −32768, 32767, ( e[ x ][ y ] + 64 ) >> 7 )

        3. 再对每行进行行变换

             r'[][] = transform_row(g[][])


   2.2 列变换和行变换都是对一列或一行进行卷积,卷积公式分别为

       1. DST

  

       2. DCT


HM中的量化过程如下:

根据反量化公式:d[ x ][ y ] = Clip3( −32768, 32767, ( ( TransCoeffLevel[ xTbY ][ yTbY ][ cIdx ][ x ][ y ] * m[ x ][ y ] *levelScale[ qP%6 ] << (qP / 6 ) ) + ( 1 << ( bdShift − 1 ) ) ) >> bdShift )

可推导出量化公式为:T = (d>>(cQP.per-bdShift)/(m*levelScale[cQP.rem])
其中,bdShift = BitDepthY + Log2( nTbS ) − 5, levelScale[k] = { 40, 45, 51, 57, 64, 72 }

当不使用量化矩阵时,m=16,因此m * levelScale[k] = {640, 720,  816, 912,  1024, 1152}

为了避免除法,HM使用觉的方式,将除转为乘,再右移。此右移还可跟d的右移结合在一起,减小计算步数。

可推导出合并后的右移位数为:cQP.per - BitDepthY - Log2( nTbS ) + 5 + PRE_SCALE

而代码中的右移位数为:iQBits =cQP.per - BitDepthY - Log2( nTbS ) + maxLog2TrDynamicRange  + 14

因此,可推荐出PRE_SCALE = maxLog2TrDynamicRange+9

代码中,maxLog2TrDynamicRange为15,因此PRE_SCALE为24

即,先对系数乘以2^24=16777216,再除m * levelScale[k] ,就相当于乘g_quantScales[cQP.rem] = {26214,23302,20560,18396,16384,14564,}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值