1. H264編碼分層
- NAL層:(Network Abstraction Layer,視頻數(shù)據(jù)網(wǎng)絡(luò)抽象層): 它的作用是H264只要在網(wǎng)絡(luò)上傳輸,在傳輸?shù)倪^(guò)程每個(gè)包以太網(wǎng)是1500字節(jié),而H264的幀往往會(huì)大于1500字節(jié),所以要進(jìn)行拆包,將一個(gè)幀拆成多個(gè)包進(jìn)行傳輸,所有的拆包或者組包都是通過(guò)NAL層去處理的。
- VCL層:(Video Coding Layer,視頻數(shù)據(jù)編碼層): 對(duì)視頻原始數(shù)據(jù)進(jìn)行壓縮
?我們可以看到視頻幀序列每一幀圖像是由slice構(gòu)成的,每一個(gè)slice是由多個(gè)宏塊構(gòu)成的,在實(shí)際傳輸?shù)倪^(guò)程中,一般一幀圖像就是一個(gè)slice,沒有分那么細(xì)。
NAL單元的結(jié)構(gòu)組成
- ?SODB:(String of Data Bits,原始數(shù)據(jù)比特流):由VCL層產(chǎn)生,數(shù)據(jù)長(zhǎng)度不一定是8的倍數(shù),所以處理起來(lái)比較麻煩
- RBSP:(Raw Byte Sequence Payload,SODB+trailing bits,編碼后的數(shù)據(jù)流):算法是在SODB最后一位補(bǔ)1,不按字節(jié)對(duì)齊補(bǔ)0,如果補(bǔ)齊0,不知道在哪里結(jié)束,所以補(bǔ)1,如果不夠8位則按位補(bǔ)0
- EBSP:(Encapsulate Byte Sequence Payload):生成編碼后的數(shù)據(jù)流之后,我們還要在每個(gè)幀之前加一個(gè)起始位,需要開發(fā)者人為添加。起始位一般是十六進(jìn)制的0001。但是在整個(gè)編碼后的數(shù)據(jù)里,可能會(huì)出來(lái)連續(xù)的2個(gè)0x00。那這樣就與起始位產(chǎn)生了沖突.那怎么處理了? H264規(guī)范里說(shuō)明如果處理2個(gè)連續(xù)的0x00,就額外增加一個(gè)0x03 。這樣就能預(yù)防壓縮后的數(shù)據(jù)與起始位產(chǎn)生沖突? 【EBSP 其實(shí)就是 RBSP 前面增加起始位】
-
NALU: (NAL Header(1B)+EBSP).NALU就是在EBSP的基礎(chǔ)上加1B的網(wǎng)絡(luò)頭.
?
Slice 宏塊分層:
在上述的VCL層中,切片與宏塊劃分的具體情況如下,對(duì)于slice是由header和data組成,data中由很多的宏塊(MacroBlock)組成,在宏塊中存儲(chǔ)的包括宏塊的類型 mb_type,宏塊的預(yù)測(cè)值mb_pred 和殘差值 codec residual
?實(shí)際上H264碼流包含了兩種格式,Annexb和RTP格式的。整體碼流結(jié)構(gòu)為如下形式:
在文件中保存的,每一個(gè)NAL單元前面都有一個(gè)startcode,00開頭的起始碼,這樣由Startcode和NAL單元構(gòu)成的就是Annexb格式。
在網(wǎng)上傳輸,不包含startcode,直接傳輸NAL單元叫RTP碼流。
H264 原始碼流的組成
2、碼流總體結(jié)構(gòu):
h264的功能分為兩層,視頻編碼層(VCL)和網(wǎng)絡(luò)提取層(NAL)。H.264 的編碼視頻序列包括一系列的NAL 單元,每個(gè)NAL 單元包含一個(gè)RBSP。一個(gè)原始的H.264 NALU 單元常由 [StartCode] [NALU Header] [NALU Payload] 三部分組成,其中 Start Code 用于標(biāo)示這是一個(gè)NALU 單元的開始,必須是"00 00 00 01" 或"00 00 01"。
?
NAL 頭部編碼是表示 RBSP 的信息,有 12 種
NAL Header頭部編碼格式:
占一個(gè)字節(jié),8 位,由三部分組成forbidden_bit(1bit),nal_reference_bit(2bits)(優(yōu)先級(jí)),nal_unit_type(5bits)(類型)。
forbidden_bit:禁止位。
nal_reference_bit:當(dāng)前NAL的優(yōu)先級(jí),值越大,該NAL越重要。
nal_unit_type :NAL類型
?如下例子:
IDR幀(關(guān)鍵幀)
- IDR(Instantaneous Decoding Refresh)即時(shí)解碼刷新。 在編碼解碼中為了方便,將GOP中首個(gè)I幀要和其他I幀區(qū)別開,把第一個(gè)I幀叫IDR,這樣方便控制編碼和解碼流程,所以IDR幀一定是I幀,但I(xiàn)幀不一定是IDR幀;IDR幀的作用是立刻刷新,使錯(cuò)誤不致傳播,從IDR幀開始算新的序列開始編碼。I幀有被跨幀參考的可能,IDR不會(huì)。
- I幀不用參考任何幀,但是之后的P幀和B幀是有可能參考這個(gè)I幀之前的幀的。IDR就不允許這樣,例如:
- 其核?作?是,是為了解碼的重同步,當(dāng)解碼器解碼到 IDR 圖像時(shí),?即將參考幀隊(duì)列清空,將已解碼的數(shù)據(jù)全部輸出或拋棄,重新查找參數(shù)集,開始?個(gè)新的序列。這樣,如果前?個(gè)序列出現(xiàn)重?錯(cuò)誤,在這?可以獲得重新同步的機(jī)會(huì)。IDR圖像之后的圖像永遠(yuǎn)不會(huì)使?IDR之前的圖像的數(shù)據(jù)來(lái)解碼。
?
IDR 關(guān)鍵幀的核?作?是,是為了解碼的重同步,當(dāng)解碼器解碼到 IDR 圖像時(shí),?即將參考幀隊(duì)列清空,將已解碼的數(shù)據(jù)全部輸出或拋棄,重新查找參數(shù)集,開始?個(gè)新的序列。這樣,如果前?個(gè)序列出現(xiàn)重?錯(cuò)誤,在這?可以獲得重新同步的機(jī)會(huì)。IDR圖像之后的圖像永遠(yuǎn)不會(huì)使?IDR之前的圖像的數(shù)據(jù)來(lái)解碼。
?如何定義 IBP幀和數(shù)據(jù)傳輸
- 分組,也就是將一系列變換不大的圖像歸為一個(gè)組,也就是一個(gè)序列,也可以叫GOP(畫面組);
- 定義幀,將每組的圖像幀歸分為I幀、P幀和B幀三種類型;
- 預(yù)測(cè)幀, 以I幀做為基礎(chǔ)幀,以I幀預(yù)測(cè)P幀,再由I幀和P幀預(yù)測(cè)B幀;
- 數(shù)據(jù)傳輸, 最后將I幀數(shù)據(jù)與預(yù)測(cè)的差值信息進(jìn)行存儲(chǔ)和傳輸?!?span style="color:#fe2c24;">這里是以預(yù)測(cè)的差值作為存儲(chǔ)】
從圖中我們需要得到一個(gè)概念,H264碼流是由一個(gè)個(gè)的NAL單元組成,其中SPS、PPS、IDR和SLICE是NAL單元某一類型的數(shù)據(jù)。【由NAL 頭部單元去定義的】
SPS 和 PPS
- SPS(Sequence Parameter Set:序列參數(shù)集)包含一些通用的參數(shù),比如Profile和Level,比如視頻幀的尺寸,參考幀的最大數(shù)量等,這些參數(shù)對(duì)整個(gè)Video Sequence或者Programme都是通用的。
- PPS(Picture Parameter Set:圖像參數(shù)集)包含一些通用的參數(shù),比如熵編碼類型,有效的參考圖像的數(shù)目和初始化參數(shù)等,這些參數(shù)可以應(yīng)用到一個(gè)Video Sequence或者一部分編碼幀。
1. SPS?序列參數(shù)集
H264碼流中SPS PPS詳解 - 知乎
H.264基礎(chǔ)知識(shí)及視頻碼流解析_娃哈哈、的博客-CSDN博客
H264 獲取SPS與PPS(附源碼)_似乎已不再年輕的博客-CSDN博客
2. PPS?圖像參數(shù)集
H264碼流解析_瓜瓜是橘貓的博客-CSDN博客_h264碼流解析
H264碼流結(jié)構(gòu)分析_chenchong_219的博客-CSDN博客_h264碼流
指數(shù)哥倫布編碼格式
指數(shù)哥倫布編碼格式是熵編碼的一種。熵編碼包括的編碼方法有:香農(nóng)-范諾編碼、哈夫曼編碼、算術(shù)編碼、指數(shù)哥倫布編碼、CAVLC、CABAC等。具體實(shí)施起來(lái)就是,對(duì)出現(xiàn)概率較大的符號(hào),取較短的碼長(zhǎng),而對(duì)出現(xiàn)概率較小的符號(hào)取較大的碼長(zhǎng)。這就是熵編碼的中心思想
在計(jì)算機(jī)中,一般數(shù)字的編碼都為二進(jìn)制,但是由于以相等長(zhǎng)度來(lái)記錄不同數(shù)字,因此會(huì)出現(xiàn)很多的冗余信息,如下:
如數(shù)字1,原本只需要1個(gè)bit就能表示的數(shù)據(jù),如今需要8個(gè)bit來(lái)表示,那么其余7個(gè)bit就可以看做是冗余數(shù)據(jù),
在網(wǎng)絡(luò)傳輸時(shí),如果以原本等長(zhǎng)的編碼方式來(lái)傳輸數(shù)據(jù),則會(huì)出現(xiàn)很大的冗余量,加重網(wǎng)絡(luò)負(fù)擔(dān),但是如果只用有效字節(jié)來(lái)傳輸上述碼流,則會(huì)是:10110011111111101,這樣根本不能分離出原本的數(shù)據(jù),哥倫布編碼則是作為一種壓縮編碼算法,能很有效地對(duì)原本的數(shù)據(jù)進(jìn)行壓縮,并且能很容易地把編碼后的碼流分離成碼字。
編碼器
?解碼器
?H.264中定義的指數(shù)哥倫布編碼共分四類:
無(wú)符號(hào)指數(shù)哥倫布熵編碼 示例:
1. 編碼過(guò)程:
a、將待編碼的數(shù)加1轉(zhuǎn)換為最小的二進(jìn)制序列(假設(shè)一共M位);
b、此二進(jìn)制序列前面補(bǔ)充M-1個(gè)0;
示例:
對(duì) 4 進(jìn)行無(wú)符號(hào)指數(shù)哥倫布熵編碼
1、將4加1(為5)轉(zhuǎn)換為最小的二進(jìn)制序列即 101 (此是M=3)
2、此二進(jìn)制序列前面補(bǔ)充M-1個(gè)0:即2個(gè)0
3、得出的4的無(wú)符號(hào)指數(shù)哥倫布熵編碼的序列為 00101
2. 解碼過(guò)程:
1、獲取二進(jìn)制序列開頭連續(xù)的N個(gè)0
2、讀取之后的N+1位的值,假設(shè)為X
3、X-1獲取解碼后的值
示例:
如對(duì) 00101進(jìn)行無(wú)符號(hào)指數(shù)哥倫布熵解碼
1、獲取開頭連續(xù)的N個(gè)0, 此時(shí)N = 2
2、再向后讀取N+1位的值,即 101,為5
3、 5 - 1 =4 獲取其解碼后碼值文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-430658.html
H264 指數(shù)哥倫布編碼_szfhy的博客-CSDN博客文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-430658.html
到了這里,關(guān)于【FFmpeg學(xué)習(xí)】H264 視頻碼流分析的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!