單純傳輸視頻畫面,視頻量很是大,對現有的網絡和存儲來講是不可接受的。html
爲了可以使視頻便於傳輸和存儲,人們發現視頻有大量重複的信息,若是將重複信息在發送端去掉,在接收端恢復出來,這樣就大大減小了視頻數據的文件,所以有了H.264視頻壓縮標準。算法
又稱爲關鍵幀或者幀內編碼幀,採用幀內壓縮技術。緩存
是一種自帶所有信息的獨立幀,無需參考其餘圖像即可獨立進行解碼,能夠簡單理解爲一張靜態畫面。視頻序列中的第一個幀始終都是I幀,由於它是關鍵幀。bash
又稱爲
向前參考幀
或幀間預測編碼幀
,採用幀間壓縮技術。網絡
除了I幀
以外的全部幀,所有向前依賴。性能
全部幀都只保存與前一幀的差別,以達到高壓縮率的效果。編碼
解碼時須要用以前緩存的畫面疊加上本幀定義的差異,生成最終畫面。spa
又稱爲刷
雙向參考幀
,屬於幀間壓縮技術。.net
即參考前一幀,也參考後一幀。以達到比P幀
更高的壓縮效果。3d
也就是說要解碼B幀,不只要取得以前的緩存畫面,還要解碼以後的畫面,經過先後畫面的與本幀數據的疊加取得最終的畫面。對於直播業務,B幀比P幀永遠要慢一點。
B幀壓縮率高,可是對解碼性能要求較高。
I幀只需考慮本幀
P幀記錄的是與前一幀的差異
B幀記錄的是前一幀及後一幀的差異
能節約更多的空間,視頻文件小了,但相對來講解碼的時候就比較麻煩。
由於在解碼時,不只要用以前緩存的畫面,並且要知道下一個I或者P的畫面,對於不支持B幀解碼的播放器容易卡頓。
複製代碼
視頻監控系統中預覽的視頻畫面是實時的,對畫面的流暢性要求較高。採用I幀、P幀進行視頻傳輸能夠提升網絡的適應能力,且能下降解碼成本因此現階段的視頻解碼都只採用I幀和P幀進行傳輸。
Group of Pictures 一組幀
類似畫面的一組幀
以下圖所示,兩個I幀
之間的全部幀,叫作一組幀。
具體的劃分細節,在下面《幀分組》的部分會提到
序列參數集 Sequence Parameter Set
包含一組幀中:存放幀數、參考幀數目、解碼圖像尺寸、幀場編碼模式選擇標識等
圖像參數集 Picture Parameter Set
包含一組幀中:存放熵編碼選擇模式標識、片組數目、初始量化參數和去方塊過濾波係數調整標識等
在一組幀中,SPS與PPS也屬於I幀。
當一組幀中丟失了某一幀,就會形成某個部分沒有完成更新。形成花屏。
爲了不花屏的問題,當發現I幀或P幀丟失,則不現實本GOP中全部的內容。知道下一個I幀到達後從新刷新圖像。
x264是目前使用最普遍的H264編解碼器(主要用來編碼,解碼用ffmpeg)。 x265的壓縮率比x264更高,性能的消耗也更大。
相對x264性能較低,但支持SVC技術。
SVC能夠將視頻分層傳輸:
能夠對用戶帶寬進行不一樣策略的定製方案:將一幀數據分爲小、中、大三個部分,根據對方網絡狀況分別追加發送。
接收到的部分越多,最後組合起來的視頻就越清晰。
但因爲不少手機不支持SVC編碼,因此須要使用軟編處理,會對CPU產生損耗。
Google出品,分別對應x264/x265
這部分最後發現李超老師本身已經寫過博客了,建議去看原文
解決空域數據的冗餘問題
空域數據,相似音頻中的超聲波段,不容易甚至不會被人類注意識別。
解決時域數據的冗餘問題
時域數據,對於監控之類靜止不動的畫面,對幀與幀之間重複的數據進行計算壓縮。
將空間上的相關性變爲頻域上無關的數據而後進行量化
相似哈夫曼無損編碼
對於一段視頻,首先會被送到 H264 編碼器的緩衝區中,併爲每一幀圖片進行宏塊的劃分
H264默認是使用 16X16 大小的區域做爲一個宏塊,也能夠劃分紅 8X8 大小。
對宏塊中的每個像素點進行計算
對於複雜的圖片或局部,H264能夠對宏塊進行更細緻的劃分以達到更高的壓縮率,好比8X16、 16X8、 8X8、 4X8、 8X4、 4X4
宏塊劃分好後,還須要對編碼器緩存中全部的圖片進行分組(GOP)
幀間預測壓縮
主要在這裏解決時域數據的冗餘問題
:
對於某些關聯特別密切的幀,其實咱們只須要保存一幀的數據,其它幀均可以經過這一幀再按某種規則預測出來,因此說視頻數據在時間上的冗餘是最多的。
如何斷定兩幀處在一個GOP中?以一個的檯球桌的視頻爲例:
H264編碼器會按順序,每次取出兩幅相鄰的幀進行宏塊比較,計算兩幀的類似度。以下圖:
其算法是:在相鄰幾幅圖像畫面中,通常有差異的像素只有10%之內的點,亮度差值變化不超過2%,而色度差值的變化只有1%之內,咱們認爲這樣的圖能夠分到一組。
也叫
運動估計與補償
,用於壓縮時間層面的冗餘,清除相同數據。
對於一組幀,須要計算運動物體的運動矢量:
H264編碼器首先按順序從緩衝區頭部取出兩幀視頻數據,而後進行宏塊掃描。當發現其中一幅圖片中有物體時,就在另外一幅圖的鄰近位置(搜索窗口中)進行搜索。若是此時在另外一幅圖中找到該物體,那麼就能夠計算出物體的運動矢量了。
下面這幅圖就是搜索後的檯球移動的位置
H264依次把每一幀中球移動的距離和方向都記錄下來就成了下面的樣子
運動矢量計算出來後,將相同部分(也就是綠色部分)減去,就獲得了補償數據。咱們最終只須要將補償數據進行壓縮保存,之後在解碼時就能夠恢復原圖了。壓縮補償後的數據只須要記錄不多的一點數據。以下所示
人眼對圖象都有一個識別度,對低頻的亮度很敏感,對高頻的亮度不太敏感。因此基於一些研究,能夠將一幅圖像中人眼不敏感的數據去除掉。這樣就提出了幀內預測技術。
H264的幀內壓縮與JPEG很類似。一幅圖像被劃分好宏塊後,對每一個宏塊能夠進行 9 種預測模式
。找出與原圖最接近的一種預測模式。幀內預測後的圖像與原始圖像的對好比下:
將預測圖像與原圖像對比獲得殘差值
,解碼時根據記錄下來的預測模式
與殘差值
,便可還原出本來的圖像。
能夠將
殘差值
作整數離散餘弦變換
,去掉數據的相關性,進一步壓縮數據。
好比:
壓縮後變成
根據信息出現的頻率,對總體進行壓縮
參考哈夫曼編碼:對高頻信息使用短碼,而低頻信息使用長碼進行壓縮。
MPEG-2
中使用的VLC
就是這種算法
而在H264中,使用CABAC
進行壓縮,不僅對頻率進行壓縮,還根據上下文進行進一步壓縮
對於視頻幀,在有了上下文以後,剩下的幀會進一步壓縮
從大到小,H264的視頻結構以下所示 視頻流 => N個視頻幀 => N個切片 => 切片頭+N個宏塊 => N個子塊
網絡抽象層 以太網單個數據包限制爲1500字節,NAL能夠將單幀數據進行拆包與組包處理,以進行傳輸。
視頻編碼層 對視頻的原始數據進行壓縮
原始數據比特流
由NAL層產生。長度不必定是8字節的倍數
爲
SODB
末尾補1,而後補零成8位。
起始標記的格式化
在
EBSP
前加一個1B的網絡頭
NALU 頭部信息,由三部分構成
對於Type(nal_unit_type):
1, 2, 3, 4, 5及12的NAL單元稱爲VCL的NAL單元,其餘類型的NAL單元爲非VCL的NAL單元。
0:未規定
1:非IDR圖像中不採用數據劃分的片斷
2:非IDR圖像中A類數據劃分片斷
3:非IDR圖像中B類數據劃分片斷
4:非IDR圖像中C類數據劃分片斷
5:IDR圖像的片斷
IDR幀屬於I幀,此位置表明關鍵幀的一部分
6:補充加強信息 (SEI)
7:序列參數集/SPS
8:集圖像參數/PPS
SPS和PPS都是特殊的NALU。一個MP4文件只有一個SPS,可是有不少PPS,SPS必須在全部NALU的最開頭。
9:分割符
10:序列結束符
11:流結束符
12:填充數據
13 – 23:保留
24 – 31:未規定 (2七、28表示爲分片NALU)
複製代碼
一個RTP數據包中只包含一個NALU(切片)
不少P幀、B幀都是單一類型
一個RTP數據包中包含多個NALU
好比SPS、PPS一般就會放在同一個RTP數據包內進行發送
一個NALU被分片成多個RTP數據包發送
紅、綠、藍。每一個元素1字節,共24位
從電視系統中衍生出來的一套顏色編碼方式
明亮度(灰階值)。基礎信號,非黑即白
色彩和飽和度。用於指定像素顏色
YUV常見格式能夠參閱:YUV格式介紹
其中最多見的是YUV 4:2:0
,相對RGB 8:8:8
的格式,節省了不少空間。
YUV 4:2:0
並不意味着沒有V份量,而是隻在相鄰的分行掃描中一行採用YUV 4:2:0
,下一行採用YUV 4:0:2
這種抽樣存儲。
能夠參閱視頻存儲格式YUV420 NV12 NV21 i420 YV12