H264---封裝格式:字節流格式(AnnexB)、AVCC 、RTP打包格式


H.264的兩種打包/封裝方法:字節流AnnexB格式 AVCC格式
放用於網絡發送時,要封裝成RTP格式

1、AnnexB格式----用於實時播放

處於H264文檔附錄B(Annex-B Byte stream format)中

開始前綴(00000001或000001)+NALU數據  絕大部分編碼器的默認輸出格式
  一共有兩種起始碼start_code
   ①3字節0x000001  單幀多slice(即單幀多個NALU)之間間隔
   ②4字節0x00000001 幀之間,或者SPS等之前
4字節類型的開始碼在在連續的數據傳輸中非常有用,因為用字節來對齊、分割流數據,比如:用連續的31個bit0后接一個bit1來分割流數據,是很容易的。

AnnexB格式每個NALU都包含起始碼,且通常會周期性的在關鍵幀之前重復SPS和PPS
  👉👉👉所以解碼器可以從視頻流隨機點開始進行解碼,實時的流格式

2、AVCC—用於存儲

解碼器配置參數在一開始就配置好了,系統可以很容易的識別NALU的邊界,不需要額外的起始碼,減少了資源的浪費,同時可以在播放時調到視頻的中間位置。這種格式通常被用於可以被隨機訪問的多媒體數據,如存儲在硬盤的文件。MP4、MKV通常用AVCC格式來存儲。

AVCC格式不使用起始碼作為NALU的分界,這種格式在每個NALU前都加上一個大端格式的前綴(1、2、4字節,代表NALU長度)

所以在解析AVCC格式的時候需要將指定的前綴字節數的值保存在一個頭部對象中,這個都通常稱為extradata或者sequence header。同時,SPS和PPS數據也需要保存在extradata或者叫’sequence header’中。
H.264 extradata / sequence header’語法如下:

bits      
8   version ( always 0x01 )  
8   avc profile ( sps[0][1] )  
8   avc compatibility ( sps[0][2] )  
8   avc level ( sps[0][3] )  
6   reserved ( all bits on )  
2   NALULengthSizeMinusOne  變量告訴我們用幾個字節來存儲NALU的長度(前綴:1、2或4)
// 【第5字節的后2位】這個值是(前綴長度-1),如果值=3,那前綴就是4,因為4-1=3  
  值=0 對應前綴1字節 對應每個NALU包最大長度255字節
  值=1 對應前綴2字節 對應每個NALU包最大長度64K
  值=3 對應前綴4字節 使用最多
3   reserved ( all bits on )  
5   number of SPS NALUs (usually 1)  repeated once per SPS:  
16 SPS size  
N 	variable   SPS NALU data  
8 	number of PPS NALUs (usually 1)   repeated once per PPS  
16 PPS size  
N 	variable PPS NALU data  

使用上面的例子,那么AVCC extradata看起來像是這樣的:
0x0000 | 01 64 00 0A FF E1 00 19 67 64 00 0A AC 72 84 44  
0x0010 | 26 84 00 00 03 00 04 00 00 03 00 CA 3C 48 96 11  
0x0020 | 80 01 07 68 E8 43 8F 13 21 30  
  你會發現SPS和PPS被存儲在了非NALU包中(out of band帶外),即獨立於基本流數據。
  這些數據的存儲和傳輸是文件容器的任務,超出了本文的范疇。
  •  

雖然AVCC格式不使用起始碼,但防競爭字節還是有的。

防字節競爭處理(Annxb和AVCC均有):RBSP👉EBSP
>用起始碼定位NALU邊界存在一個問題,即NALU中可能存在與起始碼相同的數據。
>為了防止這個問題,在構建NALU時,需要在數據中的0x000000,0x000001,0x000002,0x000003中插入防競爭字節(Emulation Prevention Bytes)0x03,使其變為:
0x000000 = 0x0000 03 00
0x000001 = 0x0000 03 01
0x000002 = 0x0000 03 02
0x000003 = 0x0000 03 03
解碼器在檢測到0x000003時,將0x03拋棄,恢復原始數據。

3、RTP封裝=12字節固定RTP包頭 + 載荷(NALU)

在這里插入圖片描述

V:	RTP協議的版本號,當前協議版本號為2。
P:	填充標志,如果P=1,則在該報文的尾部填充一個或多個額外的八位組,它們不是有效載荷的一部分。
X:	擴展標志,如果X=1,則在RTP報頭后跟有一個擴展報頭
CC:	CSRC計數器,指示CSRC 標識符的個數。

M:	標記位(不同載荷含義不同,視頻標記一幀的最后一個分片slice則=1,其他=0)
PT:	載荷類型RTP_PAYLOAD_RTSP 如GSM音頻、JPEM圖像等。例如H264=96
序列號: 用於標識發送者所發送的 RTP 報文的序列號,每發送一個報文,序號增加 1

