1. 程式人生 > >Android視訊開發基礎(一)

Android視訊開發基礎(一)

基本概念

位元速率

       位元速率就是資料傳輸時單位時間傳送的資料位數,單位一般是kbps即千位每秒。位元速率影響體積,與體積成正比:位元速率越大,體積越大;位元速率越小,體積越小。位元速率還影響清晰度,位元速率越高清晰度也就越高。需要注意的是位元速率超過一定數值,對影象的質量沒有多大影響。通常來講,體積=位元速率×時間,由於有其他因素影響,這個值會稍微有一些誤差。位元速率也就是取樣率(並不等同於取樣率,取樣率的單位是Hz,表示每秒取樣的次數),單位時間內取樣率越大,精度就越高,處理出來的檔案就越接近原始檔案。但是檔案體積與取樣率是成正比的,所以幾乎所有的編碼格式重視的都是如何用最低的位元速率達到最少的失真,圍繞這個核心衍生出來cbr(固定位元速率)與vbr(可變位元速率)。

       通常來說,一個視訊檔案包括畫面和聲音,音訊及視訊都有各自不同的位元速率,也就是說,同一個視訊檔案音訊和視訊的位元速率並不相同。而通常所說的視訊檔案位元速率大小,一般是指視訊檔案中音訊和視訊位元速率的總和。

       CBR 編碼 (Constant Bitrate)

       CBR 編碼是一種靜態位元速率,也就是視訊檔案從頭到尾都是恆定位元速率。

       它的優點是運算量小,壓縮快,能被大多數軟體和裝置支援,缺點是佔用空間相對大,壓縮出來的視訊畫質較差,尤其是在在畫面劇烈運動的時候會由於位元速率不夠而丟失部分畫面資訊,從視覺上來看就是畫面波紋嚴重,影象不清晰。一般情況下,合成相同質量的節目時,採用CBR編碼方式時節目合成時間會短一些,但檔案的長度會大一些。

       VBR 編碼 (Variable Bitrate)

       它是一種動態位元速率,也就是沒有固定的位元率,編碼演算法根據視訊內容的變化來選擇不同的實時位元速率對視訊進行編碼,把較高的位元速率用於複雜的動態畫面,而把較低的位元速率用於靜態畫面,合理利用資源,達到畫質較高的情況下,體積也較小。當視訊內容的畫面變化忽大忽小時,VBR 編碼是很有優勢的。使用 VBR 編碼時,系統將自動為內容的簡單部分分配較少的位元,從而留出足量的位元用於生成高質量的複雜部分,這意味著複雜性恆定的內容不會受益於 VBR 編碼。對混合內容使用 VBR 編碼時,在檔案大小相同的條件下,VBR 編碼的輸出結果要比 CBR 編碼的輸出結果質量好得多。在某些情況下,與 CBR 編碼檔案質量相同的 VBR 編碼檔案,其體積大小可能只有前者的一半。

       VBR的優點就體現出來了,畫面質量相對高,檔案體積相對較小,但是缺點也很明顯,編碼的演算法要複雜很多,運算量大,壓縮時間長。

幀率

        幀率或者稱FPS(Frames Per Second,幀/秒),是指每秒顯示的圖片數,或者GPU處理時每秒能夠更新的次數。越高的幀速率可以得到更流暢逼真的畫面。每秒鐘幀數越多,所顯示的動作就會越流暢。幀率也會影響體積,幀率越高,每秒鐘顯示的畫面越多,體積就越大。

       由於人類眼睛的特殊生理結構,如果畫面幀率高於16,就會認為是連貫的,此現象稱之為視覺暫留。並且當幀速達到一定數值後,再增長的話,人眼能感知的流暢度的提升就比較有限了。一般來說30fps是可以接受的,將效能提升至60fps則可以明顯提升互動感和逼真感,如果超過75fps一般就不容易察覺到有明顯的流暢度提升了。如果幀率超過螢幕重新整理率只會浪費圖形處理的能力,因為監視器不能以這麼快的速度更新。

解析度

       通常所說的1280x720(720p)或者1920x1080(1080p),就是視訊的解析度。解析度影響影象大小,與影象大小成正比:解析度越高,影象越大;解析度越低,影象越小。

清晰度

       在位元速率一定的情況下,解析度與清晰度成反比關係:解析度越高,影象越不清晰,解析度越低,影象越清晰。        在解析度一定的情況下,位元速率與清晰度成正比關係,位元速率越高,影象越清晰;位元速率越低,影象越不清晰。

聲道

       指聲音在錄製或播放時,在不同空間位置採集或回放的相互獨立的音訊訊號,所以聲道數也就是聲音錄製時的音源數量或回放時相應的揚聲器數量。 

位深度

       每一個畫素用多少位表示,這個位數就叫“位深度”。位深度越大,可用的顏色越多,顏色表現就越逼真。位深度為8的影象可用顏色為256種。

       每個視訊都包含這些基本的引數,我們可以通過一個叫做MediaInfo的工具在電腦上來檢視視訊檔案的詳細引數。下面的兩張圖展示了一個視訊的引數資訊。

       從上面的圖中,可以看到視訊的幀率為20fps,視訊平均位元速率為195kbps,而且是採用的VBR編碼,而音訊和視訊分別的位元速率為64kbps和128kbps,視訊軌和音訊軌的編碼方式分別為H.264 AVC和AAC。

視訊的格式

       說到視訊的格式,首先想到的可能會是mp4、3gp、avi、flv、rmvb、mkv等日常生活中常見視訊檔案格式。這些格式其實只是視訊的封裝格式。事實上視訊的格式分為兩種:封裝格式和編碼格式。

       一張圖片可以用很多種演算法來顯示在螢幕中,所以圖片的編碼方式就有了JPEG,BMP,PNG等。。。 視訊是動態影象,所以在這裡就又多出了一個概念,用什麼樣的方式表達1s內的若干張圖片,這就是簡單意義上的視訊編碼,繼而就誕生了MPEG,H.264等多種編碼格式。後來有了音訊、字幕、配音,就需要一個容器來把他們全部放進去儲存,所以就誕生了封裝格式。這段話就通俗的解釋了編碼格式和封裝格式的作用和區別。

封裝格式

       所謂封裝格式,就是按照一定的規則來將視訊軌道、可能多個的音訊軌道、字幕等視訊檔案所需要的零散資訊組裝在一起,播放視訊檔案的時候一起同步進行播放,並且提供了視訊索引,可以讓你在播放視訊時拖動進度條。也就是說它僅僅是一個外殼,或者把它當成一個放視訊軌和音訊軌的資料夾也可以。同時裡面都會有一些資訊,比如當前流中包含哪些編碼型別、時間戳等,播放器可以按照這些資訊來匹配解碼器、同步音視訊。但是視訊檔案的封裝格式並不影響視訊的畫質,影響視訊畫質的是視訊的編碼格式。

       視訊封裝格式其實和裡面的視訊編碼和音訊編碼關係不大。之所以有這麼多不同的封裝格式是為了適應不同的播放場景。典型的三種視訊封裝:ts、mp4和mkv,ts適合網路流媒體播放,體積較大,一般用於電視直播或網路直播中;mp4一般只包括一條視訊軌和一條音訊軌,適合大多數裝置,相容性最好;mkv可以封裝多個音訊軌、字幕軌,適合網路傳播分享。

       大多數情況下,視訊檔案字尾名就是封裝格式的名字。不過我們也可以手動修改視訊檔案的字尾。

編碼格式

       所謂視訊編碼格式就是指通過特定的壓縮技術,將某個視訊格式的檔案轉換成另一種視訊格式檔案的方式。不同編碼方式的區別主要是壓縮演算法的不同。視訊編碼的目的主要是壓縮資料體積。視訊中常用的編碼標準有H.26X系列、MPEG系列、Divx、Xvid、WMV-HD和VC-1等等。         在移動端使用最多的mp4視訊檔案,主要使用H.264 AVC編碼格式。它主要有以下優點:

       1.低位元速率:和MPEG2、MPEG4等壓縮技術相比,在同等影象質量下,採用H.264技術壓縮後的資料量只有MPEG2的1/8,MPEG4的1/3。H.264的最大優勢是具有很高的資料壓縮率,可以有效減少使用者頻寬的佔用。

       2.高質量的影象:H.264能提供連續、流暢的高質量影象。

       3.容錯能力強:H.264提供瞭解決在不穩定網路環境下容易發生的丟包等錯誤的必要工具。

       4.網路適應性強:H.264提供了網路抽象層,使得H.264的檔案能容易地在不同網路上傳輸。

       我們注意到,一個完整的視訊檔案是由音訊和視訊兩部分組成。H.264、Xvid等就是視訊編碼格式,MP3、AAC等就是音訊編碼格式。而當前客戶端中使用最多的mp4格式的視訊檔案,視訊和音訊編碼格式通常使用的是H.264和AAC編碼。

       下圖列出來常用的視訊封裝格式與編碼格式的對應關係

       事實上,很多封裝容器對音訊編碼和視訊編碼的組合方式放的很開,如AVI還可以使用H264+AAC組合。尤

其是MKV封裝容器,基本無論什麼樣的組合都可以!但一般MKV用的最多的就是H264+AAC組合,此組合檔案

體積最小,清晰度最高。

H.264編碼

基本原理

       H.264是新一代的編碼標準,以高壓縮高質量和支援多種網路的流媒體傳輸著稱,在編碼方面,它的理論依據是:一段時間內影象的統計結果表明,在相鄰幾幅影象畫面中,一般有差別的畫素只有10%以內的點,亮度差值變化不超過2%,而色度差值的變化只有1%以內。所以對於一段變化不大的影象畫面,我們可以先編碼出一個完整的影象幀A,隨後的B幀不編碼全部影象,只寫入與A幀的差別,這樣B幀的大小就只有完整幀的1/10或更小!B幀之後的C幀如果變化不大,我們可以繼續以參考B的方式編碼C幀,這樣迴圈下去。這段影象我們稱為一個序列,當某個影象與之前的影象變化很大,無法參考前面的幀來生成,那我們就結束上一個序列,開始下一段序列。    

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

三種幀的不同

I幀 

幀內編碼幀,I幀表示關鍵幀,可以理解為這一幀畫面的完整保留,解碼時只需要本幀資料就可以完成。

1)它是一個全幀壓縮編碼幀。它將全幀影象資訊進行JPEG壓縮編碼及傳輸;

2)解碼時僅用I幀的資料就可重構完整影象;

3)I幀描述了影象背景和運動主體的詳情;

4)I幀不需要參考其他畫面而生成;

5)I幀是P幀和B幀的參考幀(其質量直接影響到同組中以後各幀的質量);

6)I幀是幀組GOP的基礎幀(第一幀),在一組中只有一個I幀;

7)I幀不需要考慮運動向量;

8)I幀所佔資料的資訊量比較大。

P幀 

前向預測編碼幀。P幀表示的是這一幀跟之前的一個關鍵幀(或P幀)的差別,解碼時需要用之前快取的畫面疊加上本幀定義的差別,生成最終畫面。(也就是差別幀,P幀沒有完整畫面資料,只有與前一幀的畫面差別的資料)。

P幀的預測與重構:P幀是以I幀為參考幀,在I幀中找出P幀“某點”的預測值和運動向量,取預測差值和運動向量一起傳送。在接收端根據運動向量從I幀中找出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幀的壓縮比較高。

B幀

雙向預測內插編碼幀。B幀是雙向差別幀,也就是B幀記錄的是本幀與前後幀的差別,換言之,要解碼B幀,不僅要取得之前的快取畫面,還要解碼之後的畫面,通過前後畫面的與本幀資料的疊加取得最終的畫面。B幀壓縮率高,但是解碼時CPU會比較累。

B幀的預測與重構:B幀以前面的I或P幀和後面的P幀為參考幀,“找出”B幀“某點”的預測值和兩個運動向量,並取預測差值和運動向量傳送。接收端根據運動向量在兩個參考幀中“找出(算出)”預測值並與差值求和,得到B幀“某點”樣值,從而可得到完整的B幀。

1)B幀是由前面的I或P幀和後面的P幀來進行預測的;

2)B幀傳送的是它與前面的I或P幀和後面的P幀之間的預測誤差及運動向量;

3)B幀是雙向預測編碼幀;

4)B幀壓縮比最高,因為它只反映丙參考幀間運動主體的變化情況,預測比較準確;

5)B幀不是參考幀,不會造成解碼錯誤的擴散。

       I、B、P各幀是根據壓縮演算法的需要,是人為定義的,它們都是實實在在的物理幀。一般來說,I幀的壓縮率是7,P幀是20,B幀可以達到50。可見使用B幀能節省大量空間,節省出來的空間可以用來儲存多一些I幀,這樣在相同位元速率下,可以提供更好的畫質。

       在視訊編碼序列中,GOP即Group of Picture(影象組),指兩個I幀之間的距離,Reference(參考週期)指兩個P幀之間的距離。一個I幀所佔用的位元組數大於一個P幀,一個P幀所佔用的位元組數大於一個B幀。所以,在位元速率不變的前提下,GOP值越大,P、B幀的數量會越多,畫面細節更多,也就更容易獲取較好的影象質量;Reference越大,B幀的數量越多,同理也更容易獲得較好的影象質量。

       由於P、B幀的複雜度大於I幀,所以過多的P、B幀會影響編碼效率,使編碼效率降低。另外,過長的GOP還會影響Seek操作(找I幀)的響應速度,由於P、B幀是由前面的I或P幀預測得到的,所以Seek操作需要直接定位,解碼某一個P或B幀時,需要先解碼得到本GOP內的I幀及之前的N個預測幀才可以,GOP值越長,需要解碼的預測幀就越多,seek響應的時間也越長。  假設I幀損壞,那麼整個GOP結構就壞掉了,設定過長的間隔也會導致編碼後的視訊不穩定。

       一個 I 幀可以不依賴其他幀就解碼出一幅完整的影象,而 P 幀、B 幀不行。P 幀需要依賴視訊流中排在它前面的幀才能解碼出影象。B 幀則需要依賴視訊流中排在它前面或後面的幀才能解碼出影象。

       這就帶來一個問題:在視訊流中,先到來的 B 幀無法立即解碼,需要等待它依賴的後面的P 幀先解碼完成,這樣一來播放時間與解碼時間不一致了,順序打亂了,那這些幀該如何播放呢?這時就需要我們來了解另外兩個概念:DTS 和 PTS。

       DTS和PTS 

       DTS(Decoding Time Stamp):即解碼時間戳,這個時間戳的意義在於告訴播放器該在什麼時候解碼這一幀的資料。

       PTS(Presentation Time Stamp):即顯示時間戳,這個時間戳用來告訴播放器該在什麼時候顯示這一幀的資料。

       需要注意的是:雖然 DTS、PTS 是用於指導播放端的行為,但它們是在編碼的時候由編碼器生成的。

       當視訊流中沒有 B 幀時,通常 DTS 和 PTS 的順序是一致的。但如果有 B 幀時,解碼順序和播放順序就不一致了。

       比如一個視訊中,幀的顯示順序是:I B B P,現在我們需要在解碼 B 幀時知道 P 幀中資訊,因此這幾幀在視訊流中的順序可能是:I P B B,這時候就體現出每幀都有 DTS 和 PTS 的作用了。它們的順序大概如下:

       音視訊同步        上面說了DTS、PTS 相關的概念。在一個媒體流中,除了視訊以外,通常還包括音訊。音訊的播放,也有 DTS、PTS 的概念,但是音訊沒有類似視訊中 B 幀,不需要雙向預測,所以音訊幀的 DTS、PTS 順序是一致的。音訊視訊混合在一起播放,就呈現了完整的視訊。在音視訊一起播放的時候,我們通常需要面臨怎麼去同步它們的問題,以免出現音畫不同步的情況。要實現音視訊同步,通常需要選擇一個參考時鐘,參考時鐘上的時間是線性遞增的,編碼音視訊流時依據參考時鐘上的時間給每幀資料打上時間戳。在播放時,讀取資料幀上的時間戳,同時參考當前參考時鐘上的時間來安排播放。這裡的說的時間戳就是我們前面說的 PTS。

壓縮演算法

H.264的壓縮方法

       1.分組:把幾幀影象分為一組(GOP,也就是一個序列),為防止運動變化,幀數不宜取多。

       2.定義幀:將每組內各幀影象定義為三種類型,即I幀、B幀和P幀;

       3.預測幀:以I幀做為基礎幀,以I幀預測P幀,再由I幀和P幀預測B幀;

       4.資料傳輸:最後將I幀資料與預測的差值資訊進行儲存和傳輸。

幀內壓縮和幀間壓縮

       幀內(Intraframe)壓縮也稱為空間壓縮。當壓縮一幀影象時,僅考慮本幀的資料而不考慮相鄰幀之間的冗餘資訊,這實際上與靜態影象壓縮類似。幀內一般採用有失真壓縮演算法,由於幀內壓縮是編碼一個完整的影象,所以可以獨立的解碼、顯示。幀內壓縮一般達不到很高的壓縮。      

       幀間(Interframe)壓縮的原理是:相鄰幾幀的資料有很大的相關性,或者說前後兩幀資訊變化很小的特點。也即連續的視訊其相鄰幀之間具有冗餘資訊,根據這一特性,壓縮相鄰幀之間的冗餘量就可以進一步提高壓縮量,減小壓縮比。幀間壓縮也稱為時間壓縮(Temporal compression),它通過比較時間軸上不同幀之間的資料進行壓縮。幀間壓縮一般是無損的。幀差值(Frame differencing)演算法是一種典型的時間壓縮法,它通過比較本幀與相鄰幀之間的差異,僅記錄本幀與其相鄰幀的差值,這樣可以大大減少資料量。