近幾年,視頻編解碼技術在理論及應用方面都取得了重大的進展,越來越多的人想要了解編解碼技術。因此,網易雲信研發工程師為大家進行了歸納梳理,從理論及實踐兩個方面簡單介紹視頻編解碼技術。
相關閱讀推薦
1、視頻介紹
視頻的本質是圖像序列,根據視覺暫留的原理,每秒播放20~25張圖像,就會形成連續平滑的視覺效果,人眼將無法區分其中單幅的圖像,就這樣連續的畫面叫做視頻。每秒播放的圖像數量叫作幀率。圖像是由像素構成的,在彩色圖像中,每個像素由R、G、B三個分量構成,每個分量用一個字節存儲。分辨率用於描述圖像的尺寸,例如分辨率1280x720就表示圖像寬度是1280個像素、高度是720個像素。
2、壓縮視頻的原因
為什么要對視頻進行壓縮?假如有一段時長為60秒視頻,它的分辨率是1280x720,幀率是25,那么這段視頻的大小等於:60 x 25 x 1280 x 720 x 3 = 4147200000字節,大約是3955MB,如此龐大的數據,如果不進行壓縮,那么磁盤空間將會很快被占滿。
多媒體數據占了互聯網數據量的80%以上,其中大部分都是圖像視頻數據,未壓縮之前的視頻非常龐大,不利於存儲和傳輸,因此很有必要對視頻進行壓縮,視頻壓縮也叫作視頻編碼,它利用視頻中存在的空間冗余和時間冗余,剔除人眼不敏感的信息,達到數據壓縮的目的。
3、視頻壓縮的依據
視頻能夠進行壓縮的根本原因是信息冗余,視頻中存在兩種冗余信息:
(1) 空間冗余。對於視頻的每一幀圖像,在一定尺度范圍內,像素的變化是非常平緩的,像素之間非常相似,這就是空間冗余。
(2) 時間冗余。視頻是由連續變化的圖像構成的,在一個很短的時間內,相鄰圖像之間的變化很小,因此相鄰圖像很相似,這就是時間冗余。
4、視頻編碼的原理和細節
由於視頻中存在大量的信息冗余,想要對視頻進行壓縮,就必須找到去除冗余信息的方法,標准的視頻編碼過程包含下面幾個步驟:
(1) 預測編碼。所謂預測就是利用前面像素值來推算當前的像素值。根據前面的知識我們知道,在空間或者時間上相鄰的像素是很相似,因此只要預測方法合適,預測值和實際值會很接近,假設當前像素的實際值是X,預測值是P,那么X和P之間的殘差A=X-P。如果我們只對殘差數據進行編碼,那么將會大大壓縮數據量。這就是預測編碼的原理。預測編碼可以分為空間預測(幀內預測)和時間預測(幀間預測)兩種。預測編碼可以分為下面幾個步驟:
- 利用前面已經編碼並重構像素塊預測當前像素塊的值
- 求當前像素和預測像素的差值
- 對像素差值進行編碼
- 把編碼后的數據傳輸到解碼端,在解碼端按照同樣的方法對像素值進行預測,再加上殘差,就可以重構得到原始圖像了。
為了得到最佳的預測值,編碼器通常需要使用不同預測方法進行預測,然后根據某個評判標准(一般是SAD、STAD、RDO等)得到最優的預測值(注意不是預測值越接近實際值就越優,所謂最優是計算復雜度、失真和碼率之間的綜合考量),特別對於幀間預測來說,在預測的時候要在參考幀中找到當前塊的匹配塊,需要大量的計算,因此預測模塊一般是編碼器中計算量最大的模塊,而預測方法的好壞也直接決定了視頻的壓縮率。
(2) 變換編碼。變化編碼本身不會對數據進行壓縮,變換的目的是把空域信息轉換為頻域信息,去除了信息之間的相關性,在接下來的編碼操作中可以得到更高的壓縮比,變化編碼是為下一步的量化編碼做准備的。在視頻編碼中常見的變換方法是DCT變換和哈達瑪變換。
(3) 量化編碼。量化是視頻產生失真的根本原因。經過預測編碼、變換編碼之后得到的數據被稱為變換系數,雖然變換系數相對於原始數據數來說已經很小了,但是系數值的變化范圍仍然很大,利用量化把變換系數的連續取值轉換成有限的離散值,這樣可大大提高壓縮率。假設有這樣一組數據[16,96,100,600,50],量化參數是25,那么量化之后數據是round([16 / 25, 96 / 25, 100 / 24, 600 / 25, 50 / 25]) = [0,4,4,24,2],可以看到,量化之前的數據范圍是16~600,需要大量的比特數才能表示,量化之后的數據范圍是0~24,只需要少量比特數就可以表示,實現了壓縮數據的目的。編碼是一個不可逆的操作,它是失真產生的根本原因。
(4) 環路濾波。環路濾波和壓縮沒有很大關系,卻和視頻的畫面質量有很大關系。視頻編碼是以塊為單位進行的,在經過量化模塊時,可能每個塊選擇的量化系數不同,導致每個塊產生的失真不一樣,造成像素塊的邊界不連續,因此人眼觀看視頻的時會有方塊效應(也就是有很多馬賽克現象)。為了提高視頻質量,有必要對方塊效應進行消除,這就是環路濾波模塊的功能。經過量化操作之后的數據塊,再經過反量化、反變換,然后進行重構,接着進入去方塊濾波進行去方塊操作,得到的像素塊就可以作為參考像素塊給預測模塊使用。環路濾波是一個可選模塊。
(5) 熵編碼。熵編碼的目的是去除統計冗余,實現數據的進一步壓縮。這么說可能有點抽象,舉個例子,假設有這樣一組數據[0,4,4,24,2],如果使用定長編碼來進行編碼,這段數據可以表示為[00000,00100,00100,11000,00010],每個數據需要5 bit來表示,這段數據的總長度是5 bit x 5=25 bit;如果我們使用哈夫曼來編碼,這個數組中每個元素概率值分別如下:數值0的概率是20%,數值4的概率是40%,數值24的概率是20%,數值2的概率是20%,即[20%,40%,20%,20%],根據每個元素的概率構造哈夫曼樹(節點中括號內的是數組元素值),如下圖所示,因此這段數據可以表示為[0,10,110,111],數據的總長度是11 bit。
由此可見使用哈夫曼編碼可以去除統計冗余,實現數據壓縮的目的,哈夫曼編碼就是一種熵編碼方法,但是由於哈夫曼編碼對錯誤非常敏感,不適合實際應用,因此實際應用中通常使用變長編碼(CAVLC)和算術編碼(CABAC)作為熵編碼算法。算術編碼利用一個0到1之間的浮點數來描述一個信號序列,然后用這個浮點數來表示這個信號序列,極大的壓縮了數據。算術編碼可以使用一個簡單的例子說明,假設有一個二進制串“10101110”,符號0和1的概率值都是50%,算術編碼的過程如下:
(1) 設置定一個區間,通常這個區間我們設定為[0,1),然后使用low指向區間的下界,用high指向區間的上界,現在low指向0,rhigh指向1.
(2) 輸入每一個符號,按照符號的不同對low和high進行調整,調整方法如下面公式所示,最后把low指向的浮點數作為這個符號串的碼字,表示這個二進制串,可以看到算術編碼的壓縮效率比哈夫曼編碼高很多,在x264中使用CABAC(上下文自適應的二進制算數編碼)作為熵編碼算法。
以上就是編解碼技術的基礎知識介紹,該系列第二篇文章將會介紹視頻編解碼技術的實踐。
更多即時通訊、音視頻技術的干貨文章,請關注網易雲信博客。