這是我大四的一個專業選修課的結課作業,寫了點關於視頻編碼的相關知識點的匯總,由於本身也不是做這個方向的,水平不夠,所有內容基本都來自於書籍、博客和課上知識。我沒有去查看和實現源代碼,也沒有去看官方的標准手冊,所以有些地方肯定說得有點問題。發這篇博客的原因是,希望能夠給一些不知道視頻編碼為何物的人參考參考,大致的思路應該還是可以看看的。內容有什么不對的地方可以在底下評論,謝謝!
前言
現在的時代是一個信息流的時代,人類接收信息的方式,已經更多的來自於手機、電腦、電視這些電子產品。你沒事的時候看個電影,在直播平台給你喜歡的主播刷個小禮物,在B站上看看視頻,都在使用着視頻編碼技術。不僅如此,現在的社會是一個數字的社會,你在你的手機、電腦、電視上看的東西,都是由一個個離散的數字值組合而成。因此,為了滿足人民日益增長的對視頻信息攝取的渴望,科學家們想出了一個又一個辦法,來使得視頻傳輸的效率越高、速度越快、顯示更清晰等等,簡而言之就是,以更小的帶寬、更高的效率、更快的速度給人以更舒服的觀看體驗。
不過對於一個不是這個專業的小白同學,就會有各種疑問了,這篇文章就是寫給這些小白們,讓他們對視頻編碼有一個直觀清晰的認識。
第一部分:視頻和圖像的關系
小白:老師老師,我想問一下,什么是視頻啊?視頻和圖像有啥關系嗎?
我:很多學生在剛接觸視頻這塊知識的時候,都會有這樣的疑問。其實我們在電影院看電影的時候,熒幕上放的東西並不是一個連續的畫面,而是一幅幅快速閃過的圖像,那我們為什么看到的是正常的連續視頻,而不是卡來卡去的翻頁PPT呢?這就不得不提一下什么是視覺暫留了!人眼在觀察景物時,光信號傳入大腦神經,需經過一段短暫的時間,光的作用結束后,視覺形象並不立即消失,這就是“視覺暫留”了,也就是說你看過的一個畫面,並不會立刻消失,而是會在你的大腦中留下一點“余輝”。所以你看到的視頻,都只是一幅一幅獨立的快速閃過的圖像組成。只要閃得足夠快,你就以為那是連續的視頻,不會有卡的效果啦!
小白:哇!這么神奇!那,那個閃得足夠快具體是多快呢?
我:你真是個喜歡提問的小白呢!人的視覺暫留大概能維持0.1s到0.4s的時間,以0.1s來算的話,也就是在視頻播放中,一秒至少要放10個圖像,才讓人不會覺得卡。當然不同人的敏感程度也不同,為了一個更好的效果,現在電影院中的電影一般都是一秒放24幀圖像,電視的話,咱國家是每秒25幀圖像,美國加拿大那邊是約每秒30幀。
小白:誒?咋我國和美國那邊還不一樣呢?
我:哈哈,你真仔細,其實很簡單,因為我們國家的用電體系是50Hz,美國那邊是60Hz,視頻每秒幀數正好是發電頻率(也叫工頻)的一半,你可以理解為是為了視頻顯示和用電的步調一致(一個正弦波周期對應一個波峰、一個波谷,也正好對應兩幀的圖像顯示時間),這樣的一致原則,更有利於信號的傳輸吧!
小白:哦…原來是這樣。
我:其實這就是最簡單,也是最需要明白的一件事,“視頻是由圖像構成的”。所以說,對視頻進行編碼(為了使得一個視頻占用的空間大小更小,卻又不會很影響觀看質量),最應該想到的一個方法就是先對每一幅靜態的圖像進行編碼,每一幀圖像都能夠做到很好的壓縮,視頻自然就能很好的壓縮了。
由此,JPEG誕生啦!
第二部分:JPEG是啥?
小白:老師老師,我明白了視頻是由一幀幀快速閃過的圖像構成的,視頻編碼首先就要考慮對圖像編碼。那么咋對圖像進行編碼呢?
我:嘿嘿嘿,我來介紹一下什么是JPEG吧!小白,你自己用電腦查看圖像的時候,細心的話是不是發現,圖像的文件名后面都有個后綴,比如什么.jeg、.jpeg、.png、.bmp等等。前兩個就是我們今天的主角。.jeg和.jpeg其實是一個東西,都是遵循jpeg標准的圖像格式,只是因為DOS、Windows 95等早期系統采用的8.3命名規則只支持最長3字符的擴展名,為了兼容采用了.jpg。
小白:嗯..也就是說jpeg標准就是一種可以將圖像進行壓縮的算法標准,對吧?
我:對對對。怎么對圖像進行壓縮呢?首先,我們有過一點信號的知識的同學都知道,我們可以從時域和頻域兩個角度去分析一個信號,而jpeg標准壓縮其實是對圖像的頻域進行壓縮的。
小白:將信號從時域轉換為頻域用傅里葉變換,這我知道,為啥圖像也能有頻域???
我:圖像當然有時域和頻域咯,你知道的那個傅里葉變換是將一個一維信號轉換到頻域的方法吧。圖像其實你可以理解為一個二維信號,而且是一個二維的數字信號,是離散的。我們可以通過DCT變換來得到一個圖像的頻域信號。DCT變換其實就是二維信號的離散傅里葉變換的實部部分。比如一張8×8的圖像信號,通過DCT變換之后,頻域也是8×8的信號。同時在頻域部分,左上角顯示的是低頻分量,右下角顯示的高頻分量。記住高低頻的位置,接下來會涉及到。
小白:誒?很奇怪啊,為什么非要把圖像轉換到頻域進行壓縮呢?
我:這個問題問得好!因為一幅圖像中占比較多的部分往往是低頻分量,也就是說,圖像中的像素點的變化往往是緩慢的,相鄰兩個像素點往往是有很大相關的。辣么!如果我們將一幅圖像變換到頻域,往往是左上角低頻部分的數值較大,而右下角的高頻數值較小(因為圖像高頻分量少)。在實際中,左上角的值可以達到幾百的數量級,而右下角的數值幾乎接近於0 。
所以當我們將圖像變換到頻域之后,我們再對頻域信號進行量化。相比於直接對時域信號量化,這種方法的好處是,在量化之后,往往高頻部分,即右下角部分的值全部為0了,僅僅保留了低頻部分的量化值。以Lena的照片舉個例子:

