HEVC学习(二十五) —— 变换系数的编码之一

本文首先介绍系数扫描模式的初始化。

直接给出代码及相应的注释:

 

// scanning order table
UInt* g_auiSigLastScan[ 3 ][ MAX_CU_DEPTH ]; //!< [pattern][depth]

const UInt g_sigLastScan8x8[ 3 ][ 4 ] =
{
  {0, 2, 1, 3}, //!< right-up diagonal
  {0, 1, 2, 3}, //!< horizontal
  {0, 2, 1, 3}  //!< vertical
};
UInt g_sigLastScanCG32x32[ 64 ];


 

Void initSigLastScan(UInt* pBuffD, UInt* pBuffH, UInt* pBuffV, Int iWidth, Int iHeight, Int iDepth)
{
  const UInt  uiNumScanPos  = UInt( iWidth * iWidth );
  UInt        uiNextScanPos = 0;

  /*
  ** 在这里需要先作如下说明,以免对接下来代码中的一些处理会有疑惑。
  ** 首先,在初始化时,总共有2x2,4x4,8x8,16x16,32x32,64x64,128x128这7种情况,当然,我们实际使用
  ** 的就只有4x4,8x8,16x16,32x32这4种,其余的几种至少目前的draft中是不采用的,故重点关注这4种即可。
  ** 其次,这段初始化代码是基于JCTVC-G644这个提案的,提案的具体内容请自行把这个提案下载下来阅读,这里
  ** 不作详细介绍。
  */

  if( iWidth < 16 )
  {
  UInt* pBuffTemp = pBuffD;
  if( iWidth == 8 )
  {
    pBuffTemp = g_sigLastScanCG32x32; //!< 用于TU为32x32时的系数扫描,CG为Coefficient Group的缩写
  }
  for( UInt uiScanLine = 0; uiNextScanPos < uiNumScanPos; uiScanLine++ )
  {
    Int    iPrimDim  = Int( uiScanLine );	//!< uiScanLine为已经扫描过的反对角线数
    Int    iScndDim  = 0;						//!< 在某条反对角线上的计数
    while( iPrimDim >= iWidth )				//!< 扫描的反对角线如果已经超过矩阵反对角线数的一半
    {													//!< 则根据该反对角线与反主对角线的距离,距离每增加1,则总元素数减1
      iScndDim++;
      iPrimDim--;
    }
    while( iPrimDim >= 0 && iScndDim < iWidth ) //!< 设置矩阵中某一条反对角线上(左下到右上)的元素的序号 
    {//!< pBuffTemp赋值的原理:iPrimDim控制当前扫描到的元素的行数,iiScndDim控制该元素在反对角线上的序号
      pBuffTemp[ uiNextScanPos ] = iPrimDim * iWidth + iScndDim ;
      uiNextScanPos++;
      iScndDim++;
      iPrimDim--;
    }
  }
  }
  if( iWidth > 4 )
  {
    UInt uiNumBlkSide = iWidth >> 2;						//!< 以4x4像素为一个单元
    UInt uiNumBlks    = uiNumBlkSide * uiNumBlkSide; //!< 单元数
    UInt log2Blk      = g_aucConvertToBit[ uiNumBlkSide ] + 1;

    for( UInt uiBlk = 0; uiBlk < uiNumBlks; uiBlk++ )
    {
      uiNextScanPos   = 0;
      UInt initBlkPos = g_auiSigLastScan[ SCAN_DIAG ][ log2Blk ][ uiBlk ]; //!< 以4x4块为单元的位置(序号)	
      if( iWidth == 32 )
      {
        initBlkPos = g_sigLastScanCG32x32[ uiBlk ]; //!< TU为32x32时,不会再在16个4x4块中进行up-right diamond扫描,而直接在整一个32x32中以4x4块为单元进行扫描
      }
      UInt offsetY    = initBlkPos / uiNumBlkSide;					//!< 当前4x4块垂直方向的偏移量
      UInt offsetX    = initBlkPos - offsetY * uiNumBlkSide;	//!< 当前4x4块水平方向的偏移量
      UInt offsetD    = 4 * ( offsetX + offsetY * iWidth );		//!< 当前4x4块第一个位置序号
      UInt offsetScan = 16 * uiBlk;	//!< 每一个4x4块包含了16个像素(即系数),用于给出当前4x4块第一个位置相对于第1个4x4块第一个位置的偏移量
      for( UInt uiScanLine = 0; uiNextScanPos < 16; uiScanLine++ ) //!< 对每个4x4块进行扫描顺序的确定	
      {
        Int    iPrimDim  = Int( uiScanLine );
        Int    iScndDim  = 0;
        while( iPrimDim >= 4 ) //!< 则根据该反对角线与反主对角线的距离,距离每增加1,则总元素数减1
        {
          iScndDim++;
          iPrimDim--;
        }
        while( iPrimDim >= 0 && iScndDim < 4 ) //!< 设置矩阵中某一条反对角线上(左下到右上)的元素的序号 
        {
          pBuffD[ uiNextScanPos + offsetScan ] = iPrimDim * iWidth + iScndDim + offsetD;
          uiNextScanPos++;
          iScndDim++;
          iPrimDim--;
        }
      }
    }
  }
  
  UInt uiCnt = 0;
  if( iWidth > 2 )
  {//!< 水平扫描模式
    UInt numBlkSide = iWidth >> 2;  
    for(Int blkY=0; blkY < numBlkSide; blkY++) //!< 以4x4块为单元,行优先
    {
      for(Int blkX=0; blkX < numBlkSide; blkX++)
      {
        UInt offset    = blkY * 4 * iWidth + blkX * 4; //!< 确定当前4x4块的第一个位置序号
        for(Int y=0; y < 4; y++) //!< 对每个4x4块中的16个位置进行遍历,行优先
        {
          for(Int x=0; x < 4; x++)
          {
            pBuffH[uiCnt] = y*iWidth + x + offset;
            uiCnt ++;
          }
        }
      }
    }
    //!< 垂直扫描模式
    uiCnt = 0;
    for(Int blkX=0; blkX < numBlkSide; blkX++) //!< 以4x4块为单元,列优先
    {
      for(Int blkY=0; blkY < numBlkSide; blkY++)
      {
        UInt offset    = blkY * 4 * iWidth + blkX * 4;
        for(Int x=0; x < 4; x++) //!< //!< 对每个4x4块中的16个位置进行遍历,行优先
        {
          for(Int y=0; y < 4; y++)
          {
            pBuffV[uiCnt] = y*iWidth + x + offset;
            uiCnt ++;
          }
        }
      } //!< for(Int blkY=0; blkY < numBlkSide; blkY++)       
    } //!< for(Int blkX=0; blkX < numBlkSide; blkX++)     
  } //!< if( iWidth > 2 )   
  else  //!< if( iWidth <= 2 )
  { //!< Horizontal scan pattern
  for(Int iY=0; iY < iHeight; iY++)
  {
    for(Int iX=0; iX < iWidth; iX++)
    {
      pBuffH[uiCnt] = iY*iWidth + iX;
      uiCnt ++;
    }
  }

  //!< Vertical scan pattern
  uiCnt = 0;
  for(Int iX=0; iX < iWidth; iX++)
  {
    for(Int iY=0; iY < iHeight; iY++)
    {
      pBuffV[uiCnt] = iY*iWidth + iX;
      uiCnt ++;
    }
  }    
  } //!< else //!< if( iWidth <= 2 )
}


 

发布了97 篇原创文章 · 获赞 855 · 访问量 106万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章