《H.264/AVC視訊編解碼技術詳解》視訊教程已經在“CSDN學院”上線,視訊中詳述了H.264的背景、標準協議和實現,並通過一個實戰工程的形式對H.264的標準進行解析和實現,歡迎觀看!

“紙上得來終覺淺,絕知此事要躬行”,只有自己按照標準文件以程式碼的形式操作一遍,才能對視訊壓縮編碼標準的思想和方法有足夠深刻的理解和體會!

連結地址:H.264/AVC視訊編解碼技術詳解

GitHub程式碼地址:點選這裡

一、視訊的時間冗餘

在本系列博文的第三篇中,我們初步瞭解了H.264視訊編碼技術的基本結構和框架:

在H.264中,預測編碼與變換/量化編碼、熵編碼並列的重要組成部分,對編解碼器的效能具有重大影響。預測編碼主要包括兩部分:幀內預測和幀間預測。在前面的博文中我們討論了幀內預測編碼的基本原理和實現方法:

幀內編碼的影象其最主要特點是可以不依賴參考影象,可以獨立解碼,因而可以作為一個GOP的起點和隨機接入點,即IDR幀;然而另一方面,按照幀內編碼輸出的位元速率相對較高,即壓縮率較低。究其原因在於,幀內編碼為了確保可獨立解碼這一最關鍵的特性,只利用了影象的空間冗餘進行壓縮,無法充分利用視訊資訊前後幀之間的關聯。

與幀內編碼不同,幀間編碼所利用的是視訊的時間冗餘。通常在視訊資訊中,每一幀所包含的物體物件與其前後幀之間存在運動關係,這種物體的運動關係即構成幀與幀之間的時間冗餘。由於幀與幀之間物體的運動相關性大於一幀內部相鄰畫素之間的相關性,尤其對於時間相近的影象之間,時間冗餘比空間冗餘更加明顯。

影象之間物體的運動關係可由下圖表示:

在這裡插入圖片描述

二、塊結構的運動估計和運動補償

在H.264中,壓縮時間冗餘並非通過前幀和後幀之間求取整幀差分這種低效率的方法。H.264是一種基於塊結構的混合編碼標準,因此幀間編碼也以畫素塊的形式實現。同幀內編碼類似,幀間編碼同樣以一個巨集塊(Macroblock, MB)作為最小單位進行。

在H.264的整體流程中,幀間編碼可分為幾個步驟執行:

  • 預測編碼(包括運動估計/運動補償過程);
  • 變換/量化編碼;
  • 熵編碼;
  • 參考幀管理;

其中,變換/量化編碼和熵編碼採用了與幀內編碼相同或相似的方案。而預測編碼採用了基於塊的運動估計(Motion Estimation, ME)和運動補償(Motion Compensation, MC)的方法,此方法與幀內預測對應,亦稱為幀間預測(Inter-Frame Prediction/Inter Prediction)。在H.264框架中表示如下圖所示:

在這裡插入圖片描述

三、運動估計

運動估計,有時也稱作運動搜尋,即在相應參考幀中搜索當前畫素塊的對應參考畫素塊,使最終的編碼代價最小。為了實現這個目標,相比幀內編碼所定義的16×16和8×8兩種巨集塊劃分方式,幀間編碼定義了更多、更復雜的方法。

3.1 運動估計巨集塊劃分

當一個巨集塊將按幀間編碼進行編碼時,該巨集塊將按照某種預定義的方法進行分割。針對幀間預測,H.264定義了4種巨集塊分割和4種子巨集塊分割方式:

  • 巨集塊分割:16×16、16×8、8×16、8×8;
  • 子巨集塊分割:8×8、8×4、4×8、4×3;

幀間預測的巨集塊分割如下圖所示:

在這裡插入圖片描述

當某個巨集塊配置為8×8形式時,每個8×8巨集塊將按照子巨集塊的分割方法來進行進一步分割。

3.2 運動向量

在一個幀間編碼巨集塊中,每一個分割後的子塊都會進行相應的運動搜尋,在參考幀中查詢對應的相同尺寸的畫素塊作為參考。當前畫素塊在當前幀中的位置同參考塊在參考幀總的位置之間的相對位置代表了畫素塊中的物體在兩幀之間的運動軌跡。這個相對位置以兩個座標值組成的向量(MV_x, MV_y)表示,稱為運動向量(Motion Vector, MV)。一個巨集塊最多可能包含16個MV。一個運動向量的例子可由下圖表示:

在這裡插入圖片描述
在上圖中某個畫素塊在參考幀和當前幀中不存在運動關係,因此運動向量為(0,0)。

在這裡插入圖片描述

運動向量預測

對於一個幀間編碼巨集塊,最多可以分割成16個4×4畫素大小的子塊來進行運動估計。每一個子塊都按照實際的運動向量進行編碼和傳輸需要較多的位元數。為了提升編碼的效率,H.264中定義了運動向量預測的方法。每一個子塊的運動向量MV由計算得到的預測向量MVP運動向量殘差MVD得到。其中,MVD從碼流中相應的語法元素解析得到,MVP由相鄰畫素塊的資訊計算得到。

由於相鄰的巨集塊或者子塊通常具有相似的運動關係和空間相關性,因此MVP的值由相鄰畫素塊的MV值計算得到。當前塊同相鄰塊之間的相互關係可由下圖表示:

