一:前言
H264是新一代的編碼標准,以高壓縮高質量和支持多種網絡的流媒體傳輸著稱,在編碼方面,我理解的他的理論依據是:參照一段時間內圖像的統計結果表明,在相鄰幾幅圖像畫面中, 一般有差別的像素只有10%以內的點,亮度差值變化不超過2%,而色度差值的變化只有1%以內。所以對於一段變化不大圖像畫面,我們可以先編碼出一個完整 的圖像幀A,隨后的B幀就不編碼全部圖像,只寫入與A幀的差別,這樣B幀的大小就只有完整幀的1/10或更小!B幀之后的C幀如果變化不大,我們可以繼續 以參考B的方式編碼C幀,這樣循環下去。這段圖像我們稱為一個序列(序列就是有相同特點的一段數據),當某個圖像與之前的圖像變化很大,無法參考前面的幀 來生成,那我們就結束上一個序列,開始下一段序列,也就是對這個圖像生成一個完整幀A1,隨后的圖像就參考A1生成,只寫入與A1的差別內容。
在H264協議里定義了三種幀,完整編碼的幀叫I幀,參考之前的I幀生成的只包含差異部分編碼的幀叫P幀,還有一種參考前后的幀編碼的幀叫B幀。
H264采用的核心算法是幀內壓縮和幀間壓縮,幀內壓縮是生成I幀的算法,幀間壓縮是生成B幀和P幀的算法。
二: 序列的說明
在H264中圖像以序列為單位進行組織,一個序列是一段圖像編碼后的數據流,以I幀開始,到下一個I幀結束。
一個序列的第一個圖像叫做 IDR 圖像(立即刷新圖像),IDR 圖像都是 I 幀圖像。H.264 引入 IDR 圖像是為了解碼的重同步,當解碼器解碼到 IDR 圖像時,立即將參考幀隊列清空,將已解碼的數據全部輸出或拋棄,重新查找參數集,開始一個新的序列。這樣,如果前一個序列出現重大錯誤,在這里可以獲得重新同步的機會。IDR圖像之后的圖像永遠不會使用IDR之前的圖像的數據來解碼。
一個序列就是一段內容差異不太大的圖像編碼后生成的一串數據流。當運動變化比較少時,一個序列可以很長,因為運動變化少就代表圖像畫面的內容變動很小,所 以就可以編一個I幀,然后一直P幀、B幀了。當運動變化多時,可能一個序列就比較短了,比如就包含一個I幀和3、4個P幀。
三:
視頻壓縮中,每幀代表一幅靜止的圖像。而在實際壓縮時,會采取各種算法減少數據的容量,其中IPB就是最常見的。
簡單地說,I幀是關鍵幀,屬於幀內壓縮。就是和AVI的壓縮是一樣的。P是向前搜索的意思。B是雙向搜索。他們都是基於I幀來壓縮數據。
I幀表示關鍵幀,你可以理解為這一幀畫面的完整保留;解碼時只需要本幀數據就可以完成(因為包含完整畫面)
P幀表示的是這一幀跟之前的一個關鍵幀(或P幀)的差別,解碼時需要用之前緩存的畫面疊加上本幀定義的差別,生成最終畫面。(也就是差別幀,P幀沒有完整畫面數據,只有與前一幀的畫面差別的數據)
B幀是雙向差別幀,也就是B幀記錄的是本幀與前后幀的差別(具體比較復雜,有4種情況),換言之,要解碼B幀,不僅要取得之前的緩存畫面,還要解碼之后的畫面,通過前后畫面的與本幀數據的疊加取得最終的畫面。B幀壓縮率高,但是解碼時CPU會比較累~。
采用的壓縮方法: 分組:把幾幀圖像分為一組(GOP),為防止運動變化,幀數不宜取多。
1.定義幀:將每組內各幀圖像定義為三種類型,即I幀、B幀和P幀;
2.預測幀:以I幀做為基礎幀,以I幀預測P幀,再由I幀和P幀預測B幀;
3.數據傳輸:最后將I幀數據與預測的差值信息進行存儲和傳輸。
一、I幀
I幀:幀內編碼幀 ,I幀表示關鍵幀,你可以理解為這一幀畫面的完整保留;解碼時只需要本幀數據就可以完成(因為包含完整畫面)
I圖像(幀)是靠盡可能去除圖像空間冗余信息來壓縮傳輸數據量的幀內編碼圖像。
I幀又稱為內部畫面 (intra picture),I 幀通常是每個 GOP(MPEG 所使用的一種視頻壓縮技術)的第一個幀,經過適度地壓縮(做為隨機訪問的參考點)可以當成圖象。在MPEG編碼的過程中部分視頻幀序列壓縮成為I幀,部分壓縮成P幀,還有部分壓縮成B幀。I幀法是幀內壓縮法(P、B為幀間),也稱為“關鍵幀”壓縮法。I幀法是基於離散余弦變換DCT(Discrete Cosine Transform)的壓縮技術,這種算法與JPEG壓縮算法類似。采用I幀壓縮可達到1/6的壓縮比而無明顯的壓縮痕跡。
I幀特點:
1.它是一個全幀壓縮編碼幀。它將全幀圖像信息進行JPEG壓縮編碼及傳輸;
2.解碼時僅用I幀的數據就可重構完整圖像;
3.I幀描述了圖像背景和運動主體的詳情;
4.I幀不需要參考其他畫面而生成;
5.I幀是P幀和B幀的參考幀(其質量直接影響到同組中以后各幀的質量);
6.I幀是幀組GOP的基礎幀(第一幀),在一組中只有一個I幀;
7.I幀不需要考慮運動矢量;
8.I幀所占數據的信息量比較大。
I幀編碼流程:
(1)進行幀內預測,決定所采用的幀內預測模式。
(2)像素值減去預測值,得到殘差。
(3)對殘差進行變換和量化。
(4)變長編碼和算術編碼。
(5)重構圖像並濾波,得到的圖像作為其它幀的參考幀。
二、P幀
P圖像(幀)是通過充分降低於圖像序列中前面已編碼幀的時間冗余信息來壓縮傳輸數據量的編碼圖像,也叫預測幀。
在針對連續動態圖像編碼時,將連續若干幅圖像分成P,B,I三種類型,P幀由在它前面的P幀或者I幀預測而來,它比較與它前面的P幀或者I幀之間的相同信息或數據,也即考慮運動的特性進行幀間壓縮。P幀法是根據本幀與相鄰的前一幀(I幀或P幀)的不同點來壓縮本幀數據。采取P幀和I幀聯合壓縮的方法可達到更高的壓縮且無明顯的壓縮痕跡。
P幀的預測與重構:
P幀是以I幀為參考幀,在I幀中找出P幀“某點”的預測值和運動矢量,取預測差值和運動矢量一起傳送。在接收端根據運動矢量從I幀中找出P幀“某點”的預測值並與差值相加以得到P幀“某點”樣值,從而可得到完整的P幀。
P幀特點:
①P幀是I幀后面相隔1-2幀的編碼幀。
②P幀采用運動補償的方法傳送它與前面的I或P幀的差值及運動矢量(預測誤差)。
③解碼時必須將I幀中的預測值與預測誤差求和后才能重構完整的P幀圖像。
④P幀屬於前向預測的幀間編碼。它只參考前面最靠近它的I幀或P幀。
⑤P幀可以是其后面P幀的參考幀,也可以是其前后的B幀的參考幀。
⑥由於P幀是參考幀,它可能造成解碼錯誤的擴散。
⑦由於是差值傳送,P幀的壓縮比較高。
三、B幀
B幀:雙向預測內插編碼幀。B幀是雙向差別幀,也就是B幀記錄的是本幀與前后幀的差別(具體比較復雜,有4種情況,但我這樣說簡單些),換言之,要解碼B 幀,不僅要取得之前的緩存畫面,還要解碼之后的畫面,通過前后畫面的與本幀數據的疊加取得最終的畫面。B幀壓縮率高,但是解碼時CPU會比較累。
P幀:前向預測編碼幀。P幀表示的是這一幀跟之前的一個關鍵幀(或P幀)的差別,解碼時需要用之前緩存的畫面疊加上本幀定義的差別,生成最終畫面。(也就是差別幀,P幀沒有完整畫面數據,只有與前一幀的畫面差別的數據)
B圖像(幀)是既考慮與源圖像序列前面已編碼幀,也顧及源圖像序列后面已編碼幀之間的時間冗余信息來壓縮傳輸數據量的編碼圖像,也叫雙向預測幀。
B幀法是雙向預測的幀間壓縮算法。當把一幀壓縮成B幀時,它根據相鄰的前一幀、本幀以及后一幀數據的不同點來壓縮本幀,也即僅記錄本幀與前后幀的差值。只有采用B幀壓縮才能達到200:1的高壓縮。一般地,I幀壓縮效率最低,P幀較高,B幀最高。
B幀的預測與重構:
B幀以前面的I或P幀和后面的P幀為參考幀,“找出”B幀“某點”的預測值和兩個運動矢量,並取預測差值和運動矢量傳送。接收端根據運動矢量在兩個參考幀中“找出(算出)”預測值並與差值求和,得到B幀“某點”樣值,從而可得到完整的B幀。
B幀特點:
1.B幀是由前面的I或P幀和后面的P幀來進行預測的;
2.B幀傳送的是它與前面的I或P幀和后面的P幀之間的預測誤差及運動矢量;
3.B幀是雙向預測編碼幀;
4.B幀壓縮比最高,因為它只反映2參考幀間運動主體的變化情況,預測比較准確;
5.B幀不是參考幀,不會造成解碼錯誤的擴散。
P 幀和 B 幀編碼的基本流程為:
(1)進行運動估計,計算采用幀間編碼模式的率失真函數(節)值。P 幀 只參考前面的幀,B 幀可參考后面的幀。
(2)進行幀內預測,選取率失真函數值最小的幀內模式與幀間模式比較,確定采用哪種編碼模式。
(3)計算實際值和預測值的差值。
(4)對殘差進行變換和量化。
(5)若編碼,如果是幀間編碼模式,編碼運動矢量。
注:I、B、P各幀是根據壓縮算法的需要,是人為定義的,它們都是實實在在的物理幀,至於圖像中的哪一幀是I幀,是隨機的,一但確定了I幀,以后的各幀就嚴格按規定順序排列。
IDR(Instantaneous Decoding Refresh)--即時解碼刷新。
I幀:幀內編碼幀是一種自帶全部信息的獨立幀,無需參考其它圖像便可獨立進行解碼,視頻序列中的第一個幀始終都是I幀。
I和IDR幀都是使用幀內預測的。它們都是同一個東西而已,在編碼和解碼中為了方便,要首個I幀和其他I幀區別開,所以才把第一個首個I幀叫IDR,這樣就方便控制編碼和解碼流程。 IDR幀的作用是立刻刷新,使錯誤不致傳播,從IDR幀開始,重新算一個新的序列開始編碼。而I幀不具有隨機訪問的能力,這個功能是由IDR承擔。 IDR會導致DPB(DecodedPictureBuffer 參考幀列表——這是關鍵所在)清空,而I不會。IDR圖像一定是I圖像,但I圖像不一定是IDR圖像。一個序列中可以有很多的I圖像,I圖像之后的圖像可以引用I圖像之間的圖像做運動參考。一個序列中可以有很多的I圖像,I圖像之后的圖象可以引用I圖像之間的圖像做運動參考。
對於IDR幀來說,在IDR幀之后的所有幀都不能引用任何IDR幀之前的幀的內容,與此相反,對於普通的I-幀來說,位於其之后的B-和P-幀可以引用位於普通I-幀之前的I-幀。從隨機存取的視頻流中,播放器永遠可以從一個IDR幀播放,因為在它之后沒有任何幀引用之前的幀。但是,不能在一個沒有IDR幀的視頻中從任意點開始播放,因為后面的幀總是會引用前面的幀 。
收到 IDR 幀時,解碼器另外需要做的工作就是:把所有的 PPS 和 SPS 參數進行更新。
對IDR幀的處理(與I幀的處理相同):(1) 進行幀內預測,決定所采用的幀內預測模式。(2) 像素值減去預測值,得到殘差。(3) 對殘差進行變換和量化。(4) 變長編碼和算術編碼。(5) 重構圖像並濾波,得到的圖像作為其它幀的參考幀。
多參考幀情況下, 舉個例子 :有如下幀序列: IPPPP I P PPP ……。按照 3 個參考幀編碼。
因為“按照 3 個參考幀編碼”,所以參考幀隊列長度為 3 。
遇到綠色的 I 時,並不清空參考幀隊列,把這個 I 幀加入參考幀隊列(當然 I 編碼時不用參考幀。)。再檢測到紅色的 P 幀時,用到的就是 PPI 三幀做參考了。
h264的壓縮方法:
1.分組:把幾幀圖像分為一組(GOP,也就是一個序列),為防止運動變化,幀數不宜取多。
2.定義幀:將每組內各幀圖像定義為三種類型,即I幀、B幀和P幀;
3.預測幀:以I幀做為基礎幀,以I幀預測P幀,再由I幀和P幀預測B幀;
4.數據傳輸:最后將I幀數據與預測的差值信息進行存儲和傳輸。
幀內(Intraframe)壓縮也稱為空間壓縮(Spatial compression)。當壓縮一幀圖像時,僅考慮本幀的數據而不考慮相鄰幀之間的冗余信息,這實際上與靜態圖像壓縮類似。幀內一般采用有損壓縮算法,由於幀內壓縮是編碼一個完整的圖像,所以可以獨立的解碼、顯示。幀內壓縮一般達不到很高的壓縮,跟編碼jpeg差不多。
幀間(Interframe)壓縮的原理是:相鄰幾幀的數據有很大的相關性,或者說前后兩幀信息變化很小的特點。也即連續的視頻其相鄰幀之間具有冗余信 息,根據這一特性,壓縮相鄰幀之間的冗余量就可以進一步提高壓縮量,減小壓縮比。幀間壓縮也稱為時間壓縮(Temporal compression),它通過比較時間軸上不同幀之間的數據進行壓縮。幀間壓縮一般是無損的。幀差值(Frame differencing)算法是一種典型的時間壓縮法,它通過比較本幀與相鄰幀之間的差異,僅記錄本幀與其相鄰幀的差值,這樣可以大大減少數據量。
順便說下有損(Lossy )壓縮和無損(Lossy less)壓縮。無損壓縮也即壓縮前和解壓縮后的數據完全一致。多數的無損壓縮都采用RLE行程編碼算法。有損壓縮意味着解壓縮后的數據與壓縮前的數據不 一致。在壓縮的過程中要丟失一些人眼和人耳所不敏感的圖像或音頻信息,而且丟失的信息不可恢復。幾乎所有高壓縮的算法都采用有損壓縮,這樣才能達到低數據 率的目標。丟失的數據率與壓縮比有關,壓縮比越小,丟失的數據越多,解壓縮后的效果一般越差。此外,某些有損壓縮算法采用多次重復壓縮的方式,這樣還會引 起額外的數據丟失。
四、實際應用
從上面的解釋看,我們知道I和P的解碼算法比較簡單,資源占用也比較少,I只要自己完成就行了,P呢,也只需要解碼器把前一個畫面緩存一下,遇到P時就使用之前緩存的畫面就好了,如果視頻流只有I和P,解碼器可以不管后面的數據,邊讀邊解碼,線性前進,大家很舒服。
但網絡上的電影很多都采用了B幀,因為B幀記錄的是前后幀的差別,比P幀能節約更多的空間,但這樣一來,文件小了,解碼器就麻煩了,因為在解碼時,不僅要用之前緩存的畫面,還要知道下一個I或者P的畫面(也就是說要預讀預解碼),而且,B幀不能簡單地丟掉,因為B幀其實也包含了畫面信息,如果簡單丟掉,並用之前的畫面簡單重復,就會造成畫面卡(其實就是丟幀了),並且由於網絡上的電影為了節約空間,往往使用相當多的B幀,B幀用的多,對不支持B幀的播放器就造成更大的困擾,畫面也就越卡。
一般平均來說,I的壓縮率是7(跟JPG差不多),P是20,B可以達到50,可見使用B幀能節省大量空間,節省出來的空間可以用來保存多一些I幀,這樣在相同碼率下,可以提供更好的畫質。
在如上圖中,GOP (Group of Pictures)長度為13,S0~S7 表示 8個視點,T0~T12 為 GOP的 13個時刻。每個 GOP包含幀數為視點數 GOP 長度的乘積。在該圖中一個 GOP 中,包含94 個 B幀。B 幀占一個 GOP 總幀數的 90.38%。GOP 越長,B 幀所占比例更高,編碼的率失真性能越高。下圖測試序列 Race1 在不同 GOP 下的率失真性能對比。