1. 程式人生 > >影象和流媒體 -- I 幀,B幀,P幀,IDR幀的區別

影象和流媒體 -- I 幀,B幀,P幀,IDR幀的區別

一、H246簡介

    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幀。

三、3 種幀的說明


(1)I幀

I 幀:幀內編碼幀 ,I 幀表示關鍵幀,你可以理解為這一幀畫面的完整保留;解碼時只需要本幀資料就可以完成(因為包含完整畫面)
I 幀特點:
1)它是一個全幀壓縮編碼幀。它將全幀影象資訊進行 JPEG 壓縮編碼及傳輸;
2)解碼時僅用 I 幀的資料就可重構完整影象;
3)I 幀描述了影象背景和運動主體的詳情;
4)I 幀不需要參考其他畫面而生成;
5)I 幀是 P 幀和 B 幀的參考幀(其質量直接影響到同組中以後各幀的質量);
6)I 幀是幀組 GOP 的基礎幀(第一幀),在一組中只有一個 I 幀;
7)I 幀不需要考慮運動向量;
8)I 幀所佔資料的資訊量比較大。

(2)P幀 

P 幀:前向預測編碼幀。
P 幀表示的是這一幀跟之前的一個關鍵幀(或P 幀)的差別,解碼時需要用之前快取的畫面疊加上本幀定義的差別,生成最終畫面。(也就是差別幀,P 幀沒有完整畫面資料,只有與前一幀的畫面差別的資料
P幀的預測與重構:P 幀是以 I 幀為參考幀,在 I 幀中找出 P 幀“某點”的預測值和運動向量,取預測差值和運動向量一起傳送。在接收端根據運動向量從 I 幀中找出 P 幀“某點”的預測值並與差值相加以得到 P 幀“某點”樣值,從而可得到完整的 P 幀。
P 幀特點:
1)P 幀是 I 幀後面相隔 1~2 幀的編碼幀;
2)P 幀採用運動補償的方法傳送它與前面的 I 或 P 幀的差值及運動向量(預測誤差);
3)解碼時必須將 I 幀中的預測值與預測誤差求和後才能重構完整的 P 幀影象;
4)P 幀屬於前向預測的幀間編碼。它只參考前面最靠近它的 I 幀或 P 幀;
5)P 幀可以是其後面 P 幀的參考幀,也可以是其前後的 B 幀的參考幀;
6)由於 P 幀是參考幀,它可能造成解碼錯誤的擴散;
7)由於是差值傳送,P 幀的壓縮比較高。

(3)B幀

B 幀:雙向預測內插編碼幀。B 幀是雙向差別幀,也就是 B 幀記錄的是本幀與前後幀的差別(具體比較複雜,有 4 種情況,但我這樣說簡單些),換言之,要解碼 B 幀,不僅要取得之前的快取畫面,還要解碼之後的畫面,通過前後畫面的與本幀資料的疊加取得最終的畫面。B 幀壓縮率高,但是解碼時 CPU 會比較累。
B 幀的預測與重構:B 幀以前面的 I 或 P 幀和後面的 P 幀為參考幀,“找出”B 幀“某點”的預測值和兩個運動向量,並取預測差值和運動向量傳送。接收端根據運動向量在兩個參考幀中“找出(算出)”預測值並與差值求和,得到 B幀“某點”樣值,從而可得到完整的 B 幀。
B 幀特點
1)B 幀是由前面的 I 或 P 幀和後面的 P 幀來進行預測的;
2)B 幀傳送的是它與前面的 I 或 P 幀和後面的 P 幀之間的預測誤差及運動向量;
3)B 幀是雙向預測編碼幀;
4)B 幀壓縮比最高,因為它只反映丙參考幀間運動主體的變化情況,預測比較準確;
5)B 幀不是參考幀,不會造成解碼錯誤的擴散。
注:I、B、P 各幀是根據壓縮演算法的需要,是人為定義的,它們都是實實在在的物理幀。一般來說,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 下的率失真效能對比。

四、壓縮演算法的說明

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 幀與 IDR 幀的區別

IDR(Instantaneous Decoding Refresh)--即時解碼重新整理。
    I 和 IDR 幀都是使用幀內預測的。它們都是同一個東西而已,在編碼和解碼中為了方便,要首個 I 幀和其他 I 幀區別開,所以才把第一個首個 I 幀叫 IDR,這樣就方便控制編碼和解碼流程。IDR 幀的作用是立刻重新整理,使錯誤不致傳播,從IDR幀開始,重新算一個新的序列開始編碼。而 I 幀不具有隨機訪問的能力,這個功能是由 IDR 承擔。IDR 會導致DPB(參考幀列表——這是關鍵所在)清空,而 I 不會。IDR 影象一定是 I 影象,但I影象不一定是 IDR 影象。一個序列中可以有很多的I影象,I 影象之後的影象可以引用 I 影象之間的影象做運動參考。一個序列中可以有很多的 I 影象,I 影象之後的圖象可以引用I影象之間的影象做運動參考。
    對於 IDR 幀來說,在 IDR 幀之後的所有幀都不能引用任何 IDR 幀之前的幀的內容,與此相反,對於普通的 I 幀來說,位於其之後的 B- 和 P- 幀可以引用位於普通 I- 幀之前的 I- 幀。從隨機存取的視訊流中,播放器永遠可以從一個 IDR 幀播放,因為在它之後沒有任何幀引用之前的幀。但是,不能在一個沒有 IDR 幀的視訊中從任意點開始播放,因為後面的幀總是會引用前面的幀。

舉個例子,在一段視訊中,存在以下幀:I P B P B P B B P I PB…
如果這段視訊應用了多重參照幀,那麼藍色的 P 幀在參照他前面的 I 幀(紅色)的同時,還可能會參照 I 幀之前的 P (綠色),由於 I 幀前後的場景可能會有很大的反差甚至根本不同,所以此時 P 幀參考I幀之前的幀不但會沒有意義,反而會造成很多問題。所以一種新型的幀被引入,那就是 IDR 幀。如果這段視訊應用了多重參考幀的同時採用了 IDR 幀,那麼幀的順序就會變成這樣:I P B P B P B B PIDRPB…

由於 IDR 幀禁止後面的幀向自己前面的幀參照,所以這回那個藍色的 P 幀就不會參照綠色的 P 幀了。

六、獲取 I 幀

使用 ffmpeg 獲取 I 幀

指令為:ffmpeg -i wkll.mp4 -ss 00:00:00 -t 1 -r 1 -q:v 2 -f image2 pic-%03d.jpeg

生成如下: