實(shí)時(shí)視頻系統(tǒng)中的媒體傳輸,絕大多數(shù)都會(huì)采用RTP(實(shí)時(shí)傳輸協(xié)議)標(biāo)準(zhǔn)。H.264視頻作為當(dāng)前應(yīng)用最廣泛的視頻編碼標(biāo)準(zhǔn),其傳輸協(xié)議也會(huì)首選RTP標(biāo)準(zhǔn)。在設(shè)計(jì)實(shí)現(xiàn)H.264的實(shí)時(shí)傳輸時(shí),H.264協(xié)議基于RTP的打包和解包定義于IETF標(biāo)準(zhǔn)-RFC6184,RTC系統(tǒng)需要遵循這個(gè)標(biāo)準(zhǔn)來(lái)設(shè)計(jì)打包和解包處理模塊。在通信理論中,這個(gè)過(guò)程可以被認(rèn)為是基于傳輸?shù)男诺谰幋a。本篇技術(shù)文章帶你了解H.264在RTP中的基本格式和技術(shù)實(shí)踐。
使用RTP對(duì)H.264打包和解包需要遵循IETF標(biāo)準(zhǔn)RFC6184, 我們先來(lái)了解一下H.264在RTP中的封包協(xié)議。
圖1 RTP報(bào)頭
對(duì)于H.264的RTP負(fù)載格式而言,RTP報(bào)頭的格式和RFC 3550里面的定義是一致的,不過(guò)有一些字段需要特別說(shuō)明一下。對(duì)RTP時(shí)間戳所對(duì)應(yīng)訪問(wèn)單元的最后一個(gè)數(shù)據(jù)包來(lái)設(shè)置標(biāo)記位,符合視頻中M位的正常使用格式,以允許有效的播放緩沖處理。解碼器可以使用這個(gè)位作為訪問(wèn)單元最后一個(gè)數(shù)據(jù)包的早期指示,但是不能完全依賴這個(gè)屬性。沒(méi)有特別指定的負(fù)載類(lèi)型,需要通過(guò)協(xié)商來(lái)確定。根據(jù)RFC 3550設(shè)置和使用。對(duì)于單NAL單元和非交錯(cuò)打包模式,序列號(hào)用于確定NAL單元的解碼順序。RTP時(shí)間戳設(shè)置為視頻內(nèi)容的采樣時(shí)間戳。必須使用90 kHz時(shí)鐘頻率。 H.264的RTP負(fù)載可分為三大類(lèi),類(lèi)型如下:
此類(lèi)RTP負(fù)載中僅包含單個(gè)NAL單元。負(fù)載報(bào)頭類(lèi)型編號(hào)等于原始NAL單元類(lèi)型,即從 1 到 23 的范圍值,詳見(jiàn)H.264規(guī)范。
此類(lèi)型用于聚合多個(gè)NAL單元成為單個(gè) RTP 負(fù)載。這類(lèi)數(shù)據(jù)包有四個(gè)細(xì)分版本:?jiǎn)螘r(shí)間聚合包A (STAP-A)、單時(shí)間聚合包B (STAP-B)、16位偏移多時(shí)間聚合包 (MTAP16) 和24位偏移多時(shí)間聚合包 (MTAP24)。負(fù)載類(lèi)型編號(hào)分配給 STAP-A、STAP-B、MTAP16 和 MTAP24 的值分別為 24、25、26 和27。
用于將單個(gè)NAL單元分片到多個(gè)RTP 數(shù)據(jù)包。存在兩個(gè)版本:FU-A 和 FU-B,負(fù)載類(lèi)型編號(hào)分別為 28 和 29。單NAL單元模式
所有的接收端都必須支持這種模式,主要應(yīng)用于兼容低時(shí)延應(yīng)用中的硬件設(shè)備。只有單NAL單元數(shù)據(jù)包可以在這種模式下使用。
非交錯(cuò)模式
建議接收端去支持這種模式,主要應(yīng)用于低時(shí)延應(yīng)用。只有單NAL單元、STAP-A和FU-A數(shù)據(jù)包可以在這種模式下使用。
交錯(cuò)模式
有需求的接收端可以去支持這種模式,主要應(yīng)用于非低延時(shí)應(yīng)用。STAP-B、兩種MTAP、FU-A和FU-B數(shù)據(jù)包可以在這種模式下使用。
表2 H.264打包模式允許的負(fù)載類(lèi)型單NAL單元和非交錯(cuò)模式中,NAL單元必須以NAL單元解碼順序傳輸,這兩種模式更適合低延時(shí)需求的交互系統(tǒng)。
交錯(cuò)模式中NAL單元的傳輸順序和解碼順序可以是不一致的,導(dǎo)致接收端的解包過(guò)程中需要按照解碼順序重新排序,引入更多的時(shí)延,因此并不適合需要低時(shí)延的交互系統(tǒng)。