將Lena圖像中取出一個8×8的小塊進行DCT變換,得到的頻域值如下:

此處注意,jpeg壓縮的時候是一塊一塊進行壓縮的,不是整個圖一起壓縮。
我們可以很明顯地發現,頻域部分的左上角低頻分量的值較大,,直流分量甚至達到235.6,而右下角高頻分量的值接近於0 。
接着我們對頻域信號進行量化。我們直接將頻域圖像除以一個量化矩陣。量化矩陣中的值就是不同位置的點的量化階梯,量化矩陣是:

比方說,最左上角的直流分量是235.6,量化階梯式16,則最終的量化值就是235.6/16 = 14.725(向上取整為15)。所以最終的量化結果如下:

小白:哇!太神奇了,沒想到一幅這么復雜的圖像,在頻域進行量化之后,竟然變得這么簡單。而且我看到,量化后的矩陣右下角部分都是0了,我們怎么利用這一個特性進行壓縮呢?肯定有什么好方法吧!哈哈!
我:小白真聰明!如果在一個碼流中,總是有一大串相同的數字出現,我們完全可以只記一個數字的值和這個數字出現的次數,比如有15個連續0,我們就記(0,15)。也就是我們僅僅只用兩個數字,就可以代替這么多的0了,這個壓縮比可是相當相當的大啊!!!這種方法就叫做“游程編碼”。
而且由於圖像的頻域部分由低到高的方向是向右下角的,所以在編碼的過程中,采用的z字形走位(zigzag編碼)。

所以編碼的時候大致的順序就是:15,0,-2,-1,-1,-1,0,0,-1,0,0,0……這樣就可以使得高頻分量集中在序列的后面,使得更多的0可以集中在一起。
小白:天哪!太厲害了吧!不過老師,我發現你剛剛有一點沒說,你看你看,你之前那個量化矩陣,不同點的量化階梯是不一樣的。而且我發現整體趨勢是低頻分量量化階梯較小,高頻量化階梯較大,這……你得給我解釋解釋。

