H264 NAL層解析
1.引言
H.264的主要目標:
1.高的視訊壓縮比
2.良好的網路親和性
解決方案:
VCL video coding layer 視訊編碼層
NAL network abstraction layer 網路提取層
VCL:核心演算法引擎,塊,巨集塊及片的語法級別的定義
NAL:片級以上的語法級別(如序列引數集和影象引數集),同時支援以下功能:獨立片解碼,起始碼唯一保證,SEI以及流格式編碼資料傳送
VCL設計目標:儘可能地獨立於網路的情況下進行高效的編解碼
NAL設計目標:根據不同的網路把資料打包成相應的格式,將VCL產生的位元字串適配到各種各樣的網路和多元環境中。
NALU頭結構:NALU型別(5bit)、重要性指示位(2bit)、禁止位(1bit)。
NALU型別:1~12由H.264使用,24~31由H.264以外的應用使用。
重要性指示:標誌該NAL單元用於重建時的重要性,值越大,越重要。
禁止位:網路發現NAL單元有位元錯誤時可設定該位元為1,以便接收方丟掉該單元。
2.NAL語法語義
NAL層句法:
在編碼器輸出的碼流中,資料的基本單元是句法元素。
句法表徵句法元素的組織結構。
語義闡述句法元素的具體含義。
分組都有頭部,解碼器可以很方便的檢測出NAL的分界,依次取出NAL進行解碼。
但為了節省碼流,H.264沒有另外在NAL的頭部設立表示起始位置的句法元素。
如果編碼資料是儲存在介質上的,由於NAL是依次緊密相連的,解碼器就無法在資料流中分辨出每個NAL的起始位置和終止位置。
解決方案:在每個NAL前新增起始碼:0X000001
在某些型別的介質上,為了定址的方便,要求資料流在長度上對齊,或某個常數的整數倍。所以在起始碼前新增若干位元組的0來填充。
檢測NAL的開始:
0X000001和0X000000
我們必須考慮當NAL內部出現了0X000001和0X000000
解決方案:
H.264提出了“防止競爭”機制:
0X000000——0X00000300
0X000001——0X00000301
0X000002——0X00000302
0X000003——0X00000303
為此,我們可以知道:
在NAL單元中,下面的三位元組序列不應在任何位元組對齊的位置出現
0X000000
0X000001
0X000002
Forbidden_zero_bit =0;
Nal_ref_idc:表示NAL的優先順序。0~3,取值越大,表示當前NAL越重要,需要優先受到保護。如果當前NAL是屬於參考幀的片,或是序列引數集,或是影象引數集這些重要的單位時,本句法元素必需大於0。
Nal_unit_type:當前NAL 單元的型別
3.H.264的NAL層處理
結構示意圖:
NAL以NALU(NAL unit)為單元來支援編碼資料在基於分組交換技術網路中傳輸。
它定義了符合傳輸層或儲存介質要求的資料格式,同時給出頭資訊,從而提供了視訊編碼和外部世界的介面。
NALU:定義了可用於基於分組和基於位元流系統的基本格式
RTP封裝:只針對基於NAL單元的本地NAL介面。
三種不同的資料形式:
SODB 資料位元串-->最原始的編碼資料
RBSP 原始位元組序列載荷-->在SODB的後面填加了結尾位元(RBSP trailing bits 一個bit“1”)若干位元“0”,以便位元組對齊
EBSP 擴充套件位元組序列載荷-->在RBSP基礎上填加了仿校驗位元組(0X03)它的原因是: 在NALU加到Annexb上時,需要新增每組NALU之前的開始碼StartCodePrefix,如果該NALU對應的slice為一幀的開始則用4位位元組表示,ox00000001,否則用3位位元組表示ox000001.為了使NALU主體中不包括與開始碼相沖突的,在編碼時,每遇到兩個位元組連續為0,就插入一個位元組的0x03。解碼時將0x03去掉。也稱為脫殼操作
處理過程:
1. 將VCL層輸出的SODB封裝成nal_unit, Nal_unit是一個通用封裝格式,可以適用於有序位元組流方式和IP包交換方式。
2. 針對不同的傳送網路(電路交換|包交換),將nal_unit 封裝成針對不同網路的封裝格 式。
第一步的具體過程:
VCL層輸出的位元流SODB(String Of Data Bits),到nal_unit之間,經過了以下三步處理:
1.SODB位元組對齊處理後封裝成RBSP(Raw Byte Sequence Payload)。
2.為防止RBSP的位元組流與有序位元組流傳送方式下的SCP(start_code_prefix_one_3bytes,0x000001)出現位元組競爭情形,迴圈檢測RBSP前三個位元組,在出現位元組競爭時在第三位元組前加入emulation_prevention_three_byte (0x03),具體方法:
nal_unit( NumBytesInNALunit ) {
forbidden_zero_bit
nal_ref_idc
nal_unit_type
NumBytesInRBSP = 0
for( i = 1; i < NumBytesInNALunit; i++ ) {
if( i + 2 < NumBytesInNALunit && next_bits( 24 ) = = 0x000003 ) {
rbsp_byte[ NumBytesInRBSP++ ]
rbsp_byte[ NumBytesInRBSP++ ]
i += 2
emulation_prevention_three_byte /* equal to 0x03 */
} else
rbsp_byte[ NumBytesInRBSP++ ]
}
}
3. 防位元組競爭處理後的RBSP再加一個位元組的header(forbidden_zero_bit+ nal_ref_idc+ nal_unit_type),封裝成nal_unit.
第二步的具體過程:
case1:有序位元組流的封裝
byte_stream_nal_unit( NumBytesInNALunit ) {
while( next_bits( 24 ) != 0x000001 )
zero_byte /* equal to 0x00 */
if( more_data_in_byte_stream( ) ) {
start_code_prefix_one_3bytes /* equal to 0x000001 */ nal_unit( NumBytesInNALunit )
}
}
類似H.320和MPEG-2/H.222.0等傳輸系統,傳輸NAL作為有序連續位元組或位元流,同時要依靠資料本身識別NAL單元邊界。在這樣的應用系統中,H.264/AVC規範定義了位元組流格式,每個NAL單元前面增加3個位元組的字首,即同步位元組。在位元流應用中,每個影象需要增加一個附加位元組作為邊界定位。還有一種可選特性,在位元組流中增加附加資料,用做擴充傳送資料量,能實現快速邊界定位,恢復同步
Case2:IP網路的RTP打包封裝
分組打包的規則
(1)額外開銷要少,使MTU尺寸在100~64k位元組範圍都可以;
(2)不用對分組內的資料解碼就可以判別該分組的重要性;
(3)載荷規範應當保證不用解碼就可識別由於其他的位元丟失而造成的分組不可解碼;
(4)支援將NALU分割成多個RTP分組;
(5)支援將多個NALU彙集在一個RTP分組中。
RTP的頭標可以是NALU的頭標,並可以實現以上的打包規則。
一個RTP分組裡放入一個NALU,將NALU(包括同時作為載荷頭標的NALU頭)放入RTP的載荷中,設定RTP頭標值。為了避免IP層對大分組的再一次分割,片分組的大小一般都要小於MTU尺寸。由於包傳送的路徑不同,解碼端要重新對片分組排序,RTP包含的次序資訊可以用來解決這一問題。
NALU分割
對於預先已經編碼的內容,NALU可能大於MTU尺寸的限制。雖然IP層的分割可以使資料塊小於64千位元組,但無法在應用層實現保護,從而降低了非等重保護方案的效果。由於UDP資料包小於64千位元組,而且一個片的長度對某些應用場合來說太小,所以應用層打包是RTP打包方案的一部分。
新的討論方案(IETF)應當符合以下特徵:
(1)NALU的分塊以按RTP次序號升序傳輸;
(2)能夠標記第一個和最後一個NALU分塊;
(3)可以檢測丟失的分塊。
NALU合併
一些NALU如SEI、引數集等非常小,將它們合併在一起有利於減少頭標開銷。已有兩種集合分組:
(1)單一時間集合分組(STAP),按時間戳進行組合;
(2)多時間集合分組(MTAP),不同時間戳也可以組合。
NAL規範視訊資料的格式,主要是提供頭部資訊,以適合各種媒體的傳輸和儲存。NAL支援各種網路,包括:
1.任何使用RTP/IP協議的實時有線和無線Internet 服務
2.作為MP4檔案儲存和多媒體資訊檔案服務
3.MPEG-2系統
4.其它網
NAL規定一種通用的格式,既適合面向包傳輸,也適合流傳送。實際上,包傳輸和流傳輸的方式是相同的,不同之處是傳輸前面增加了一個起始碼字首
在類似Internet/RTP面向包傳送協議系統中,包結構中包含包邊界識別位元組,在這種情況下,不需要同步位元組。
NAL單元分為VCL和非VCL兩種
VCL NAL單元包含視訊影象取樣資訊,
非VCL包含各種有關的附加資訊,例如引數集(頭部資訊,應用到大量的VCL NAL單元)、提高效能的附加資訊、定時資訊等
引數集:
引數集是很少變化的資訊,用於大量VCL NAL單元的解碼,分為兩種型別:
1.序列引數集,作用於一串連續的視訊影象,即視訊序列。
兩個IDR影象之間為序列引數集。IDR和I幀的區別見下面。
2. 影象引數集,作用於視訊序列中的一個或多個個別的影象
序列和影象引數集機制,減少了重複引數的傳送,每個VCL NAL單元包含一個標識,指
向有關的影象引數集,每個影象引數集包含一個標識,指向有關的序列引數集的內容
因此,只用少數的指標資訊,引用大量的引數,大大減少每個VCL NAL單元重複傳送的資訊。
序列和影象引數集可以在傳送VCL NAL單元以前傳送,並且重複傳送,大大提高糾錯能力。序列和影象引數集可以在“帶內”,也可以用更為可靠的其他“帶外”通道傳送。
儲存單元:
一組指定格式的NAL單元稱為儲存單元,每個儲存單元對應一個影象。每個儲存單元包含一組VCL NAL單元,組成一個主編碼影象,VCL NAL單元由表示視訊影象取樣的像條所組成。儲存單元前面可以加一個字首,分界儲存單元,附加增強資訊(SEI)(如影象定時資訊)也可以放在主編碼影象的前面。主編碼影象後附加的VCL NAL單元,包含同一影象的冗餘表示,稱為冗餘編碼影象,當主編碼影象資料丟失或損壞時,可用冗餘編碼影象解碼。
編碼視訊序列
一個編碼視訊序列由一串連續的儲存單元組成,使用同一序列引數集。每個視訊序列可獨立解碼。編碼序列的開始是即時重新整理儲存單元(IDR)。IDR是一個I幀影象,表示後面的影象不用參考以前的影象。一個NAL單元流可包含一個或更多的編碼視訊序列。
RTP協議:
實時傳輸協議(Real-time Transport Protocol,RTP)是在Internet上處理多媒體資料流的一種網路協議,利用它能夠在一對一(單播)或者一對多(multicast,多播)的網路環境中實現傳流媒體資料的實時傳輸。RTP通常使用UDP來進行多媒體資料的傳輸,但如果需要的話可以使用TCP或者ATM等其它協議,整個RTP協議由兩個密切相關的部分組成:RTP資料協議和RTP控制協議。實時流協議(Real Time Streaming Protocol, RTSP)最早由Real Networks和Netscape公司共同提出,它位於RTP和RTCP之上,其目的是希望通過IP網路有效地傳輸多媒體資料。
RTP資料協議
RTP資料協議負責對流媒體資料進行封包並實現媒體流的實時傳輸,每一個RTP資料包都由頭部(Header)和負載(Payload)兩個部分組成,其中頭部前12個位元組的含義是固定的,而負載則可以是音訊或者視訊資料。RTP資料包的頭部格式如圖1所示:
其中比較重要的幾個域及其意義如下:
CSRC記數(CC) 表示CSRC標識的數目。CSRC標識緊跟在RTP固定頭部之後,用來表示RTP資料包的來源,RTP協議允許在同一個會話中存在多個資料來源,它們可以通過RTP混合器合併為一個資料來源。例如,可以產生一個CSRC列表來表示一個電話會議,該會議通過一個RTP混合器將所有講話者的語音資料組合為一個RTP資料來源。
負載型別(PT) 標明RTP負載的格式,包括所採用的編碼演算法、取樣頻率、承載通道等。例如,型別2表明該RTP資料包中承載的是用ITU G.721演算法編碼的語音資料,取樣頻率為8000Hz,並且採用單聲道。
序列號 用來為接收方提供探測資料丟失的方法,但如何處理丟失的資料則是應用程式自己的事情,RTP協議本身並不負責資料的重傳。
時間戳 記錄了負載中第一個位元組的取樣時間,接收方能夠時間戳能夠確定資料的到達是否受到了延遲抖動的影響,但具體如何來補償延遲抖動則是應用程式自己的事情。從RTP資料包的格式不難看出,它包含了傳輸媒體的型別、格式、序列號、時間戳以及是否有附加資料等資訊,這些都為實時的流媒體傳輸提供了相應的基礎。RTP協議的目的是提供實時資料(如互動式的音訊和視訊)的端到端傳輸服務,因此在RTP中沒有連線的概念,它可以建立在底層的面向連線或面向非連線的傳輸協議之上;RTP也不依賴於特別的網路地址格式,而僅僅只需要底層傳輸協議支援組幀(Framing)和分段(Segmentation)就足夠了;另外RTP本身還不提供任何可靠性機制,這些都要由傳輸協議或者應用程式自己來保證。在典型的應用場合下,RTP一般是在傳輸協議之上作為應用程式的一部分加以實現的,如圖2所示:
RTCP控制協議
RTCP控制協議需要與RTP資料協議一起配合使用,當應用程式啟動一個RTP會話時將同時佔用兩個埠,分別供RTP和RTCP使用。RTP本身並不能為按序傳輸資料包提供可靠的保證,也不提供流量控制和擁塞控制,這些都由RTCP來負責完成。通常RTCP會採用與RTP相同的分發機制,向會話中的所有成員週期性地傳送控制資訊,應用程式通過接收這些資料,從中獲取會話參與者的相關資料,以及網路狀況、分組丟失概率等反饋資訊,從而能夠對服務質量進行控制或者對網路狀況進行診斷。
RTCP協議的功能是通過不同的RTCP資料包來實現的,主要有如下幾種型別:
SR 傳送端報告,所謂傳送端是指發出RTP資料包的應用程式或者終端,傳送端同時也可以是接收端。
RR 接收端報告,所謂接收端是指僅接收但不傳送RTP資料包的應用程式或者終端。
SDES 源描述,主要功能是作為會話成員有關標識資訊的載體,如使用者名稱、郵件地址、電話號碼等,此外還具有向會話成員傳達會話控制資訊的功能。
BYE 通知離開,主要功能是指示某一個或者幾個源不再有效,即通知會話中的其他成員自己將退出會話。
APP 由應用程式自己定義,解決了RTCP的擴充套件性問題,並且為協議的實現者提供了很大的靈活性。
RTCP資料包攜帶有服務質量監控的必要資訊,能夠對服務質量進行動態的調整,並能夠對網路擁塞進行有效的控制。由於RTCP資料包採用的是多播方式,因此會話中的所有成員都可以通過RTCP資料包返回的控制資訊,來了解其他參與者的當前情況。
在一個典型的應用場合下,傳送媒體流的應用程式將週期性地產生髮送端報告SR,該RTCP資料包含有不同媒體流間的同步資訊,以及已經傳送的資料包和位元組的計數,接收端根據這些資訊可以估計出實際的資料傳輸速率。另一方面,接收端會向所有已知的傳送端傳送接收端報告RR,該RTCP資料包含有已接收資料包的最大序列號、丟失的資料包數目、延時抖動和時間戳等重要資訊,傳送端應用根據這些資訊可以估計出往返時延,並且可以根據資料包丟失概率和時延抖動情況動態調整傳送速率,以改善網路擁塞狀況,或者根據網路狀況平滑地調整應用程式的服務質量。
RTSP實時流協議
作為一個應用層協議,RTSP提供了一個可供擴充套件的框架,它的意義在於使得實時流媒體資料的受控和點播變得可能。總的說來,RTSP是一個流媒體表示協議,主要用來控制具有實時特性的資料傳送,但它本身並不傳輸資料,而是必須依賴於下層傳輸協議所提供的某些服務。RTSP可以對流媒體提供諸如播放、暫停、快進等操作,它負責定義具體的控制訊息、操作方法、狀態碼等,此外還描述了與RTP間的互動操作。
RTSP在制定時較多地參考了HTTP/1.1協議,甚至許多描述與HTTP/1.1完全相同。RTSP之所以特意使用與HTTP/1.1類似的語法和操作,在很大程度上是為了相容現有的Web基礎結構,正因如此,HTTP/1.1的擴充套件機制大都可以直接引入到RTSP中。
由RTSP控制的媒體流集合可以用表示描述(Presentation Description)來定義,所謂表示是指流媒體伺服器提供給客戶機的一個或者多個媒體流的集合,而表示描述則包含了一個表示中各個媒體流的相關資訊,如資料編碼/解碼演算法、網路地址、媒體流的內容等。
雖然RTSP伺服器同樣也使用識別符號來區別每一流連線會話(Session),但RTSP連線並沒有被繫結到傳輸層連線(如TCP等),也就是說在整個RTSP連線期間,RTSP使用者可開啟或者關閉多個對RTSP伺服器的可靠傳輸連線以發出RTSP 請求。此外,RTSP連線也可以基於面向無連線的傳輸協議(如UDP等)。
RTSP協議目前支援以下操作:
檢索媒體 允許使用者通過HTTP或者其它方法向媒體伺服器提交一個表示描述。如表示是組播的,則表示描述就包含用於該媒體流的組播地址和埠號;如果表示是單播的, 為了安全在表示描述中應該只提供目的地址。
邀請加入 媒體伺服器可以被邀請參加正在進行的會議,或者在表示中回放媒體,或者在表示中錄製全部媒體或其子集,非常適合於分散式教學。
新增媒體 通知使用者新加入的可利用媒體流,這對現場講座來講顯得尤其有用。與HTTP/1.1類似,RTSP請求也可以交由代理、通道或者快取來進行處理。
3. JM86中的處理
涉及的函式:
流程圖:
I幀和IDR幀的區別:
1. 在 H.264 中 I 幀並不具有隨機訪問的能力,這個功能由 IDR 承擔。以前的標準中由 I 幀承擔。
2. IDR 會導致 DPB (參考幀列表——這是關鍵所在)清空,而 I 不會。
3. I和IDR幀其實都是I幀,都是使用幀內預測的。但是IDR幀的作用是立刻重新整理,使錯誤不致傳播,從IDR幀開始,重新算一個新的序列開始編碼。
4. IDR影象一定是I影象,但I影象不一定是IDR影象。一個序列中可以有很多的I影象,I影象之後的影象可以引用I影象之間的影象做運動參考。
相關文章
- 三層交換技術解析
- Spring IOC 原理深層解析Spring
- 全連線層的作用解析
- 深度解析HashMap集合底層原理HashMap
- ThreadLocal底層原始碼解析thread原始碼
- Zigbee解析: NWK層作用
- h264 Nalu 詳解
- 持久層Mybatis3底層原始碼分析,原理解析MyBatisS3原始碼
- Promise的分層解析及實現Promise
- 解析ArrayList的底層實現(上)
- AIDL 跨程式呼叫 -- 介面層解析AI
- 三層交換機技術解析(轉)
- JavaCV FFmpeg H264編碼Java
- H264 Profile對比分析
- H264基本原理
- 面試題深入解析:Synchronized底層實現面試題synchronized
- 深入解析 Go 中 Slice 底層實現Go
- 深度解析HashMap底層實現架構HashMap架構
- DNS分層結構及DNS解析流程DNS
- iptables深入解析:應用層外掛篇
- 讀取xml檔案 解析雙層xmlXML
- 原始碼解析:網路層 YTKNetwork原始碼
- Vector底層結構和程式碼解析
- RTSP H264/HEVC 流 Wasm 播放ASM
- ffmpeg提取H264影片資料
- 9_深入解析Oracle rdba結構及os層rdba解析工具分享Oracle
- Java 嵌入指令碼快速解析多層 jsonJava指令碼JSON
- 深入解析CSS樣式層疊權重值CSS
- HashMap底層資料結構原始碼解析HashMap資料結構原始碼
- SpringBoot自定義控制層引數解析Spring Boot
- DG的ASYNC與SYNC深層原理解析
- 10_深入解析Oracle number資料型別及os層number解析工具分享Oracle資料型別
- [H264]解密純264檔案格式解密
- 將H264碼流打包成RTP包
- Android 事件分發機制原始碼解析-view層Android事件原始碼View
- Java集合類,從原始碼解析底層實現原理Java原始碼
- Java中 i=i++ 問題底層原理解析Java
- git plumbing 更加底層命令解析-深入理解GITGit