其中,當前塊的MVP由A、B和C塊的MV取中間值計算得到。如果畫素塊C不存在,那麼以畫素塊D取而代之。如果當前巨集塊採用了SKIP模式編碼(即碼流中不傳遞相應的資料),則按照16×16模式巨集塊的方法計算MVP。

運動向量亞畫素差值

為了進一步提升運動估計的精度,提升視訊壓縮的比率,在比H.264更早的視訊壓縮標準中就引入了亞畫素精度的運動向量,在H.264中又得到了進一步的繼承和發展。在H.264中,亮度分量的MV最高可達1/4畫素精度,色度分量的MV最高可達1/8畫素精度。無論1/2、1/4或1/8畫素位置上的畫素值在影象中都是不存在的,只是作為在運動估計過程中的一個臨時值存在。

其中,1/2畫素精度的亞畫素可由下圖表示:

在這裡插入圖片描述

1/4畫素精度的亞畫素可由下圖表示:

在這裡插入圖片描述

1/8畫素精度的亞畫素可由下圖表示:

在這裡插入圖片描述

由上圖可知,亞畫素精度就是根據相鄰畫素值計算得到的,理論上存在於實際畫素之間的一箇中間值。其計算方法是有當前相鄰的幾個畫素計算加權均值的方式得到,具體的計算方法定義在標準文件的8.4.2.2.1節中。亮度資訊的插值如下圖:

在這裡插入圖片描述

在上圖中,大寫字母A~U表示的是影象中實際存在的整數畫素點,其他字母表示的是差值計算得到的亞畫素點。對於水平和垂直方向的半畫素點b和h,其計算方法為相鄰6個畫素的加權均值,計算方法為:

b = (( E − 5*F + 20*G + 20*H − 5*I + J) + 16) >> 5;
h = (( A − 5*C + 20*G + 20*M − 5*R + T) + 16) >> 5;

對於四個畫素的中間點j,其計算方法與b和h類似,只是用於計算加權均值的畫素變為了同方向上的6個半畫素點:

j = (( cc − 5*dd + 20*h1 + 20*m1 − 5*ee + ff) + 512) >> 10;或
j = (( aa − 5*bb + 20*b1 + 20*s1 − 5*gg + hh) + 512) >> 10;

上式中的cc等畫素點的計算方法類似b或h等半畫素點的計算方法中的加權求和方法,已(1, -5, 20, 20, -5, 1)為權值求和。

對於1/4畫素位置的值,其計算方法更為簡單,即去其相鄰的整畫素或半畫素的值取平均即可。

四、運動搜尋快速演算法

完全的運動搜尋過程是一種極為耗時的操作,其主要原因有:

  1. 運動搜尋過程需要覆蓋搜尋區中的每個畫素和亞畫素;
  2. 運動搜尋需要在多個參考幀中進行;

為了解決這個問題,研究人員提出了多種運動搜尋的優化演算法,旨在降低運動搜尋的總運算量。其中比較常見的有:

  • 三步搜尋法;
  • 菱形搜尋法;
  • 六邊形搜尋法;

4.1 三步搜尋法

三步搜尋法對比全搜尋只有約1/10的計算量,而演算法效能基本一致。三步搜尋法如圖所示:

在這裡插入圖片描述

三步搜尋法執行過程:

  1. 從搜尋視窗中心開始,以4為步長搜尋8個點+中心點共9個點,以SAD最小的原則選擇一個最佳匹配點;
  2. 以步驟1得到的最佳匹配點為中心點,以2為步長繼續搜尋相似的9個點,得到第二個最佳匹配點;
  3. 從第二個最佳匹配點開始,以1為步長重複上述步驟,得到最終的運動搜尋匹配點;

4.2 菱形搜尋法

菱形搜尋法使用大菱形和小菱形兩種模板,大菱形包含9個點,小菱形包含5個點,如下圖所示:

在這裡插入圖片描述

菱形搜尋法執行步驟:

  1. 從搜尋視窗中心開始,按照大菱形模板搜尋9個點,檢查菱形中心點是否是大菱形中的最佳匹配點;
  2. 如果最佳匹配點是菱形的中心點,則進一步按照小菱形模板進行搜尋;
  3. 如果最佳匹配點不是菱形中心點,則按照實際的最佳匹配點繼續按大菱形模板搜尋,直到找到某個最佳匹配點在大菱形模板的中心點,然後按小菱形模板搜尋;

4.3 六邊形搜尋法

六邊形搜尋的原理同菱形搜尋法類似,區別在於其大模板採用的模板為7個點的六邊形形狀,而小六邊形模板的形狀同菱形模板相同,如下圖所示:

在這裡插入圖片描述

六邊形搜尋執行步驟:

  1. 從搜尋視窗中心開始,按照大六邊形模板搜尋9個點,檢查菱形中心點是否是大六邊形中的最佳匹配點;
  2. 如果最佳匹配點是六邊形的中心點,則進一步按照小六邊形模板搜尋;
  3. 如果最佳匹配點不是六邊形中心點,則按照實際的最佳匹配點繼續按大六邊形模板搜尋,直到找到某個最佳匹配點在大六邊形模板的中心點,然後按小六邊形模板搜尋;