我:你你你…你確定你是小白,而不是作者內心的想象出來的托?行叭,既然你發現了,那我就說一下吧。
人的眼睛往往對低頻分量更敏感,可以想象如果低頻分量的量化階梯過高,那圖像中那種漸變的趨勢就被抹去了,圖像就像有了斑塊的感覺。高頻分量往往是描述突變的部分,比如邊緣部分,只要超過一個量化階梯后,便可以恢復出來。所以這樣處理不僅對圖像不會造成過大的失真,而且能夠使更多的連續0出現,提高壓縮比。
不僅如此,如果是彩色圖像的話,圖像如果在亮色空間(YCbCr空間),由於人眼對亮度和顏色的敏感程度不同,所以量化的時候,亮度通道和色差通道使用的量化矩陣還有不同!
小白:誒?亮色空間是啥?你好像沒說過這個概念。
我:嗯,彩色圖像可以用RGB(紅綠藍)三個通道描述,也可以用YUV或者YCbCr的亮度分量+兩個色差分量描述(Y指亮度分量)。這幾種描述方式都是可以互相轉換的。大致這么理解就行了。
小白:哦哦。我有點明白了。
我:其實呢,在jpeg編碼標准中,我們在圖像中的某一塊量化之后的結果,DC分量和AC分量是分開編碼的!還是上面的結果舉例。

DC(直流分量)就是最左上角的那個點,AC分量就是除了DC那個點剩下的所有點。為什么要分開編碼呢?因為一幅圖像中,相鄰的編碼塊的DC分量,即整體的亮度信息或者色差平均值是很接近的。所以AC分量依舊按照上述的z字形(zigzag編碼)游程編碼,而DC分量是跨塊的增量編碼,比如一幅圖像的連續小塊的DC分量分別是15,13,14,12,15,16。則我們就編碼15,-2,1,-2,3,1。通過這種增量編碼,很好地利用了相鄰塊之間的DC分量緩變的冗余信息,來提高了編碼效率!
小白:我似乎明白了jpeg的大致思想呢!將圖像變換到頻域,再量化,因為圖像的頻率分量大多集中在低頻,所以會出現很多連續0,可以通過游程編碼提高編碼效率。同時還可以利用相鄰塊的直流分量的緩變特性,用增量編碼來提高DC分量的編碼效率。
我:emmmm,不錯不錯,看來你已經掌握本質了!接下來我們就開始介紹視頻編碼部分吧!
小白:嗯!上面是先修知識,老師好棒棒啊!
第三部分:視頻編碼的前世今生
小白:之前老師說過,視頻就是由一幀幀圖像組合而成,所以我們對視頻編碼,就是要先對其中每一幀圖像編碼。那現在不就可以了嗎?還能再提高編碼效率嗎?
我:嘿嘿嘿!小白啊,當我們在考慮如何提高編碼效率時候,就應該考慮我們的編碼對象存在着哪些冗余信息!這點很重要!那我們想一個視頻有哪些冗余呢?
小白:之前那個jpeg編碼算是一種冗余嗎?
我:是的,之前我們通過對每一幀圖像壓縮編碼,就是降低視頻編碼中的空間冗余。所謂空間冗余,就是像素之間存在一定的相關性,利用這種相關性,我們便可以用更少的碼字來(近似)描述原來的信息。那有空間冗余,在我的提示下,小白你還能想出什么冗余呢?
小白:額。。。難道是時間冗余?
我:哈哈,是的呢!那什么是時間冗余呢?
小白:是不是在時間維度上,前后幀的相關性產生的冗余呢?
我:是的!小白,一看你就不是小白,一定是作者精神分裂的產物!
小白:是不是你心里不知道嗎?
我:好吧,言歸正傳。我們之前說視頻是由一幀幀快速閃過的圖像組成的,在這么快的閃動速度下,前一幀和后一幀圖像很多地方都是相似的,甚至沒有變化。這個冗余的量是非常非常可觀的。如果我們僅僅把視頻當作一幀幀獨立互不相關的圖像來進行壓縮,那是遠遠不夠的!
小白:嗯,有道理!
我:其實視頻編碼技術,真正的核心技術點已經講完了!就是如何解決視頻幀與幀之間的冗余問題。其實除了空間冗余、時間冗余,還有視覺冗余、圖像構造冗余、知識冗余等等。
視覺冗余其實我們已經提到過了,比如人眼對亮度色差的敏感度差異,人眼對低頻高頻分量之間的敏感度差異,都算是視覺冗余。
圖像構造冗余的話,比方說一個具有很強的規則紋理性的圖像,我們完全利用紋理中的相關性進行編碼。知識冗余更有意思,假設我們的編解碼系統具有了人的智慧,當發現圖像有一個人臉,那么其實根據常識,我們知道人的有兩只眼、一個鼻子、一張嘴,還能知道它們的大致相對位置,知道的信息越多,冗余就降低的越多,編碼效率就越高!
小白:哇!視頻編碼聽起來好好玩啊!接着說!!!
我:現在在視頻編碼領域,有兩大組織,一個是ITU-T(國際電信聯盟遠程通信標准化組),另一個是ISO/IEC(國際標准化組織/國際電工委員會),好吧,翻譯過來的名字有點長。這兩個標准化組織在視頻編碼的歷史中,互相促進,互相學習。前者制定的標准是H.26x系列,后者制定的標准是MPEG系列。

