HM is the official reference software for H.265/HEVC, which is a block-based hybrid coding standard that divides quadtree in CTU units. The maximum CTU specified in H.265 is 64×64. CTU information in HM is stored in the TComDataCU class, which has the following definition (the definition is too long) :

class TComDataCU
{
private:
​
  // -------------------------------------------------------------------------------------------------------------------
  // class pointers
  // -------------------------------------------------------------------------------------------------------------------
​
  TComPic*      m_pcPic;                                ///< picture class pointer
  TComSlice*    m_pcSlice;                              ///< slice header pointer
​
  // -------------------------------------------------------------------------------------------------------------------
  // CU description
  // -------------------------------------------------------------------------------------------------------------------
  // how to save partition information in hm. See pCtu->getDepth(I), where I represents the number of the current CTU assigned to the minimum CU.
  // For example, 64*64 is divided into 256 4*4 numbers. The member variable m_puhDepth[uiIdx] is used to record CU depth information.
  // m_puhDepth[uiIdx] is processed in rpcTempCU.
​
  UInt          m_ctuRsAddr;                            ///< CTU (also known as LCU) address in a slice (Raster-scan address, as opposed to tile-scan/encoding order).
  UInt          m_absZIdxInCtu;                         ///< absolute address in a CTU. It's Z scan order
  UInt          m_uiCUPelX;                             ///< CU position in a pixel (X)
  UInt          m_uiCUPelY;                             ///< CU position in a pixel (Y)
  UInt          m_uiNumPartition;                       ///< total number of minimum partitions in a CU
  UChar*        m_puhWidth;                             ///< array of widths
  UChar*        m_puhHeight;                            ///< array of heights
  UChar*        m_puhDepth;                             ///< array of depths
  Int           m_unitSize;                             ///< size of a "minimum partition"
      SChar*        m_pePartSize;                           ///< array of partition sizes
  SChar*        m_pePredMode;                           ///< array of prediction modes./ / to omit
}
Copy the code

CTU can be recursively divided into sub-Cu in a quadtree manner, and sub-Cu is recursively processed in zig-Zag order, as shown in the figure below:

 

The numbers in the figure are the processing order of CU.

In fact, the entire CTU is stored in the TComDataCU class, and only one copy of the data is stored in the CTU. The child CU only needs to specify its location in the CTU. The class member variable m_absZIdxInCtu represents the position of the child CU in CTU (Zig-Zag order).

CTU is not represented in the form of a two-dimensional array. Because CTU is divided in different ways and the depth of each part is different, the “shape” of CTU cannot be represented in a unified form.

To represent CTU succinctly with a uniform data structure, the TComDataCU class divides CTU into 4×4 pieces, storing the depth of each piece. A 64×64 CTU can be divided into 256 4×4 blocks and a 32×32 CTU can be divided into 64 4×4 blocks.

 

The image above shows the result of a 32×32 CTU divided into 64 4×4 blocks, scanned in zig-Zag order.

The members m_puhWidth, m_puhHeight, and m_puhDepth of the TComDataCU class store the width, height, and depth of each 4×4 patch.

Here is an example of a real 64x64CTU partition:

 

The 64×64 CTU above contains 256 4×4 blocks, each of which corresponds to the following width, height, and depth:

 

Since quadtree partitions are all square blocks, they are the same width and height. Comparing the m_puhDepth array with the partition structure above shows that both results are consistent. (Note: Arrays are printed in Zig-Zag order)

HM provides two arrays, g_auiZscanToRaster and g_auiRasterToZscan, which can perform the conversion between zig- ZAG order and raster scan order.

g_auiZscanToRaster[ z-scan index ] = raster scan index
g_auiRasterToZscan[ raster index ] = z-scan index
Copy the code

If you are interested, please pay attention to wechat public account Video Coding