幀間壓縮也稱
『壹』 Android 音視頻01 --- H264的基本原理01
H264壓縮技術主要採用了以下幾種方法對視頻數據進行壓縮。包括:
解決的是空域數據冗餘問題。
解決的是時域數據冗徐問題
將空間上的相關性變為頻域上無關的數據然後進行量化。
經過壓縮後的幀分為:I幀,P幀和B幀:
關鍵幀,採用幀內壓縮技術。
向前參考幀,在壓縮時,只參考前面已經處理的幀。採用幀音壓縮技術。
雙向參考幀,在壓縮時,它即參考前而的幀,又參考它後面的幀。採用幀間壓縮技術。
除了I/P/B幀外,還有圖像序列GOP。
H264的基本原理其實非常簡單,下我們就簡單的描述一下H264壓縮數據的過程。通過攝像頭採集到的視頻幀(按每秒 30 幀算),被送到 H264 編碼器的緩沖區中。編碼器先要為每一幅圖片劃分宏塊。
劃分好宏塊後,計算宏塊的象素值。以此類推,計算一幅圖像中每個宏塊的像素值。
對於視頻數據主要有兩類數據冗餘,一類是時間上的數據冗餘,另一類是空間上的數據冗餘。其中時間上的數據冗餘是最大的。為什麼說時間上的冗餘是最大的呢?假設攝像頭每秒抓取30幀,這30幀的數據大部分情況下都是相關聯的。也有可能不止30幀的的數據,可能幾十幀,上百幀的數據都是關聯特別密切的。
H264編碼器會按順序,每次取出兩幅相鄰的幀進行宏塊比較,計算兩幀的相似度。如下圖:
在H264編碼器中將幀分組後,就要計算幀組內物體的運動矢量了。
H264編碼器首先按順序從緩沖區頭部取出兩幀視頻數據,然後進行宏塊掃描。當發現其中一幅圖片中有物體時,就在另一幅圖的鄰近位置(搜索窗口中)進行搜索。如果此時在另一幅圖中找到該物體,那麼就可以計算出物體的運動矢量了。
運動矢量計算出來後,將相同部分(也就是綠色部分)減去,就得到了補償數據。我們最終只需要將補償數據進行壓縮保存,以後在解碼時就可以恢復原圖了。壓縮補償後的數據只需要記錄很少的一點數據。
我們把運動矢量與補償稱為 幀間壓縮技術 ,它解決的是視頻幀在時間上的數據冗餘。除了幀間壓縮,幀內也要進行數據壓縮,幀內數據壓縮解決的是空間上的數據冗餘。
人眼對圖象都有一個識別度,對低頻的亮度很敏感,對高頻的亮度不太敏感。所以基於一些研究,可以將一幅圖像中人眼不敏感的數據去除掉。這樣就提出了幀內預測技術。
一幅圖像被劃分好宏塊後,對每個宏塊可以進行 9 種模式的預測。找出與原圖最接近的一種預測模式。然後,將原始圖像與幀內預測後的圖像相減得殘差值。再將我們之前得到的預測模式信息一起保存起來,這樣我們就可以在解碼時恢復原圖了,經過幀內與幀間的壓縮後,雖然數據有大幅減少,但還有優化的空間。
可以將殘差數據做整數離散餘弦變換,去掉數據的相關性,進一步壓縮數據。
上面的幀內壓縮是屬於有損壓縮技術。也就是說圖像被壓縮後,無法完全復原。而CABAC屬於無損壓縮技術。
無損壓縮技術大家最熟悉的可能就是哈夫曼編碼了,給高頻的詞一個短碼,給低頻詞一個長碼從而達到數據壓縮的目的。MPEG-2中使用的VLC就是這種演算法,我們以 A-Z 作為例子,A屬於高頻數據,Z屬於低頻數據。看看它是如何做的。
CABAC也是給高頻數據短碼,給低頻數據長碼。同時還會根據上下文相關性進行壓縮,這種方式又比VLC高效很多。
制定了相互傳輸的格式,將宏快 有組織,有結構,有順序的形成一系列的碼流。這種碼流既可 通過 InputStream 網路流的數據進行傳輸,也可以封裝成一個文件進行保存,主要作用是為了傳輸。
組成H264碼流的結構中 包含以下幾部分 ,從大到小排序依次是:
H264視頻序列,圖像,片組,片,NALU,宏塊 ,像素。
NAL層:(Network Abstraction Layer,視頻數據網路抽象層) : 它的作用是H264隻要在網路上傳輸,在傳輸的過程每個包乙太網是1500位元組,而H264的幀往往會大於1500位元組,所以要進行拆包,將一個幀拆成多個包進行傳輸,所有的拆包或者組包都是通過NAL層去處理的。
VCL層:(Video Coding Layer,視頻數據編碼層) : 對視頻原始數據進行壓縮
起始碼0x 00 00 00 01 或者 0x 00 00 01 作為 分隔符 。
兩個 0x 00 00 00 01之間的位元組數據 是表示一個NAL Unit。
I 幀的特點:
1.分組:把幾幀圖像分為一組(GOP,也就是一個序列),為防止運動變化,幀數不宜取多。
2.定義幀:將每組內各幀圖像定義為三種類型,即I幀、B幀和P幀;
3.預測幀:以I幀做為基礎幀,以I幀預測P幀,再由I幀和P幀預測B幀;
4.數據傳輸:最後將I幀數據與預測的差值信息進行存儲和傳輸。
1.更高的編碼效率:同H.263等標準的特率效率相比,能夠平均節省大於50%的碼率。
2.高質量的視頻畫面:H.264能夠在低碼率情況下提供高質量的視頻圖像,在較低帶寬上提供高質量的圖像傳輸是H.264的應用亮點。
3.提高網路適應能力:H.264可以工作在實時通信應用(如視頻會議)低延時模式下,也可以工作在沒有延時的視頻存儲或視頻流伺服器中。
4.採用混合編碼結構:同H.263相同,H.264也使用採用DCT變換編碼加DPCM的差分編碼的混合編碼結構,還增加了如多模式運動估計、幀內預測、多幀預測、基於內容的變長編碼、4x4二維整數變換等新的編碼方式,提高了編碼效率。
5.H.264的編碼選項較少:在H.263中編碼時往往需要設置相當多選項,增加了編碼的難度,而H.264做到了力求簡潔的「回歸基本」,降低了編碼時復雜度。
6.H.264可以應用在不同場合:H.264可以根據不同的環境使用不同的傳輸和播放速率,並且提供了豐富的錯誤處理工具,可以很好的控制或消除丟包和誤碼。
7.錯誤恢復功能:H.264提供了解決網路傳輸包丟失的問題的工具,適用於在高誤碼率傳輸的無線網路中傳輸視頻數據。
8.較高的復雜度:264性能的改進是以增加復雜性為代價而獲得的。據估計,H.264編碼的計算復雜度大約相當於H.263的3倍,解碼復雜度大約相當於H.263的2倍。
H.264的目標應用涵蓋了目前大部分的視頻服務,如有線電視遠程監控、交互媒體、數字電視、視頻會議、視頻點播、流媒體服務等。H.264為解決不同應用中的網路傳輸的差異。定義了兩層:視頻編碼層(VCL:Video Coding Layer)負責高效的視頻內容表示,網路提取層(NAL:Network Abstraction Layer)負責以網路所要求的恰當的方式對數據進行打包和傳送。
『貳』 mpeg標準是一種什麼壓縮標准
mpeg標准又稱為運動圖像壓縮演算法的國際標准,是一種制定壓縮的標准,也可以說是一種壓縮的方式。mpeg標準是由國際標准化組織(ISO)的運動圖像專家組(MPEG)制定的一種主要適用於運動圖像壓縮的標准。
MPEG標准主要利用了具有運動補償的幀間壓縮編碼技術以減小時間冗餘度,利用DCT技術以減小圖像的空間冗餘度,利用熵編碼則在信息表示方面減小了統計冗餘度。
mpeg標準的原理
MPEG標準的視頻壓縮編碼技術主要利用了具有運動補償的幀間壓縮編碼技術以減小時間冗餘度,利用DCT技術以減小圖像的空間冗餘度,利用熵編碼則在信息表示方面減小了統計冗餘度。這幾種技術的綜合運用,大大增強了壓縮性能。MPEG-1標准於1993年8月公布,用於傳輸1.5Mbps數據傳輸率的數字存儲媒體運動圖像及其伴音的編碼。
『叄』 幀內壓縮和幀間壓縮的主要區別是什麼
幀內相對於本幀,也就是一幅畫面壓縮。而幀間是與相鄰幀之間有關聯。
『肆』 常見視頻壓縮編碼格式及含義
視頻壓縮編碼的基本概念 視頻壓縮的目標是在盡可能保證視覺效果的前提下減少視頻數據率。視頻壓縮比一般指壓縮後的數據量與壓縮前的數據量之比。由於視頻是連續的靜態圖像,因此其壓縮編碼演算法與靜態圖像的壓縮編碼演算法有某些共同之處,但是運動的視頻還有其自身的特性,因此在壓縮時還應考慮其運動特性才能達到高壓縮的目標。在視頻壓縮中常需用到以下的一些基本概念: 一、有損和無損壓縮:在視頻壓縮中有損(Lossy )和無損(Lossless)的概念與靜態圖像中基本類似。無損壓縮也即壓縮前和解壓縮後的數據完全一致。多數的無損壓縮都採用RLE行程編碼演算法。有損壓縮意味著解壓縮後的數據與壓祥物縮前的數據不一致。在壓縮的過程中要丟失一些人眼和人耳所不敏感的圖像或音頻信息,而且丟失的信息不可恢復。幾乎所有高壓縮的演算法都採用有損壓縮,這樣才能達到低數據率的目標。丟失的數據率與壓縮比有關,壓縮比越小,丟失的數據越多,解壓縮後的效果一般越差。此外,某些有損壓縮演算法採用多次重復壓縮的方式,這樣還會引起額外的數據丟失。 二、幀內和幀間壓縮:幀內(Intraframe)壓縮也稱為空間壓縮(Spatial compression)。當壓縮一幀圖像時,僅考慮本幀的數據而不考慮相鄰幀之間的冗餘信息,這實際上與靜態圖像壓縮類似。幀內一般採用有損壓縮演算法,由於幀內壓縮時各個幀之間沒有相互關系,所以壓縮後的視頻數據仍可以以幀為單位進行編輯。幀內壓縮一般達不到很高的壓縮。 採用幀間(Interframe)壓縮是基於許多視頻或動畫的連續前後兩幀具有很大的相關性,或者說前後兩幀信息變化很小的特點。也即連續的視頻其相鄰幀之間具有冗餘信息,根據這一特性,壓縮相鄰幀之間的冗餘量就可以進一步提高壓縮量,減小壓縮比。幀間壓縮也稱為時間壓縮(Temporal compression),它通過比較時間軸上不同幀之間的數據進行壓縮。幀間壓縮一般是無損的。幀差值(Frame differencing)演算法是一種典型的時間壓縮扒宴喊法,它通過比較本幀與相鄰幀之間的差異,僅記錄本幀與其相鄰幀的差值,這樣可以大大減少數據量。 三、對稱和不對稱編碼:對稱性(symmetric)是壓縮編碼的一個關鍵特徵。對稱意味著壓縮和解壓縮佔用相同的計算處理能力和時間,對稱演算法適合於實時壓縮和傳送視頻,如視頻會議應用就以採用對稱的壓縮編碼演算法為好。而在電子出版和其它多媒體應用中,一般是把視頻預先壓縮處理好,爾後再播放,因此可以採用不對稱(asymmetric)編碼。不對稱或非對稱意味著壓縮時需要花費大量的處理春野能力和時間,而解壓縮時則能較好地實時回放,也即以不同的速度進行壓縮和解壓縮。一般地說,壓縮一段視頻的時間比回放(解壓縮)該視頻的時間要多得多。例如,壓縮一段三分鍾的視頻片斷可能需要10多分鍾的時間,而該片斷實時回放時間只有三分鍾。 目前有多種視頻壓縮編碼方法,但其中最有代表性的是MPEG數字視頻格式和AVI數字視頻格式。
『伍』 iOS硬編解碼相關知識
實現直接、簡單,參數調整方便,升級易,但CPU負載重,性能較硬編碼低,低碼率下質量通常比硬編碼要好一點。
性能高,低碼率下通常質量低於軟編碼器,但部分產品在GPU硬體平台移植了優秀的軟編碼演算法(如X264)的,質量基本等同於軟編碼。
蘋果在iOS 8.0系統之前,沒有開放系統的硬體編碼解碼功能,不過Mac OS系統一直有,被稱為Video ToolBox的框架來處理硬體的編碼和解碼,終於在iOS 8.0(即 WWDC 2014 513 )後,蘋果將該框架引入iOS系統。
H.264是新一代的編碼標准,大沒以高壓縮高質量和支持多種網路的流媒體傳輸著稱,在編碼方面,我理解的理論依據是:參照一段時間內圖像的統計結果表明,在相鄰幾幅圖像畫面中,一般有差別的像素只有10%以內的點,亮度差值變化不超過2%,而色度差值的變化只有1%以內。所以對於一段變化不大圖像畫面,我們可以先編碼出一個完整的圖像幀A,隨後的B幀就不編碼全部圖像,只寫入與A幀的差別,這樣B幀的大小就只有完整幀的1/10或更小!B幀之後的C幀如果變化不大,我們可以繼續以參考B的方式編碼C幀,這樣循環下去。這段圖像我們稱為一個序列(序列就是有相同特點的一段數據),當某個圖像與之前的圖像變化很大,無法參考前面的幀來生成,那我們就結束上一個序列,開始下一段序列,也就是對這個圖像生成一個完整幀A1,隨後的圖像就參考A1生成,只寫入與A1的差別內容。
需要注意的是:
一個序列的第一個圖像叫做 IDR 圖像(立即刷新圖像),IDR 圖唯型像都是 I 幀圖像。H.264 引入 IDR 圖像是為了解碼的重同步,當解碼器解碼到 IDR 圖像時,立即將參考幀隊列清空,將已解碼的數據全部輸出或拋棄,重新查找參數集,開始一個新的序列。這樣,如果前一個序列出現重大錯誤,在這里可以獲得重新同步的機會。IDR圖像之後的圖像永遠不會使用IDR之前的圖像的數據來解碼。
一個序列就是一段內容差異不太大的圖像編碼後生成的一串數據流。當運動變化比較少時,一個序列可以很長,因為運動變化少就代表圖像畫面的內容變動很小,所以就可以編一個I幀,然後一直P幀、B幀了。當運動變化多時,可能一個序列就比較短了,比如就包含一個I幀和3、4個P幀。
I、B、P各幀是根據壓縮演算法的需要,是人為定義的,它們都是實實在在的物理幀。一般來說,I幀的壓縮率是7(跟JPG差不多),P幀是20,B幀可以達到50。可見使用B幀能節省大量空間,節省出來的空間可以用來保存多一些I幀,這樣在相同碼率下,可以提供更好的畫質。
說明:
I幀:紅色;P幀:藍色;B幀:綠色。
1、分組:把幾幀圖像分為一組(GOP,也就是一個序列),為防止運動變化,幀數不宜取多。
2、定義幀:將每組內各幀圖像定義為三種指仿猜類型,即I幀、B幀和P幀;
3、預測幀:以I幀做為基礎幀,以I幀預測P幀,再由I幀和P幀預測B幀;
4、數據傳輸:最後將I幀數據與預測的差值信息進行存儲和傳輸。
5、幀內(Intraframe)壓縮也稱為空間壓縮(Spatial compression)。
當壓縮一幀圖像時,僅考慮本幀的數據而不考慮相鄰幀之間的冗餘信息,這實際上與靜態圖像壓縮類似。幀內一般採用有損壓縮演算法,由於幀內壓縮是編碼一個完整的圖像,所以可以獨立的解碼、顯示。幀內壓縮一般達不到很高的壓縮,跟編碼jpeg差不多。
6、幀間(Interframe)壓縮。
相鄰幾幀的數據有很大的相關性,或者說前後兩幀信息變化很小的特點。也即連續的視頻其相鄰幀之間具有冗餘信息,根據這一特性,壓縮相鄰幀之間的冗餘量就可以進一步提高壓縮量,減小壓縮比。幀間壓縮也稱為時間壓縮(Temporal compression),它通過比較時間軸上不同幀之間的數據進行壓縮。幀間壓縮一般是無損的。幀差值(Frame differencing)演算法是一種典型的時間壓縮法,它通過比較本幀與相鄰幀之間的差異,僅記錄本幀與其相鄰幀的差值,這樣可以大大減少數據量。
7、有損(Lossy)壓縮和無損(Lossy less)壓縮。
無損壓縮也即壓縮前和解壓縮後的數據完全一致。多數的無損壓縮都採用RLE行程編碼演算法。
有損壓縮意味著解壓縮後的數據與壓縮前的數據不一致。在壓縮的過程中要丟失一些人眼和人耳所不敏感的圖像或音頻信息,而且丟失的信息不可恢復。幾乎所有高壓縮的演算法都採用有損壓縮,這樣才能達到低數據率的目標。丟失的數據率與壓縮比有關,壓縮比越小,丟失的數據越多,解壓縮後的效果一般越差。此外,某些有損壓縮演算法採用多次重復壓縮的方式,這樣還會引起額外的數據丟失。
DTS主要用於視頻的解碼,在解碼階段使用.
PTS主要用於視頻的同步和輸出.
在display的時候使用.在沒有B frame的情況下.DTS和PTS的輸出順序是一樣的。
下面給出一個GOP為15的例子,其解碼的參照frame及其解碼的順序都在裡面:
如上圖:
I frame 的解碼不依賴於任何的其它的幀.而p frame的解碼則依賴於其前面的I frame或者P frame.B frame的解碼則依賴於其前的最近的一個I frame或者P frame 及其後的最近的一個P frame.
在iOS中,與視頻相關的Framework庫有5個,從頂層開始分別是 AVKit -> AVFoundation -> VideoToolbox -> Core Media -> Core Video
其中VideoToolbox可以將視頻解壓到 CVPixelBuffer ,也可以壓縮到 CMSampleBuffer 。
但是我們常用的是 CMSampleBuffer .
編碼前和解碼後的圖像數據結構(未壓縮光柵圖像緩存區-Uncompressed Raster Image Buffer)
存放CVPixelBuffer
CFDictionary對象,可能包含了視頻的寬高,像素格式類型(32RGBA, YCbCr420),是否可以用於OpenGL ES等相關信息
時間戳相關。時間以 64-big/32-bit形式出現。 分子是64-bit的時間值,分母是32-bit的時標(time scale)
時間戳相關。時間以 64-big/32-bit形式出現。 分子是64-bit的時間值,分母是32-bit的時標(time scale)。它封裝了時間源,其中CMClockGetHostTimeClock()封裝了mach_absolute_time()
時間戳相關。時間以 64-big/32-bit形式出現。CMClock上的控制視圖。提供了時間的映射:CMTimebaseSetTime(timebase, kCMTimeZero); 速率控制:
CMTimebaseSetRate(timebase, 1.0);
編碼後,結果圖像的數據結構
編解碼前後的視頻圖像均封裝在CMSampleBuffer中,如果是編碼後的圖像,以CMBlockBuffe方式存儲;解碼後的圖像,以CVPixelBuffer存儲。
存放編解碼前後的視頻圖像的容器數據結構。如圖所示,編解碼前後的視頻圖像均封裝在CMSampleBuffer中,如果是編碼後的圖像,以CMBlockBuffer方式存儲;解碼後的圖像,以CVPixelBuffer存儲。CMSampleBuffer裡面還有另外的時間信息CMTime和視頻描述信息CMVideoFormatDesc。
實現步驟如下:
需要從H.264的碼流裡面提取出以上的三個信息。最後組合成CMSampleBuffer,提供給硬解碼介面來進行解碼工作。
在H.264的語法中,有一個最基礎的層,叫做Network Abstraction Layer, 簡稱為NAL。H.264流數據正是由一系列的NAL單元(NAL Unit, 簡稱NAUL)組成的。
H264的碼流由NALU單元組成,一個NALU可能包含有:
2)H.264屬性合集-FormatDesc(包含 SPS和PPS),即流數據中,屬性集合可能是這樣的:
經過處理之後,在Format Description中則是:
需要注意的是:
要從基礎的流數據將SPS和PPS轉化為Format Desc中的話,需要調用 () 方法。
3)NALU header
對於流數據來說,一個NAUL的Header中,可能是0x00 00 01或者是0x00 00 00 01作為開頭(兩者都有可能,下面以0x00 00 01作為例子)。0x00 00 01因此被稱為開始碼(Start code).
總結以上知識,我們知道H264的碼流由NALU單元組成,NALU單元包含視頻圖像數據和H264的參數信息。其中視頻圖像數據就是CMBlockBuffer,而H264的參數信息則可以組合成FormatDesc。具體來說參數信息包含SPS(Sequence Parameter Set)和PPS(Picture Parameter Set).如下圖顯示了一個H.264碼流結構:
(實際測試時,加入time信息後,有不穩定的圖像,不加入time信息反而沒有,需要進一步研究,這里建議不加入time信息)
根據上述得到CMVideoFormatDescriptionRef、CMBlockBufferRef和可選的時間信息,使用CMSampleBufferCreate介面得到CMSampleBuffer數據這個待解碼的原始的數據。如下圖所示的H264數據轉換示意圖。
顯示的方式有兩種:
1)、將CMSampleBuffers提供給系統的AVSampleBufferDisplayLayer 直接顯示
使用方式和其它CALayer類似。該層內置了硬體解碼功能,將原始的CMSampleBuffer解碼後的圖像直接顯示在屏幕上面,非常的簡單方便。
2)、利用OPenGL渲染
通過VTDecompression介面來,將CMSampleBuffer解碼成圖像,將圖像通過UIImageView或者OpenGL上顯示。
初始化VTDecompressionSession,設置解碼器的相關信息。初始化信息需要CMSampleBuffer裡面的FormatDescription,以及設置解碼後圖像的存儲方式。demo裡面設置的CGBitmap模式,使用RGB方式存放。編碼後的圖像經過解碼後,會調用一個回調函數,將解碼後的圖像交個這個回調函數來進一步處理。我們就在這個回調裡面,將解碼後的圖像發給control來顯示,初始化的時候要將回調指針作為參數傳給create介面函數。最後使用create介面對session來進行初始化。
上所述的回調函數可以完成CGBitmap圖像轉換成UIImage圖像的處理,將圖像通過隊列發送到Control來進行顯示處理。
調用VTDecompresSessionDecodeFrame介面進行解碼操作。解碼後的圖像會交由以上兩步驟設置的回調函數,來進一步的處理。
攝像頭採集,iOS系統提供了AVCaptureSession來採集攝像頭的圖像數據。設定好session的採集解析度。再設定好input和output即可。output設定的時候,需要設置delegate和輸出隊列。在delegate方法,處理採集好的圖像。
圖像輸出的格式,是未編碼的CMSampleBuffer形式。
1)初始化VTCompressionSession
VTCompressionSession初始化的時候,一般需要給出width寬,height長,編碼器類型kCMVideoCodecType_H264等。然後通過調用VTSessionSetProperty介面設置幀率等屬性,demo裡面提供了一些設置參考,測試的時候發現幾乎沒有什麼影響,可能需要進一步調試。最後需要設定一個回調函數,這個回調是視頻圖像編碼成功後調用。全部准備好後,使用VTCompressionSessionCreate創建session
2)提取攝像頭採集的原始圖像數據給VTCompressionSession來硬編碼
攝像頭採集後的圖像是未編碼的CMSampleBuffer形式,利用給定的介面函數CMSampleBufferGetImageBuffer從中提取出CVPixelBufferRef,使用硬編碼介面來對該幀進行硬編碼,編碼成功後,會自動調用session初始化時設置的回調函數。
3)利用回調函數,將因編碼成功的CMSampleBuffer轉換成H264碼流,通過網路傳播。
相關資料傳送:
iOS8系統H264視頻硬體編解碼說明
簡單談談硬編碼和軟編碼
I,P,B幀和PTS,DTS的關系