上面就是兩個標准化組織制定的主要標准,中間的是兩個組織合作的成果。
小白:原來還有這么兩個組織在干這些事啊!看圖最先出來的是H.261標准。
我:嗯,我們接下來就介紹H.261標准。其實當我們介紹完H.261標准之后,視頻編碼體系基本就已經介紹完了。因為之后的編碼體系基本都是建立在H.261體系基礎上,只是做一些算法等方面的改進。整個編碼的宏觀結構並沒有改變。現在廣泛用的是H.265編碼,H.266還在制定之中。接下來我們講什么是H.261編碼。
第四部分:聊一聊H.261編碼
小白:我已經知道了第一個視頻編碼標准是H.261。
我:嗯,接下來我來介紹H.261的編碼規范。
H.261編碼主要是為了解決幀與幀之間的時間冗余。由此它引入了一個前向預測的概念,即可以通過上一幀來預測當前幀的畫面內容,並將當前幀的實際圖像和預測圖像的殘差作為編碼傳輸對象。
我們先定義一個I幀和一個P幀。I幀代表此幀不參考任何幀,當系統要傳輸I幀的時候,直接對圖像進行壓縮編碼,不參考其它幀圖像。P幀代表此幀要參考前面的一幀,所以當系統傳輸的是P幀的時候,僅僅只需要傳輸一個殘差,以及預測的相關參數即可。解碼端通過上一幀圖像和殘差以及相關參數,就可以恢復這一幀的原始圖像了。
小白:老師,這里的相關參數是什么,不是只要一個殘差和上一幀圖像不就可以恢復出來了嗎?兩個相加不就可以了。
我:首先要明確一點,圖像的編碼都是基於宏塊的,就像之前的靜態的JPEG編碼,也是將圖像分成一個一個小塊(宏塊),然后以宏塊為基本單位進行編碼的。
如果我們在預測的過程中,僅僅是將上一幀和這一幀的每一個宏塊的差值編碼傳輸,確實不需要額外的參數,就可以完全恢復了。但是當在視頻中,物體、人等對象往往都是在運動的,那么我們就可以去尋找當前幀的這一個欲編碼的宏塊與上一幀最相近的宏塊的相對位置找到,然后再將這兩個宏塊的殘差編碼傳輸。尋找最近似匹配塊的過程叫運動估計,將前后兩個最近似的塊作差的過程叫運動補償。運動估計的過程如下圖:

對當前幀的所有宏塊進行運動估計則形成的一組運動矢量(場),如下:

所以在傳輸的過程中,不僅要傳輸殘差信息,也要傳輸運動矢量,這樣才能恢復原始圖像。
小白:嗯,有點明白了,I幀直接傳輸原始圖像信息,P幀要參考上一幀,進行運動估計和運動補償,然后將預測的圖像和當前的原始圖像作殘差,並和運動估計的矢量一起進行編碼傳輸。
我:對,大致結構就是這一過程,但是這里面仍然有一些細節問題。
這樣吧,我給你看一張H.261的整體框架圖。

