注:參考自bilibili系列視頻,從0開始做播放器-第6章-圖像編碼的基礎(chǔ)概念(理論課)https://www.bilibili.com/video/BV1PK41157jz
常見編碼格式
視頻需要編碼,是因為采集來的原始視頻太大,一部720p的電影,存原始圖像就需要大約1T。所以需要編碼,把原始圖像壓縮,便于我們傳輸和存儲。
- H264 誕生于2003年,是目前最常見的編碼方式
- H265 是H264的繼任者,相比H264,H265性能更好,壓縮的更小,但是很耗硬件,很多硬件不支持;H265不能廣泛使用的另一個原因是,H5瀏覽器還不支持H265,主要H265專利費(fèi)比較貴。
- VP8 由 Google 發(fā)布,Youtube和google在用
- VP9 是VP8的繼任者,由 Google 發(fā)布,Youtube和google在用
- AVS(Audio Video coding Standard)國產(chǎn),常見于政府項目,安防領(lǐng)域
- AVS2 是AVS的繼任者,國產(chǎn),常見于政府項目,安防領(lǐng)域
H264
-
SPS 序列參數(shù)集
- profile,定義基礎(chǔ)配置
- 視頻長寬
-
PPS 圖像參數(shù)集
- 碼流中熵編碼/解碼選擇的算法
一般來說,編碼器編出的首幀數(shù)據(jù)為PPS和SPS,接著為I幀(注: 要想解碼一路流,必須先把SPS和PPS傳給解碼器。)(https://zhuanlan.zhihu.com/p/27896239SPS和PPS詳解)
I幀 關(guān)鍵幀,保存整個圖像的信息,自身可以通過視頻解壓算法解壓成一張單獨(dú)的完整的圖片。I幀圖像用于阻止誤差的累積和擴(kuò)散。在閉合式GOP中,每個GOP的第一個幀一定是I幀,且當(dāng)前GOP的數(shù)據(jù)不會參考前后GOP的數(shù)據(jù)。
P幀 前向預(yù)測幀,只記錄本幀與前一幀的差別
B幀 雙向預(yù)測幀,只記錄本幀與前一幀和后一幀的差別;B幀具有更高的壓縮率,但需要更多的緩沖時間以及更高的CPU占用率,因此B幀適合本地存儲以及視頻點(diǎn)播,而不適用對實(shí)時性要求較高的直播系統(tǒng)。
NALU,幀,slice,宏塊之間的關(guān)系
H264原始碼流(裸流)是由一個接一個NALU組成,H264分為兩個層面,VCL(視頻編碼層)和 NAL(網(wǎng)絡(luò)提取層)。
- VCL(video coding)視頻編碼層:負(fù)責(zé)有效表示視頻數(shù)據(jù)的內(nèi)容;
- NAL(network abstraction)網(wǎng)絡(luò)抽象層:負(fù)責(zé)格式化數(shù)據(jù)并提供頭信息,以保證數(shù)據(jù)適合各種信道和存儲介質(zhì)上的傳播。
H264結(jié)構(gòu)中,一個視頻圖像編碼后的數(shù)據(jù)叫做一幀(frame),一幀由一個片(slice)或多個片組成,一個片由一個或多個宏塊(MB)組成,一個宏塊由16x16的yuv數(shù)據(jù)組成。宏塊作為H264編碼的基本單位。
NALU是一種封裝的模組 ,一個Slice編碼之后被打包進(jìn)一個NALU,不過NALU除了容納Slice編碼的碼流外,還可以容納其他數(shù)據(jù),比如序列參數(shù)集SPS。所以nalu不一定是slice。
拓展:
那么為什么要設(shè)置片(slice)呢?
設(shè)置片(slice)的目的是為了限制誤碼的擴(kuò)散和傳輸,應(yīng)使編碼片相互間是獨(dú)立的。某片的預(yù)測不能以其他片中的宏塊為參考圖像,這樣某一片中的預(yù)測誤差才不會傳播到其他片中。
PTS和DTS
PTS:顯示時間戳,表示解碼后的幀顯示的時間
DTS:解碼時間戳,表示送入解碼器的順序
NALU (Network Abstract Layer Unit)
- nalu type 如下圖,常用的是1,5,7,8。
- 1是非IDR幀 有可能是I幀,P幀,B幀
-
5是IDR幀,IDR幀一定是I幀,但I(xiàn)幀不一定是IDR幀。IDR幀前面通常會有SPS和PPS。
IDR幀常用于流媒體,因為存成文件的話,SPS、PPS信息會存在文件頭,只存一次就可以,而流媒體,由于是網(wǎng)絡(luò)流,
1.只發(fā)一次SPS我們無法保證服務(wù)器一定會接收到;
2.就算第一次發(fā)SPS就接收到了,那也需要一直在服務(wù)器緩存;
3.如果直播小姐姐切換了前后攝像頭,SPS和PPS就會變化,如果還用第一次接收到的SPS,就會出錯
所以就需要IDR幀的存在,隔一段時間,就傳一下SPS和PPS。 - 7是SPS 序列參數(shù)集
-
8是PPS 圖像參數(shù)集
image.png
- 獲取nalu type
start code后面一個字節(jié)的低5位,獲取方法:int naluType = nalu[4]0x1f,這里是常犯錯誤的地方。
H264的兩種存儲形態(tài)
Annex B
- startCode NALU 以0001或001開頭
- 防競爭字節(jié) 編碼時,slice數(shù)據(jù)里如果出現(xiàn)000,就插入0x3,這樣,slice里所有的 0001 ,就被轉(zhuǎn)換為 000 0x3 1;解碼時,將slice數(shù)據(jù)中000后面的0x3去掉,就可以還原數(shù)據(jù)。
- 多用于網(wǎng)絡(luò)流媒體中,rtp,rtmp等
AVCC
- 表示NALU長度的前綴,不定長,有時1字節(jié),有時2字節(jié),有時4字節(jié)
- 防競爭字節(jié),同上,將000后面插入0x3,在AVCC中,由于沒有startCode,這個操作對于AVCC格式是沒有實(shí)際意義的,但是要遵從標(biāo)準(zhǔn),所以也這樣做了。遵從標(biāo)準(zhǔn),有助于不同存儲形態(tài)之間轉(zhuǎn)換。
- 多用于文件存儲中,如mp4
GOP
GOP是畫面組,一個GOP是一組連續(xù)的畫面。
GOP結(jié)構(gòu)一般是:
I BBP BBP BBP BB I
增大圖片組能有效的減少編碼后的視頻體積,但是也會降低視頻質(zhì)量。
常見誤區(qū)
- 分辨率越大碼率越大嗎?
不一定。碼率是單位時間內(nèi),傳輸?shù)木幋a后的數(shù)據(jù)位數(shù)。碼率約等于傳輸速率。
碼率由什么決定:
- 分辨率,影響較小
- 畫面混亂程度,單幀圖像,混亂程度越高,同等質(zhì)量下,編碼后的數(shù)據(jù)量越大;圖像越簡單,編碼后的數(shù)據(jù)越小。
- 畫面之間的變化量越大,編碼后的數(shù)據(jù)量越大。
- 編碼(壓縮)程度,畫面混亂程度相等時,壓縮的狠,畫質(zhì)可能不好,但編碼后數(shù)據(jù)會小
- P幀一定比I幀小,B幀一定比P幀小
- P幀不一定比I幀小,當(dāng)場景轉(zhuǎn)換的時候,臨界兩幀,比如前一幀是室內(nèi)簡單場景,是I幀,后一幀是室外復(fù)雜場景,是P幀,P幀存的是與前一幀的變化量,場景轉(zhuǎn)換時,前后兩幀差距太大,P幀數(shù)據(jù)量就會很大。所以P幀不一定比I幀小。
- B幀不一定比P幀小,也是在場景轉(zhuǎn)換的時候,B幀有可能跟前后某幀差別很大,無法參考數(shù)據(jù),于是數(shù)據(jù)量很大。
- 所以說,每類幀類型的使用位置還是很重要的,每一幀給合適的幀類型,才能發(fā)揮好壓縮效果