圖2 H.264的RTP負(fù)載報(bào)頭H.264的RTP負(fù)載報(bào)頭位于負(fù)載的第1個(gè)字節(jié),分成三個(gè)字段:
forbidden_zero_bit。值為 0 表示NAL單元類(lèi)型字節(jié)和負(fù)載不應(yīng)包含位錯(cuò)誤或其他語(yǔ)法違規(guī)。值為 1 表示NAL單元類(lèi)型字節(jié)和負(fù)載可能包含位錯(cuò)誤或其他語(yǔ)法違規(guī)。nal_ref_idc。00值和非零值的語(yǔ)義與H.264規(guī)范保持不變。值00表示NAL單元的內(nèi)容不是用于重建圖片間預(yù)測(cè)的參考圖片,這樣的NAL單元可以被丟棄并不會(huì)導(dǎo)致參考圖片的不完整。值大于00表示需要對(duì)NAL單元進(jìn)行解碼以保持參考圖片的完整性。負(fù)載類(lèi)型,包括表1里面列舉的所有類(lèi)型。因?yàn)橹挥袉蜰AL單元模式和非交錯(cuò)模式打包模式更適合應(yīng)用于低時(shí)延交互系統(tǒng)中,而這兩種打包模式所涉及的只有單NAL數(shù)據(jù)包、單時(shí)間聚合包A(STAP-A)和分片單元A(FU-A)三種RTP負(fù)載,所以在這里只對(duì)這三種負(fù)載格式做個(gè)簡(jiǎn)單的介紹。

圖3 單NAL數(shù)據(jù)包負(fù)載格式 單NAL數(shù)據(jù)包就是將原始的NAL單元直接放置到RTP的負(fù)載中,NAL單元頭就是作為單NAL數(shù)據(jù)包的負(fù)載類(lèi)型。
單時(shí)間聚合包A(STAP-A)

圖4 聚合數(shù)據(jù)包負(fù)載格式聚合數(shù)據(jù)包的負(fù)載中包含一個(gè)或者多個(gè)聚合單元。一個(gè)聚合包可以攜帶盡可能多的聚合單元;不過(guò)聚合數(shù)據(jù)包中的總數(shù)據(jù)量應(yīng)該選擇合適大小,以便生成的IP數(shù)據(jù)包小于MTU大小。聚合數(shù)據(jù)包負(fù)載報(bào)頭中的NRI字段的值必須是所有聚合NAL單元中最大值。

STAP-A數(shù)據(jù)包中,每個(gè)聚合單元的NAL都應(yīng)該是共享相同的NALU時(shí)間。負(fù)載的首字節(jié)是STAP-A負(fù)載報(bào)頭,每個(gè)聚合單元是由兩字節(jié)的NAL單元尺寸字段和原始NAL單元組成。如果STAP-A數(shù)據(jù)包中包含兩個(gè)聚合單元,負(fù)載格式如下圖:
圖6 包含兩個(gè)聚合單元的STAP-A數(shù)據(jù)包示例
圖7 FU-A數(shù)據(jù)包負(fù)載格式FU-A數(shù)據(jù)包的負(fù)載包含1字節(jié)的分片單元標(biāo)識(shí)(負(fù)載報(bào)頭)、1字節(jié)的分片單元報(bào)頭和分片單元負(fù)載。分片單元負(fù)載報(bào)頭中的NRI字段的值等同于被分片NAL單元的值。
起始位。當(dāng)設(shè)置為 1 時(shí),指示一個(gè)分片NAL 單元的開(kāi)始。當(dāng) FU 負(fù)載不是分片NAL單元的開(kāi)始片段,設(shè)置起始位為 0。結(jié)束位。當(dāng)設(shè)置為 1 時(shí),指示一個(gè)分片NAL單元的結(jié)束。當(dāng) FU負(fù)載不是分片NAL單元的最后一個(gè)片段,設(shè)置結(jié)束位為 0 。被分片的原始NAL單元類(lèi)型(1 - 23)。RTC系統(tǒng)中的視頻處理的結(jié)構(gòu)大致如下圖,RTP打包解包是視頻編解碼和傳輸之間的橋梁。
圖9 視頻流工作流程
H.264的打包的基本流程大致如下:
在此只對(duì)三種打包模式下的解包過(guò)程做一個(gè)大致的介紹。
接收端包括一個(gè)接收緩沖器來(lái)補(bǔ)償傳輸延遲和抖動(dòng)。接收端將傳入的數(shù)據(jù)包按照接收順序存儲(chǔ)到接收緩沖器中。數(shù)據(jù)包按RTP序列號(hào)的順序被解包。如果解包的數(shù)據(jù)包是單個(gè)NAL單元包,包中包含的NAL單元直接傳遞給解碼器。如果解包的數(shù)據(jù)包是 STAP-A,則包含在數(shù)據(jù)包中的NAL單元按照它們封裝在數(shù)據(jù)包中的順序被傳遞給解碼器。對(duì)于所有 FU-A包含單個(gè)NAL單元片段的數(shù)據(jù)包,解包的片段按其發(fā)送順序恢復(fù)出NAL單元,然后傳遞給解碼器。交錯(cuò)模式的解包規(guī)則一般是從傳輸順序到解碼順序來(lái)重新排序NAL單元。在實(shí)時(shí)系統(tǒng)中應(yīng)用比較少見(jiàn),具體過(guò)程在此就不展開(kāi)了。 參考文獻(xiàn)
1、RFC 3550 – RTP: A Transport Protocol for Real-time Application2、RFC 6184 – RTP Payload Format for H.264 Video