上圖就是H.261的結構圖,我們來一步一步梳理這里面的知識。流程如下:
- 圖像輸入。
- 幀內和幀間的選擇器。這里的幀內就是要傳輸I幀的意思,幀間就是P幀的意思。而視頻編碼中,這一開關的控制權在編碼者手中,標准中並沒有做出嚴格規定。編碼者可以通過“編碼控制”模塊,進行I、P幀的交換,可以控制I、P幀之間的比例大小。
- 當傳輸的I幀的時候,圖像先經過DCT編碼,轉換到頻域,再經過量化,編碼,即可傳輸。由此可見,當視頻編碼中,如果傳輸的是I幀,其實僅僅相當於做了一個圖像編碼(JPEG)。
- 由於I幀之后是P幀,P幀的傳輸需要前面一幀(I幀或P幀)的參考,所以在第3步量化之后,又經過了反量化,反DCT變換,存儲起來。當下一幀到來的時候,將這兩幀圖像進行進行運動估計和運動補償。將運動估計的結構一起送入右邊的編碼傳輸模塊。
- 在運動補償之后,已經輸出了當前幀的預測圖像了。按照我們之前的分析,由於兩幀間隔很短,這個預測圖像和真實圖像其實相差不多,通過一次環路濾波之后,和真實圖像作差,然后編碼傳輸。
大致就是這么一個框架,而這個框架將被一直延續了下來,之后的編碼標准都是在這個的基礎上進行小幅度修改和改進。
小白:這里有兩個地方沒搞明白。一個是環路濾波是做什么的,還有一個是在反DCT變換為什么會有一個相加器。
我:你觀察的還是很仔細的,先解釋環路濾波的問題。
我們知道,在視頻編碼中,我們是以一個一個宏塊為基本單位編碼的,那我們這種預測方式(估計、補償)的預測結果往往容易出現一塊一塊的斑塊,就好像圖像都是一塊一塊的,塊塊之間有明顯的間隙(分塊效應)。這個和原始圖像肯定還是有一些差距的。而環路濾波可以對這個預測圖像的邊緣進行低通濾波,使得塊與塊之間的邊界不那么明顯。所以更接近原始圖像,殘差也就越小,編碼的效率也會越高。
至於第二問題,並不難理解。這是因為,我們並不只是I、P、I、P、I這樣交換編碼,我們可以在兩個I幀之間,插入多個P幀,那在這種情況下,當上一幀是P幀,這一幀依舊是P幀時,從反DCT變換那里的輸出結果就不是上一幀的完整圖像了,而是殘差!所以為了恢復完整圖像,必須先和上一幀的預測圖像進行一次加和。
H.261標准是一個很寬泛的標准,給予了編碼者很多自我調整的空間。它的思想也一直影響了后面的編碼標准的制定。
小白:嗯,明白了!
第五部分:從H.261到H.264的進化之旅
我:H.261已經講完了,你還記得之前那個視頻編碼的年代圖嗎?
小白:記得記得,老師你看我這就給您復制過來!

我:謝謝謝謝!H.261之后,便是另一家標准組織的MPEG-1標准。由於都是基於H.261編碼標准,所以,我們這里只介紹它的不同之處。
相比於H.261,MPEG-1真的沒有做多少改進,但是它在預測方法上,引出了前后預測的方法,這是一個最大的改進。下面我們主要介紹這格前后預測是怎么回事。
我們知道H.261中有I幀、P幀,I幀是傳輸整個圖像,P幀是參考的前一幀,只傳輸殘差和相關參數。在MPEG-1中引入了B幀,這一幀不僅會參考前面的幀,也會參考后面幀,以此來共同預測當前幀。顯然這樣的預測方法可以使得預測結果更加接近原始圖像。比如在前一幀中一個特征宏塊在A處,在后一幀中那個特征宏塊在B處,那么我們有理由去預測,在當前幀中,宏塊很可能是在A、B的中點處。

這是編碼過程中的的幀流,GOP是一組周期循環的幀組。如果我們將B幀全部去掉,那么其實和H.261是完全一樣的。而我們在I、P幀間和P、P幀間插入的B幀,則是參考了前面I(P)幀以及后面的P(I)幀,注意B幀彼此不互相參考。那么這種算法結構就引發一個問題,視頻采集的順序肯定是IBBPBBPBBPBBI,而編碼的時候,為了得出B幀要傳輸的殘差,必須知道后面的P幀或I幀,以此來做參考。所以在這種要求下,視頻采集端必須有一個緩沖,並且要將順序重排,以適應編碼順序。

如上圖,這便是加入了B幀之后的編碼框圖(其實這個圖里面加入了一些MPEG-2的算法,我們現在不提,之后再提),和之前的H.261框圖相比,整體結構沒有多大改變,只是在視頻輸入端加入了幀重排模塊。在反DCT變換之后,加入兩個存儲器,以實現雙向預測。
小白:哦,原來MPEG-1相對於H.261最大的改進就是引入了雙向預測幀。
我:是的,不過當然它還做了一些其它的改進,比如它還將每一幀的中的各個編碼宏塊的直流分量單獨編碼傳輸了,這個可以用於在快進的時候,快速播放。類似的小改進還有一些,不過整體結構一直沒變。
小白:看來H.261才是視頻編碼的基石啊!
我:之后又出現了H.262/MPEG-2標准,這個標准其實只是MPEG-1的擴展版本,在全面繼承MPEG-1的壓縮算法基礎上,增添了一些新的語法結構和算法。那么值得介紹說明的有:第一,MPEG-2不僅支持逐行掃描、也支持隔行掃描,以前的CRT顯示器,為了防止掃描過程中,產生的閃爍現象,采用的是隔行掃描技術,同理在MPEG-2也添加了這一功能。第二,MPEG-2在運動估計的時候支持半像素的估計,也就是在估計的時候,可以先對估計的區域進行1:1插值(因為是半像素),然后估計的運動矢量就相比於整像素估計更精細了。第三,MPEG-2可以支持各種清晰度可變的編碼方式,比如可以控制信噪比的變化、空間分辨率的變化、時間分辨率的變化。

