H.264和VP8視頻編碼技術對比

VP8和H.264均採用混合編碼框架,空間域採用幀內預測技術,時間域採用幀間預測技術,除此之外,在整個視頻編解碼的主要技術點上,包括變換、量化、熵編碼、環路濾波等,兩者都是使用相同的環節,只是具體技術細節實現略有不同。

幀內(Intra Frame)預測

(1)區別一:H.264 Plane VS VP8 TM_PRED

對於Intra_16x16和Intra_4x4,H.264和VP8的區別在於Plane模式和TM_PRED,VP8的TM_PRED計算方法比較簡單,為:

Xij = Li + Aj - P

(2)區別二:H.264 I_PCM VS VP8 mb_skip_coeff

mb_skip_coeff:does this mb has coefficients at all, 1=no coefficients, 0=needdecode tokens.

關鍵幀和非關鍵幀均有該模式,兩個參數mb_no_skip_coeff和prob_skip_false配合使用。

幀間(Inter Frame)預測

H.264 Skip模式(B_Skip or P_Skip):do not sendany information for this macroblock.

---------------------------------------------------------------------------------------------------------------------------

注1在Frame Header中,version用3個bit,0-3表示4種不同的解碼複雜度級別,代碼詳情見alloccommon.c,0:使用6抽頭濾波器,1,2,3都使用雙線性,

void vp8_setup_version(VP8_COMMON *cm){ switch (cm->version) { case 0: cm->no_lpf = 0; cm->filter_type = NORMAL_LOOPFILTER; cm->use_bilinear_mc_filter = 0; cm->full_pixel = 0; break; case 1: cm->no_lpf = 0; cm->filter_type = SIMPLE_LOOPFILTER; cm->use_bilinear_mc_filter = 1; cm->full_pixel = 0; break; case 2: cm->no_lpf = 1; cm->filter_type = NORMAL_LOOPFILTER; cm->use_bilinear_mc_filter = 1; cm->full_pixel = 0; break; case 3: cm->no_lpf = 1; cm->filter_type = SIMPLE_LOOPFILTER; cm->use_bilinear_mc_filter = 1; cm->full_pixel = 1; break; default: /*4,5,6,7 are reserved for future use*/ cm->no_lpf = 0; cm->filter_type = NORMAL_LOOPFILTER; cm->use_bilinear_mc_filter = 0; cm->full_pixel = 0; break; }}

VP8運動搜索方式:

