一、引言
RTP封裝H.264時,RTP對NALU Header的nal_unit_type附加了擴展含義。
由《音視頻入門基礎:H.264專題(4)——NALU Header:forbidden_zero_bit、nal_ref_idc、nal_unit_type簡介》可以知道,nal_unit_type表示NALU的類型,在H.264官方文檔《T-REC-H.264-202108-I!!PDF-E.pdf》第65頁定義為:
二、NAL Unit Type
在RTP封包中,nal_unit_type被附加了擴展含義。根據《RFC 6184》第13頁:
可以看到值為1 - 23的nal_unit_type為原H.264中規定的類型,24 - 31為RTP擴展的類型。擴展的類型包括STAP-A、STAP-B、MTAP16、MTAP24、FU-A、FU-B。
三、Decoding Order Number (DON)
根據《RFC 6184》第17頁,在interleaved packetization mode(交錯分組模式)中,允許NAL單元的傳輸順序與NAL單元的解碼順序不同。Decoding Order Number(解碼順序號 ,DON)是有效載荷結構或派生變量中的一個字段,表示NAL單元的解碼順序。傳輸和解碼順序的耦合由可選的sprop-interleaving-depth媒體類型參數控制,具體如下:
當可選的sprop-interleaving-depth媒體類型參數的值等于 0(顯式或默認值)時,NAL單元的傳輸順序必須與 NAL 單元的解碼順序一致;當可選的sprop-interleaving-depth媒體類型參數的值大于0 時:MTAP16和MTAP24中NAL單元的順序不需要是NAL單元解碼順序,通過在兩個連續數據包中去包STAP-B、MTAP和FU生成的NAL單元的順序不需要是NAL單元解碼順序:
四、Single-time aggregation packet(STAP)
根據《RFC 6184》第22頁,當 NAL單元聚合在一起且共享相同的NALU時間時,應使用單時聚合數據包(STAP,Single-time aggregation packet)。
(一)STAP-A
STAP-A(STAP type A)的有效載荷不包括DON,至少由一個single-time aggregation units(單時聚合單元)組成。如下圖所示:
single-time aggregation units(單時聚合單元)由 16 位無符號大小信息(按網絡字節順序排列)組成,以字節為單位表示后面NAL單元的大小(不包括這兩個八位位組,但包括 NAL單元的NAL 單元類型八位位組),后面是NAL單元本身,包括其 NAL 單元類型字節。單時聚合單元在 RTP 有效載荷內按字節對齊,但不一定按 32 位字邊界對齊。下圖顯示了單時聚合單元的結構:
下圖展示了一個包含 STAP-A 的 RTP 數據包示例。STAP 包含兩個單時聚合單元,在圖中分別標為1和2:
(二)STAP-B
STAP-B(STAP type B)的有效載荷包括一個16位無符號解碼順序號 (DON)(按網絡字節順序排列)和至少一個single-time aggregation units(單時聚合單元):
DON 字段按傳輸順序指定 STAP-B 中第一個 NAL 單元的DON值。對于 STAP-B 中按出現順序連續出現的每個 NAL 單元,DON 值 =(STAP-B中前一個NAL單元的DON 值 + 1)% 65536,其中“%”表示模乘運算。
下圖展示了一個包含 STAP-B 的 RTP 數據包示例。STAP 包含兩個單時聚合單元,在圖中分別標為 1 和 2:
五、Multi-Time Aggregation Packet(MTAP)
MTAP(Multi-Time Aggregation Packet,多時聚合包)?的NAL單元有效載荷包括一個16位無符號解碼順序號基 (DONB)(按網絡字節順序排列)和一個或多個多時間聚合單元,如下圖所示。DONB必須包含MTAP NAL單元解碼順序中第一個NAL單元的DON值。說明:NAL 單元解碼順序中的第一個 NAL 單元不一定是 MTAP 中 NAL 單元封裝順序中的第一個 NAL 單元:
《RFC 6184》定義了兩種不同的多時間聚合單元。它們都由以下 NAL 單元的 16 位無符號大小信息(按網絡字節順序)、8 位無符號解碼順序號差值(DOND)和該 NAL 單元的 n 位時間戳偏移(TS 偏移)(按網絡字節順序)組成,其中 n 可以是 16 位或 24 位。不同 MTAP 類型(MTAP16 和 MTAP24)之間的選擇取決于應用:時間戳偏移越大,MTAP 的靈活性越高,但開銷也越大。
MTAP16的多時間聚合單元結構如下圖所示:
MTAP24的多時間聚合單元結構如下圖所示:
數據包內聚合單元的起始或終止位置不要求在 32 位字邊界上。多時間聚合單元中包含的 NAL 單元的 DON 等于 (DONB + DOND) % 65536,其中 % 表示取模運算。本備忘錄未說明 MTAP 中的 NAL 單元如何排序,但在大多數情況下,應使用 NAL 單元解碼順序。
時間戳偏移字段必須設置為等于以下公式的值:如果 NALU 時間大于或等于數據包的 RTP 時間戳,則時間戳偏移 = (NAL 單元的 NALU 時間 - 數據包的 RTP 時間戳)。
?如果 NALU 時間小于數據包的 RTP 時間戳,則時間戳偏移等于 NALU 時間 + (2^32 - 數據包的 RTP 時間戳)。
對于 MTAP 中的 “最早 ”多時間聚合單元,時間戳偏移必須為零。因此,MTAP 本身的 RTP 時間戳與最早的 NALU 時間相同。
參考說明:“最早 ”的多時間聚合單元是指如果聚合單元中包含的 NAL 單元封裝在單個 NAL 單元數據包中,在 MTAP 的所有聚合單元中具有最小擴展 RTP 時間戳的單元。擴展時間戳是一種時間戳,它的位數超過 32 位,并能計算時間戳字段的纏繞,因此能確定時間戳纏繞時的最小值。這種 “最早 ”的聚合單元可能不是 MTAP 中聚合單元封裝順序中的第一個。最早 "的 NAL 單元也不必與 NAL 單元解碼順序中的第一個 NAL 單元相同。
下圖展示了一個包含 MTAP16 類型的多時間聚合數據包的 RTP 數據包示例,該數據包包含兩個多時間聚合單元,在圖中標注為 1 和 2:
下圖展示了一個包含 MTAP24 類型的多時間聚合數據包的 RTP 數據包示例,該數據包包含兩個多時間聚合單元,在圖中標注為 1 和 2:
六、Fragmentation Units (FUs)
根據《RFC 6184》第29頁,這種有效載荷類型允許將一個 NAL 單元分割成多個 RTP 數據包。在應用層而不是依靠低層分片(如 IP)這樣做有以下優點:
該有效載荷格式能夠在 IPv4 網絡上傳輸大于 64 kbytes 的 NAL 單元,而這些 NAL 單元可能存在于預先錄制的視頻中,尤其是高清格式中(每幅圖像的切片數有限制,這導致每幅圖像的 NAL 單元數有限制,從而可能產生較大的 NAL 單元)。
分片機制允許對單個 NAL 單元進行分片,并前向糾錯。
片段只針對單個 NAL 單元,而不針對任何聚合數據包。一個 NAL 單元的片段由該 NAL 單元的整數個連續八位位組組成。NAL 單元的每個八位字節必須恰好是該 NAL 單元的一個片段的一部分。
?同一 NAL 單元的片段必須以升序 RTP 序列號連續發送(在第一個片段和最后一個片段之間不發送同一 RTP 數據包流中的其他 RTP 數據包)。同樣,一個 NAL 單元必須按 RTP 序列號順序重新組裝。
當一個 NAL 單元被分片并在分片單元 (FUs) 內傳送時,它被稱為分片 NAL 單元。STAP 和 MTAP 不得分片。FU 不得嵌套;也就是說,一個 FU 不得包含另一個 FU。
攜帶 FU 的 RTP 數據包的 RTP 時間戳被設置為分片 NAL 單元的 NALU 時間。
下圖顯示了 FU-A 的 RTP 有效載荷格式。FU-A 由一個八位位組的碎片單元指示符(FU indicator)、一個八位位組的碎片單元報頭(FU header)和一個碎片單元(fragmentation unit ?payload)有效載荷組成:
下圖顯示了 FU-B 的 RTP 有效載荷格式。FU-B 由一個八位位組的片段單元指示符(FU indicator)、一個八位位組的片段單元頭(FU header)、一個解碼順序號(DON)(按網絡字節順序)和一個片段單元有效載荷(FU payload)組成。換句話說,FU-B 的結構與 FU-A 的結構相同,只是多了一個 DON 字段:
在interleaved packetization mode(交錯分組模式)中,NAL 單元類型 FU-B 必須用于分片 NAL 單元的第一個分片單元。在任何其他情況下都不得使用 NAL 單元類型 FU-B。換句話說,在交錯分組模式下,每個被分片的 NALU 的第一個分片都是 FU-B,然后是一個或多個 FU-A 分片。
?FU 指示符八位位組的格式如下:
FU 指示符八位位組類型字段 28 和 29 的值分別標識 FU-A 和 FU-B。NRI 字段的值必須根據分片 NAL 單元中 NRI 字段的值設置。
?FU 頭的格式如下:
其中:
S:占1位。當設置為 1 時,起始位表示分片 NAL 單元的起始位置。當下面的 FU 有效載荷不是片段 NAL 單元有效載荷的開始時,開始位設為 0。
E:占1位。當設置為 1 時,End 位表示分片 NAL 單元的結束,即有效載荷的最后一個字節也是分片 NAL 單元的最后一個字節。當后續 FU 有效載荷不是片段 NAL 單元的最后一個片段時,End 位被置 0。
R:占1位。保留位必須等于 0,且必須被接收器忽略。
Type:占5位。下圖中定義的 NAL 單元有效載荷類型:
?說明:FU-Bs 中的 DON 字段允許網關將 NAL 單元分片到 FU-Bs,而無需按照 NAL 單元解碼順序組織傳入的 NAL 單元。
片段 NAL 單元不得在一個 FU 中傳輸;也就是說,在同一個 FU 標頭中,開始位和結束位不得同時置 1。
?FU 有效載荷由片段 NAL 單元有效載荷的片段組成,這樣,如果連續 FU 的片段單元有效載荷按順序連接起來,就可以重建片段 NAL 單元的有效載荷。碎片 NAL 單元的 NAL 單元類型八位位組不包含在碎片單元有效載荷中,而是在碎片單元 FU 指示符八位位組的 F 和 NRI 字段以及 FU 標頭的類型字段中傳達碎片 NAL 單元的 NAL 單元類型八位位組信息。FU 有效載荷可以有任意數量的八位位組,也可以是空的。
說明:空 FU 允許在幾乎無損的環境中減少某類發送方的延遲。這些發送方的特點是,他們在 NALU 完全生成之前,也就是在知道 NALU 大小之前,就將 NALU 片段打包。如果不允許使用零長度的 NALU 片段,發送者就必須在發送當前片段之前生成至少一個比特的下一個片段數據。由于 H.264 的特點,有時幾個宏塊占用的比特為零,這種情況并不可取,而且會增加延遲。不過,在使用零長度 NALU 片段(可能)時,應仔細權衡因傳輸時使用額外數據包而增加的至少部分 NALU 丟失風險。
?如果一個分片單元丟失,接收方應按照傳輸順序丟棄與同一分片 NAL 單元相對應的所有后續分片單元。端點或 MANE 中的接收方可將 NAL 單元的前 n 1 個片段聚合為一個(不完整的)NAL 單元,即使未收到該 NAL 單元的 n 個片段。在這種情況下,NAL 單元的 forbidden_zero_bit 必須設為 1,以表示語法違規。