這個還是剛才的圖,我們說過,這里有MPEG-2才出現的算法結構。就是右上角的自適應量化器。我們可以通過這里去調節量化矩陣的參數,可以選擇更小的量化階梯來達到更高的信噪比。同時為了改變空間分辨率,我們可以在原有的最高分辨率情況下,可以空間降采樣得到較低分辨率的視頻,為了改變時間分辨率,則可以抽幀。這樣做都是為了在傳輸帶寬受限的情況下,能夠以較低分辨率來正常的播放視頻。
小白:嗯,看來H.262/MPEG-2也只是MPEG-1基礎上做了一些小改進,尤其是分辨率可調的技術,很符合我們現在看視頻的習慣了!
我:嗯是,之后MPEG-4又出來了,你去查MPEG-4的標准時,發現它是有很多部分組成,MPEG-4的第二部分是MPEG-4 Visual,我認為這是很大膽很前衛很有價值的改進,但是標准推出之后,由於實現難度過高,並沒有落地。之后兩家組織共同制定了H.264編碼標准,這個標准也收錄在MPEG-4的第十部分。
小白:MPEG-4 Visual這么厲害的嗎?它是個啥東西?竟然都無法落地。
我:哈哈,其實這個標准很好理解,還記得我們之前說編碼的時候都是以一個個宏塊為基本單位編碼的嗎?這種只是做了機械的固定的圖像分割。而在MPEG-4 Visual中,它是以視頻中的對象進項編碼的。比如視頻中有一個人在操場上打籃球,則會視頻就有三個主要的對象,分別是“人”、“籃球”、“背景操場”。那么我們在做運動估計和補償的時候就可以以對象為單位。小白!還記得我之前跟你說過視頻中有哪些冗余嗎?這種可以減小哪種冗余呢?
小白:哦!!!我明白了,知識冗余、圖像構造冗余好像都可以減小了。
我:是啊!當我們一直能檢測出人和籃球的位置,那我們基本就可以以非常小的殘差編碼傳輸了。然而,我說到了檢測,真正的難度就在檢測,人工智能還遠遠沒有發展到可以在視頻編碼中實時進行檢測識別物體對象,這也是為什么mpeg-4 visual不好落地原因。
小白:這個標准竟然是2000年之前提出的,那些做編碼的科學家真的好厲害啊!
我:嗯,科學研究永遠要走在時代前面,才能為工業界指引前進的方向。
之后兩家標准組織開始制定H.264/mpeg-4(part10)。這是一個得到了非常廣泛應用的編碼標准。然而正如我之前所說的,我們的編碼整體的框架一直沒有變化。H.264編碼繼承了先前開發的視頻編碼標准的許多優點,並在各個主要功能模塊都做了一些“精雕細琢”的改進,采用了H.264標准,視頻的壓縮比是MPEG-2壓縮比的2到3倍,有效降低了在有線網絡、衛星網絡和電信網絡上傳送高畫質視頻的成本。
雖然整體結構沒有做大的改動,但是其中有幾處也是很有必要值得說道說道的!
首先,我們之前說MPEG-2的時候,它先引入了半像素估計,使得運動矢量的更加精細了,到了H.264已經可以支持1/4像素了,也就是原始像素與像素之間,插值更多,運動矢量也更精細了,估計的位置也更精確了。
其次,預測編碼的時候,塊的大小不再固定為16*16了,現在可以可以支持8*8和4*4這種更精細的預測了。
當然還有一個最重要的改進,我們之前的預測僅僅局限在幀與幀之間的預測,這是時間冗余。但是在同一幀里,往往有很多空間冗余,即相鄰宏塊描述的圖像也很接近。之前我們解決這種冗余是在JPEG編碼的時候,將不同塊的DC分量以增量編碼形式編碼傳輸。然而這還不夠,我們為什么不引入幀內的預測模式呢?

