HEVC的幀內預測(1)
HEVC的幀內預測(intra prediction),即intra塊的預測過程,為intra塊解碼提供預測值(predSamples[ x ][ y ])。
首先要確定當前塊和鄰塊的關係。
1.z-scan order block availability
z-scan order block availability,就是在Z順序掃描下的availability。
首先介紹計算MinTbAddrZs的方法
陣列MinTbAddrZs表示以最小塊(minimum blocks)為單位的z-scan 順序地址,最小塊的尺寸由變數Log2MinTrafoSize決定。
由以下公式得到:
看著是不是很頭疼?有沒有想死的感覺?
其中:CtbLog2SizeY為ctb(coding tree block)的尺寸對數,MinTbLog2SizeY為最小的Tb(transform block變換塊)的尺寸對數。ctbAddrRs為當前ctb的raster掃描地址,CtbAddrRsToTs[ ctbAddrRs ]就是將ctbAddrRs轉化為了Ts(tiles)掃描地址(詳見HEVC標準中的影象分割(1))。
其實這公式表達的意思就是當前以最小塊為單位的座標(x,y)的地址,此地址的定址順序在CTB內部為z-scan,在跨越CTB時為tile掃描順序。
舉個例子,如圖:
在圖(1)中,黃色塊代表當前的ctb,粗黑線標出了tile的邊界,小方塊代表ctb,黃色塊代表(x,y)所在的ctb,即當前ctb,虛線箭頭就是ts掃描的方向。則根據公式,當前ctb的ts掃描地址為24。
圖(2)中,大的黃色塊代表當前ctb,陰影塊代表(x,y)所在的tb,假設CtbLog2SizeY = 4,MinTbLog2SizeY = 3,一個ctb中包含4個tb。(x,y)在當前ctb的地址為2。
所以MinTbAddrZs = 24 + 2 = 26嗎?錯!!!
因為前面掃描過的ctb都有4個tb,所以MinTbAddrZs = 24*4 + 2 = 98.
當前塊左上角畫素座標(xCurr, yCurr),由以上MinTbAddrZs步驟計算出其最小塊地址minBlockAddrCurr。
再計算左上角座標為(xNbY, yNbY)的相鄰塊的最小塊地址,minBlockAddrN
當相鄰塊位於影象範圍外時,minBlockAddrN為-1,否則根據MinTbAddrZs方法進行計算。
如果有一個或者多個下列條件為真時,availableN 為FALSE
1. minBlockAddrN 小於0
2. minBlockAddrN 比 minBlockAddrCurr大
3. 相鄰塊所在的slice segment對應的SliceAddrRs和當前塊所在的slice segment對應的SliceAddrRs不同。
4. 相鄰塊和當前塊處於不同的tile。
否則, availableN為TRUE。
在intraSplitFlag為1時,要把當前的色度塊分成4個塊進行處理。
2.幀內預測模式計算
HEVC的幀內預測有34中模式,比H264的幀內預測更加精細。如下圖的對比
H.264的intra預測模式
HEVC的intra預測模式引入HEVC的幀內預測模式值與名稱的對應
0:INTRA_PLANAR
1:INTRA_DC
2~34:INTRA_ANGULAR2~INTRA_ANGULAR34
幀內預測模式的值可以下步驟得出:
1. 用A表示當前塊左邊鄰塊,B表示當前快上邊鄰塊。
2.計算備選幀內預測模式(candIntraPredModeX,X可以為A或者B),有下列步驟:
if(availableX==false)
{
candIntraPredModeX = INTRA_DC;
}
else if((CuPredMode[ xNbX][ yNbX ]!=INTRA)||( pcm_flag[ xNbX ][ yNbX ]==1))
{
candIntraPredModeX = INTRA_DC;
}
else if(B位於另外一個coding tree unit)
{
candIntraPredModeX = INTRA_DC;
}
else
{
candIntraPredModeX= IntraPredModeY[ xNbX ][ yNbX ]
}
其中,availableX表示鄰塊的是否可用,由第1部分介紹的過程得出。
CuPredMode[ xNbX ][ yNbX ]指相鄰塊的預測模式,可為INTRA(1)或INTER(0)。
pcm_flag[ xNbX ][ yNbX ]指相鄰塊的pcm標誌。
IntraPredModeY[ xNbX ][ yNbX ]指相鄰塊的幀內預測模式(範圍:0~34)。
3. 備選模式表(candModeList[ x ], x = 0~2)的計算過程如下:
if (candIntraPredModeB==candIntraPredModeA)
{
if(candIntraPredModeA<2)
{
candModeList[0]=0, candModeList[1]=1,candModeList[2]=26;
}
else
{
candModeList[0] = candIntraPredModeA
candModeList[1] = 2 + ( ( candIntraPredModeA + 29 ) % 32 )
candModeList[2] = 2 + ( ( candIntraPredModeA −2 + 1 ) % 32 )
}
}
else
{
candModeList[0] = candIntraPredModeA
candModeList[1] = candIntraPredModeB
if((candModeList[0]!=0)&&( candModeList[1]!=0))
candModeList[2] =0;
elseif((candModeList[0]!=1)&&( candModeList[ 1 ]!=1))
candModeList[2] =1;
else
candModeList[2] =26;
}
完成此步驟後,得到備選模式表candModeList[x ]。
4.當前幀的亮度幀內預測解碼模式(IntraPredModeY[ xPb ][ yPb ]),由以下步驟得出:
if(prev_intra_luma_pred_flag[ xPb ][ yPb ] ==1)
{
IntraPredModeY[ xPb ][ yPb ] = candModeList[ mpm_idx ]
}
else
{
if(candModeList[ 0 ]>candModeList[ 1 ])
Swap( candModeList[ 0 ], candModeList[ 1 ] )
if(candModeList[ 0 ]>candModeList[ 2 ])
Swap( candModeList[ 0 ], candModeList[ 2 ] )
if(candModeList[ 1 ]>candModeList[ 2 ])
Swap( candModeList[ 1 ], candModeList[ 2 ] )
IntraPredModeY[ xPb ][ yPb ] =rem_intra_luma_pred_mode[ xPb ][ yPb ];
for(i=0;i<2;i++)
{
if(IntraPredModeY[ xPb ][ yPb ] >= candModeList[ i ])
IntraPredModeY[ xPb ][ yPb ]++;
}
}
其中,prev_intra_luma_pred_flag,mpm_idx和rem_intra_luma_pred_mode都是coding_uint中的語法元素,可由cabac解碼得到。至此,得到亮度的幀內預測模式(IntraPredModeY)。