時間戳:	時間戳反映了該 RTP 報文的第一個八位組的采樣時刻。 接受者使用時間戳來計算延遲和抖動, 並進行同步控制。

SSRC:同步信源標識符 區分是在和誰通信。值隨機選擇,參加同一視頻會議的兩個同步信源的SSRC要相同。
//特約信源(CSRC)標識符:每個CSRC標識符占32位,可以有0~15個。每個CSRC標識了包含在該RTP報文有效載荷中的所有特約信源。

針對IP網絡的RTP打包方式。為原始的NAL打包格式,就是開始的若干字節(1,2,4字節)是NAL的長度,而不是start_code,此時必須借助某個全局的數據來獲得編碼器的profile,level,PPS,SPS等信息才可以解碼。

RTP 協議實際上是由實時傳輸協議RTP(Real-time Transport Protocol)和實時傳輸控制協議RTCP(Real-time Transport Control Protocol)兩部分組成。
  RTP 協議基於多播或單播網絡為用戶提供連續媒體數據的實時傳輸服務;  
  RTCP 協議是 RTP 協議的控制部分,用於實時監控數據傳輸質量,為系統提供擁塞控制和流控制。

原始碼流NALU格式

3.0 RTP單次發送有上限👉2種RTP打包:拆包or不拆包

在IP網絡中,當要傳輸的IP報文大小超過【最大傳輸單元MTU】時就會產生IP分片情況。(若交給底層協議拆包容易出問題→主動拆分NALU再打包成RTP包后發送)

3.1 不分包進行RTP打包:nalu_head(不分包時的包頭)

在這里插入圖片描述
即NALU自身原本的nalu_header
在這里插入圖片描述

1-12是NALU數據類型
24-31是RTP打包頭類型

一個NALU_header解讀:
在這里插入圖片描述

3.2 分包進行RTP打包:FU_indicator和FU_head(RTP分包時的包頭)

H264的RTP中有三種不同的封包模式(Single NAL,Non-interleaved,Interleaved)
通過SDP參數中指定,如:
m=video 49170 RTP/AVP 98
a=rtpmap:98 H264/90000
a=fmtp:98 profile-level-id=42A01E; packetization-mode=1; sprop-parameter-sets=Z0IACpZTBYmI,aMljiA==


1、packetization-mode決定封包模式:
  1、單一NAL單元模式( Single NAL unit mode):packetization-mode = 0 或者無此字段時缺省
  2、非交錯模式(Non-interleaved mode): packetization-mode = 1
  3、交錯模式(Interleaved mode): packetization-mode = 2


2、sprop-parameter-sets: SPS,PPS
這個參數可以用於傳輸 H.264 的序列參數集和圖像參數 NAL 單元. 這個參數的值采用 Base64 進行編碼. 不同的參數集間用","號隔開。
//若不用Base64則可能會有數據丟失

3、profile-level-id:
這個參數用於指示 H.264 流的 profile 類型和級別. 由 Base16(十六進制) 表示的 3 個字節. 第一個字節表示 H.264 的 Profile 類型, 第三個字節表示 H.264 的 Profile 級別

3種打包模式–7種打包方式對應關系在這里插入圖片描述
另一種看待角度:
①single NAL unit packet 單包(1個RTP包:1個NALU)
②aggregation packets  聚合(組合)包(1個RTP包:多個NALU,提高傳輸效率),需要解包時在重組。
  ①STAP (Single-time aggregation packet)
    STAP-A
    STAP-B
  ② MTAP (Multi-time aggregation packet)
    MTAP16
    MTAP24
③Fragmentation Unit  拆包處理【一個NALU→多包 NALU>最大傳輸單元MTU】
    FU-A  //非交錯模式
    FU-B  //交錯模式
1、單一NALU的RTP包:
在這里插入圖片描述
2、組合NALU的RTP包:
在這里插入圖片描述
3、分片NALU的RTP包:
在這里插入圖片描述

2、FU-A的分片格式
數據比較大的H264視頻包,被RTP分片發送。12字節的RTP頭后面跟隨的就是FU-A分片:
在這里插入圖片描述

FU_indicator:
F  禁止位
NRI 重要標識位👈即拆包的nalu自身的NRI
type RTP打包頭類型,FU-A時type=28

FU_header:
S  開始位 1表示分片NAL單元的開始,反之=0
E  結束位 1表示分片NAL單元的結束,反之=0。
R  保留位 必須為0,接收者必須忽略該位。
type NALU數據類型 👈NALU_header

拆包和解包:
發送端—拆包:NAL_header與分片后的FU的單元頭有如下關系:
     NAL_header前三位為FU_indicator的前三位
     NAL_header后五位為FU_header的后五位
接收端—解包:將所有的分片包組合還原成原始的NAl包
     nal_unit_type = (fu_indicator & 0xe0) | (fu_header & 0x1f)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM