[AV1] Transform Block

返回AV1专栏目录

Transform Block

在AV1中,变换编码(Transform Coding)是以块为单位进行的,这个块就称为 Transform Block,我们就姑且叫它“变换块”吧。与前面我提到的Block的概念相比,Transform Block一共包括19种尺寸,与Block的尺寸比起来,可以相同或更小,最大可以达到64x64,最小可以是4x4,源码中对于Transform Block大小的定义是一个名为 TX_SIZE 的枚举变量。

TxSize Name of TxSize 含义
0 TX_4X4 4x4 transform
1 TX_8X8 8x8 transform
2 TX_16X16 16x16 transform
3 TX_32X32 32x32 transform
4 TX_64X64 64x64 transform
5 TX_4X8 4x8 transform
6 TX_8X4 8x4 transform
7 TX_8X16 8x16 transform
8 TX_16X8 16x8 transform
9 TX_16X32 16x32 transform
10 TX_32X16 32x16 transform
11 TX_32X64 32x64 transform
12 TX_64X32 64x32 transform
13 TX_4X16 4x16 transform
14 TX_16X4 16x4 transform
15 TX_8X32 8x32 transform
16 TX_32X8 32x8 transform
17 TX_16X64 16x64 transform
18 TX_64X16 64x16 transform

既然最大的尺寸是64x64,那对于大小超过64的块,例如BLOCK_128x128,BLOCK_128x64,BLOCK_64x128,则需要在内部进行chunk,形成64x64的块后,再进行变换编码运算。

帧内编码的Transform Block划分

Block可以被划分为Transform Block,不同于H.26x系列编码标准,预测编码块与变换编码块,即PU和TU是分开进行划分的,在AV1中,预测编码是以Tranform block为单位进行的,所以做过H.264,HEVC的朋友们,在AV1的源码中,找不到熟悉的PU了 :)

在Intra Prediction的时候,会把块进行划分,最终选择最佳的分块大小,此时的分块大小使用 tx_depth来表示,并且传给解码器,tx_depth的取值范围为[0, 2],其中0为不划分,2为向下划分两级。

可以参考Spec中的 MAX_TX_DEPTH 参数,其值为2

Spec 5.11.15. TX size syntax
read_tx_size( allowSelect ) {
    
    
	if ( Lossless ) {
    
    
		TxSize = TX_4X4
		return
	}
	maxRectTxSize = Max_Tx_Size_Rect[ MiSize ]
	maxTxDepth = Max_Tx_Depth[ MiSize ]
	TxSize = maxRectTxSize
	if ( MiSize > BLOCK_4X4 && allowSelect && TxMode == TX_MODE_SELECT ) {
    
    
		tx_depth  // 此处parse出tx_depth
		for ( i = 0; i < tx_depth; i++ )
			TxSize = Split_Tx_Size[ TxSize ]
		} 
	} 
}
tx_depth 以Block的大小等于64x64为例子,Transform Block大小
0 64x64
1 32x32
2 16x16

具体的划分情况如下图所示
Transform Block Split
从上面的图可以看出,随着tx_depth的增大,transform block是逐渐以1/4的变化率在变小。上面的例子只讲了当block为正方形的时候的划分方法,那下面来说说当block的size不是正方形的情况该怎么划分。对于一个32x64的块,下面是一个例子,可以先上下均分为两个32x32的块,然后每个32x32的话可以依据上面例子的方式再次划分为16x16大小的块。

Transform Block Split
在帧内编码的情况下,变换编码的执行顺序是光栅扫描顺序(Raster scan),所以在编码时,依据从上到下,从左到右的顺序进行。

帧间编码的Transform Block划分

对于帧间编码的情况,其划分情况与帧内编码的相似,也是向下划分最多为两级,同样,也要将划分的级数传递给decoder,只不过syntax的名字不叫tx_depth了,而是txfm_split

在Spec中,函数read_var_tx_size是用来阅读流中的txfm_split的函数(实际代码中,函数调用名和变量名会有所不同)

read_var_tx_size( row, col, txSz, depth) {
    
     
	if ( row >= MiRows || col >= MiCols )
		return
	if ( txSz == TX_4X4 || depth == MAX_VARTX_DEPTH ) {
    
    
		txfm_split = 0
	} else {
    
    
		txfm_split // parsing
	}
}

具体的划分图如下
inter txfm block spliting
画成树状图更容易理解些。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/starperfection/article/details/109147179