typedef enum{ DIAMOND = 0, //鑽石搜索 NSTEP = 1, //N步搜索,比如三步搜索,四步搜索等 HEX = 2 //六邊形搜索} SEARCH_METHODS;

---------------------------------------------------------------------------------------------------------------------------

環路濾波

環內濾波器是在解碼或者編碼完一幀後使用的,對某一幀做一些附加處理,一般在基於DCT的視頻格式中是用作除去塊效應。不同於後處理,除塊濾波不僅僅是因為視覺上的原因,它還能改善後續幀的預測精確性。因此,除塊濾波的操作在解碼端和編碼端必須完全一致。

簡單的說,VP8的環內濾波和H.264類似,但是有幾點不同。

首先,有兩種模式(能在編碼器中選擇):快速模式和普通模式。快速模式比H.264要簡單,但是普通模式比H.264要複雜。

其次,當在宏塊之間濾波時,VP8的濾波器會選擇比宏塊內濾波更長的濾波模式。H.264也這麼做了,但H.264隻對幀內預測幀的邊緣採用這種方式。

第三,VP8的濾波器忽略了H.264濾波器內大部分關於自適應強度的機制。它唯一的自適應來自於它對沒有DCT係數的p16×16塊不濾波。這可能就是VP8環內濾波器會產生大量模糊的罪魁禍首:它將一遍又一遍的對宏塊的所有部分進行濾波哪怕這個宏塊在幀間沒有任何變化(只要該宏塊的其它某些部分改變了)。H.264的實現,與之相比,則根據DCT係數是否在給定要處理邊緣的兩側存在、運動矢量的差值和此邊緣兩側參考幀的差值來自適應地調整濾波強度。當然,跳過這些強度判斷和計算節省了解碼時間。

對環內除塊濾波的評價:從壓縮率的角度,因為缺少自適應強度機制而顯然的比H.264差,特別是使用「快速」模式時,雖然可能會大幅提高編解碼速度。我擔心的是這種濾波的結果是過度的模糊了畫面。

變換

對於變換來說,VP8再一次的使用了一個類H.264方案,包含DCT和WHT(Walsh-Hadamard Transform)兩種變換。每個16×16的宏塊被分成16個4×4的DCT塊,每一個使用一個精確位數的DCT近似進行變換。之後,每個變換塊的DC分量被提出成另一個4×4的組,之後對這個4×4的組進行Hadamard變換。OK,到此這不是一個類H.264方案,這就是H.264。但是,VP8的變換方案和H.264有三點不同。

首先8×8變換被完全去除了(這和i8×8模式被去除相對應)。

其二是變換本身,H.264使用了一個極其精簡的DCT,它是如此的不像DCT以至於經常被人用HCT(H.264 Cosine Transform)代指。這個精簡的變換大概能導致1%的壓縮率損失,但是大幅精簡了變換的運算,它可以完全用加、減和右移一位這三個操作來實現。VP8使用了一個特別地,不必要地精確版本,使用了非常大的乘法(20091和35468)。

第三個不同之處在於Hadamard層級變換還作用於一些幀間預測塊中,而不僅僅是i16×16這一種幀內預測模式。具體來說,它也作用與p16×16塊中。這是一個非常好的想法,特別是考慮到較小的變換大小(以及對於小範圍變換時解相關DC值的需求)。我並不是非常確定我同意將層級變換隻限定在p16×16塊內,看上去似乎只要經過很少的修改,這樣的變換也會對其他運動分塊有用。另外,與H.264不同的是,層級變換隻作用於亮度塊而不作用於色度塊。

總體上,VP8的變換方案絕對比H.264弱。缺乏8×8的變換,特別在高解析度場合,會嚴重影響對細節的保持。變換本身也非常沒有必要的慢,雖然基於位移的變換方案可能會逃過專利問題。其中一個優秀的想法是將層級DC變換應用到幀間預測塊中。

對變換的評價:接近於H.264,更慢,略微準確的4×4變換,對亮度DC變換的改進(但是沒有對色度的支持)。沒有8×8變換。總之,劣於H.264。

量化

對於量化而言,核心的處理方式對於所有類MPEG視頻格式都是一樣的,VP8也不例外。量化上各種不同標準區分自己的方法就是改變數化階係數。這裡面主要的方法又有兩種:基於幀的偏移,其作用於所有或者一部分係數;以及基於宏塊的偏移。VP8主要使用的是前者,其方案相比於H.264的自定義量化矩陣而言可伸縮性差了很多。VP8的方案允許分別調整亮度DC分量,亮度AC分量,色度DC分量等諸如此類的對應量化器。後者(基於宏塊的量化器選擇)從理論上可以利用「分割圖」的功能實現,儘管這種實現方式需要相當的技巧並且不是非常高效。

VP8在這裡犯得一個致命錯誤在於沒有把基於宏塊級別的量化作為VP8的核心特性支持。利用基於宏塊級別量化的演算法一般被稱為「自適應量化」,這種量化對視頻主觀質量的影響是絕對非常關鍵的。我在x264里的基於方差的自適應量化演算法實現,補丁。編碼器的評價一次又一次的證明,沒有自適應量化的編碼器完全沒法與具備的編碼器相提並論。

因此,想讓自適應量化在VP8上成為可能,對每個有可能被用到自適應的量化器定義一個分割圖並對每個宏塊的分割圖索引進行編碼就成了華山一條路。顯然這是很沒效率且很笨拙的實現方法,哪怕不是最優的MPEG風格delta量化器系統都是一個更好的選擇。此外,對於每幀最多4個量化器而言,VP8最多只支持4張分割圖。

對量化的評價:當需要進行視覺心理優化(psy-optimization)時,缺乏可簡化開發整合良好的自適應量化的VP8會讓人頭疼不已。總之,比H.264差遠了。

熵編碼

熵編碼是將其它過程產生的信息,如DCT係數、預測模式、運動矢量等等,整合在一起並無損壓縮成最終輸出文件的過程。

H.264和VP8均使用了兩種熵編碼方法:vlc(Variable Length Coding)和bac(Binary Arithmetic Coding)。

VP8使用的算術編碼器在一定程度上與H.264相近,但有幾點關鍵區別。首先,它以一個乘法運算取代了範圍/概率表。再者,它完全是非自適應的,與H.264中對解碼的每位都去調整概率值不同,VP8的概率值在一幀內事恆定的。與之相對的,編碼器會定期地在幀頭部的部分語法結構中發送更新後的概率值。編/解碼到關鍵幀重置概率值。

參考

[1]github.com/webmproject/

[2]github.com/cisco/openh2

[3]VP8_百度百科


推薦閱讀:

TAG:視頻編碼格式 | 多媒體技術 | 視頻直播 |