如上圖,中間的灰色就是一個4*4的預測塊,而這種預測是根據其左邊和上邊像素進行預測的,而預測模式之多可以達到9種(8*8和16*16有4種預測方式),不同的預測方式對應不同的預測函數,H.264在幀內預測時候,並不是固定預測模式的,而是在搜索一個最佳(最近似)的預測模式,使得編碼效率可以達到最高。
不僅有如上的改進,值得一提的是H.264為了提高DCT運算速度,提出了整數DCT變換,相對於小數變化,速度真是提升了很多。而且在傳輸之前的熵編碼階段,H.264使用了上下文自適應的可變長度編碼和算術編碼,在熵編碼這一塊更接近香農極限,並且很好提高了熵編碼的實時性(傳統的哈夫曼編碼不是實時的哦!)。正是有了這些改進,H.264在推出后得到了很長時間的非常廣泛的應用。
第六部分:H.265——現在的潮流
我:終於講到了H.265編碼標准了,H.265又稱為HEVC,是H.264標准的繼任者。2004年由兩家標准組織開始制定。第一版的H.265視頻壓縮標准在2013年被正式推出。
小白:H.265應該也是建立之前的編碼標准基礎上的吧。
我:是的,科學的前進並不是為了打破標准而打破標准,更靠譜的方式應該是在過往的優秀經驗上,一點一點改進發展。
我們知道,近些年的數字視頻中,正朝着更高清(4k,8k)、更逼真(立體成像、VR)發展。在這種數據量越來越大的趨勢推動下,H.264標准已經很難再支撐視頻行業的高速發展了,如果繼續采用以往的視頻編碼標准技術,就會出現以下一些局限性:
- 更高清的視頻導致像素點的增加,每幀圖像的宏塊個數急劇增加導致編碼宏塊的預測模式、運動矢量等參數占用的碼字過多。
- 同樣由於視頻的高清化,單個宏塊描述的圖像內容信息則很少,則在幀內預測的時候,相鄰宏塊之間的相似度增加,冗余度增加。
- 以往的編碼結構比較適合串行運算,制約了用並行計算的方式來提高編碼速度的實現。
正是有了這些局限性,H.265被推出了。
小白:也就是說H.265的出現是為了解決視頻越來越高清所帶來的冗余度增加的問題。
我:是的。H.265在很多細節上都做了改進,相比於H.264的編碼標准,H.265的提高效果如下表:
|
|
480P |
720P |
1080P |
4K |
| 平均碼率降低 |
52% |
56% |
62% |
64% |
小白:H.265標准也叫HEVC,全稱為高效視頻編碼(High Efficiency Video Coding),就是為了高清視頻降低碼率而制定的。
我:是的。相比於H.264,H.265在高清視頻壓縮上做了一些比較好的改進。
首先H.265的編碼結構發生了很大的變化,它采用的是四叉樹的划分。什么是四叉樹划分呢?首先H.265的圖像最大的划分塊是64*64像素的,然后繼續分層,如下圖:

對應於四叉樹的話就是這樣:

其中節點為0,代表這一子塊沒有繼續分割,是葉子節點,節點是1,代表這一子塊被繼續分割了。我想說的是在H.264中,就有宏塊繼續分割子塊的概念,目的都是為了在表達或者描述圖像中更精細的部分時,能夠采用更小的編碼預測結構塊,但是H.265這種以四叉樹為基礎的划分,更具有數據結構的整齊划一,在算法上便於回溯和查詢,為更復雜的算法實現打下基礎。
小白:嗯,這種樹形結構的划分,很適合塊的回溯和定位。
我:是的,也正因為基於這種划分結構,H.265在H.264的整體框架下,幾乎將每一部分的算法都做了改進,使得編碼的效率更高。
除此之外,在幀內預測時,H.265相比於H.264有着更多的預測模式,小白還記得H.264的幀內預測模式嗎?
小白:記得啊,4*4的預測塊有9種預測模式,在預測的時候,遍歷所有的模式,選取最終和原始圖像最接近的模式。
我:H.265為了提高預測精度,把預測模式的數量直接提高到了35種。


左圖:H.264的預測模式 右圖:H.265的預測模式
這種精細的預測模式,雖然帶來更精確的效果,但是由於要遍歷所有模式,並對每種模式進行評估比較,所以必然會帶來繁重的計算負擔。然而近幾年的硬件發展速度很快,並且H.265也做了非常多的適應並行計算的優化,使這一切都變成了可能。
當然在幀內預測中,H.265還有一些改進,比如在預測之前,會對圖像進行平滑濾波,減少噪聲對預測的影響。
小白:說完幀內預測,接下來就是幀間預測的改進吧。
我:對,之前說過,雖然H.265整體結構沒有大幅度改進,但是在每個部分的細節上的處理可謂很精妙!
在幀間預測的時候,我們的目的是要找到更合適MV(運動矢量),然后我們也會把MV作為參數進行編碼傳輸到解碼端,但是由於在高清視頻中,傳輸MV的碼字也很多,必須要對MV進行的傳輸進行優化。小白,我們都已學了這么編碼優化的知識,你能想象如何對要傳輸的MV的信息進行壓縮編碼嗎?
小白:哈哈,我明白你的意思了,對MV也進行預測,然后傳輸殘差!
我:可以的!你已經掌握了編碼的精髓了!哈哈哈哈!然而我想說的是,這種方法在H.264標准中已經采用了,利用的就是空間(或時間)相鄰塊之間的運動矢量的相關性,來進行殘差編碼。在高清視頻中,這種編碼技術顯得尤為重要。
小白:那H.265也是采用H.264這種結構嗎?
我:是的,但是H.265不僅保留這種編碼技術,還采用一種基於索引編碼傳輸的方式——merge模式。
merge模式會為當前子塊建立一個MV候選列表,遍歷這些候選MV,選取最近似的作為最優MV。若編解碼器依照相同的方式建立候選列表,則編碼器只需要傳輸最優MV在候選列表中的索引即可。這種候選列表的MV可以在空域與當前子塊上相鄰,也可以在時域與當前子塊上相鄰。
小白:merge模式直接傳輸了最優的MV的對應塊的索引,這種索引也是基於四叉樹結構,索引的傳輸相比於殘差的傳輸又提高了編碼效率。
我:這是幀間預測,H.265的改進還有在熵編碼上做了優化,以及采用了很多的並行技術,使得它的復雜算法得以落地實現!
第七部分:憧憬和探索H.266
我:小白,講到這里,你應該對整個視頻編碼的發展和實現思路有了一些自己的認識了吧。
小白:嗯,還行吧,我覺得視頻編碼的發展基本是基於第一代的編碼標准(H.261),然后不斷去改進,不斷地適應時代的需求。
我:在這種改進的過程中,融入了很多科學家和工程師的精妙的想法,這個過程是艱辛的,因為改進一處,其實就會牽動很多方面,但是這個過程相信也是有趣的,與時代共進步,服務於整個多媒體行業是一件很有成就感的事。
小白:那說完前面的編碼標准,是不是該憧憬一下未來的標准呢?我們之后的發展方向是什么樣的呢?
我:下一代的編碼標准H.266也是由兩家標准組織共同制定的,H.266的探索是從2016年初開始提上日程,其目標是實現比現有標准提高50%以上的壓縮率(目前已經達到40%以上),在開發日程上,第一個H.266標准版本將在2019年10月推出,最終標准將定於2020年底推出。新的標准將非常適合4K、8K、16K以及更高清的視頻傳輸,以及在編解碼中將會結合機器學習等AI算法,可以說是一種Future Video Codec。
小白:那H.266將會在哪些方面做出改進呢?
我:由於H.266標准還處在探索階段,標准的制定方案並不是確定的,也不一定能保留到最后階段,只能通過幾次會議來大致做一個了解。
首先H.266的制定是針對4K及以上的高清視頻,這導致目前編碼器的最大塊尺寸變為128*128(H.265是64*64)。其次在編碼結構上,H.266中是四叉樹、三叉樹、二叉樹混合划分的,比如一個大塊可以先分成四塊,然后子塊可以再分成三塊或兩塊,這就使得在編碼過程中,更加可以精細地考慮圖像的紋理特征,預測效果更好。幾種划分方式如下:

除此之外,H.266在環路濾波技術上,可能會采用自適應環路濾波。在幀內預測中,H.266的預測模式數量可能會達到70種以上。

這么多種的幀內預測模式,遍歷一遍會很耗計算力,H.266並不會全部遍歷,而是會根據預測塊的寬高比來選擇使用哪些種角度預測模式作為候選預測模式(因為存在三叉樹結構,寬高比肯定不會只有1:1)。
在幀間預測的時候,H.266可能會考慮仿射運動的預測,我覺得這一點是非常好玩的。在H.265中,只有平動模型被用於運動補償預測,然而在真實世界中,有各種各樣的運動,比如放大、縮小,旋轉等非規則運動。基於這種的預測方式,將會給運動估計的效果帶來更精確的效果,編碼效率也將會有所提高。
總的來說,H.266將會在很多部分引入更優秀的算法,2018年4月10日美國聖地亞哥會議上,為新一代視頻編碼標准定名為Versatile Video Coding,主要目標是改進現有HEVC(H.265),提供更高的壓縮性能,同時會針對新興應用(360°全景視頻和HDR)進行優化。2020年之后,5G通信開始商用化,人工智能不斷發展,硬件的算力將會更高,新的視頻編碼標准將服務於人類更加Versatile(多功能的),多元化的視頻需求!
小白:哇!生活在這個日新月異的時代真好!謝謝老師!
我:不用謝。
