1. 程式人生 > >H264 RTP封包原理(轉載)

H264 RTP封包原理(轉載)

H264 RTP封包原理(轉載)

1.  引言 
       隨著資訊產業的發展,人們對資訊資源的要求已經逐漸由文字和圖片過渡到音訊和視訊,並越來越強調獲取資源的實時性和互動性。但人們又面臨著另外一種不可避免的尷尬,就是在網路上看到生動清晰的媒體演示的同時,不得不為等待傳輸檔案而花費大量時間。為了解決這個矛盾,一種新的媒體技術應運而生,這就是流媒體技術。流媒體由於具有啟動時延小、節省客戶端儲存空間等優勢,逐漸成為人們的首選,流媒體網路應用也在全球範圍內得到不斷的發展。其中實時流傳輸協議 RTP 詳細說明了在網際網路上傳遞音訊和視訊的標準資料包格式,它與傳輸控制協議 RTCP 配合使用,成為流媒體技術最普遍採用的協議之一。 


        H.264/AVC 是ITU-T 視訊編碼專家組(VCEG)和ISO/IEC 動態影象專家組(MPEG )聯合組成的聯合視訊組(JVT)共同努力制訂的新一代視訊編碼標準,它最大的優勢是具有很高的資料壓縮比率,在同等影象質量的條件下,H.264 的壓縮比是MPEG-2 的2 倍以上,是 MPEG-4的1.5~2 倍。同時,採用視訊編碼層(VCL)和網路提取層(NAL )的分層設計,非常適用於流媒體技術進行實時傳輸。本文就是基於 RTP 協議,對 H.264 視訊進行流式打包傳輸,實現了一個基本的流媒體伺服器功能,同時利用開源播放器VLC 作為接收端,構成一個完整的H.264 視訊傳輸系統。

2.  RTP 協議關鍵引數的設定

         RTP 協議是 IETF 在 1996 年提出的適合實時資料傳輸的新型協議。RTP 協議實際上是由實時傳輸協議RTP(Real-time Transport Protocol)和實時傳輸控制協議RTCP(Real-time Transport Control Protocol)兩部分組成。RTP 協議基於多播或單播網路為使用者提供連續媒體資料的實時傳輸服務;RTCP 協議是 RTP 協議的控制部分,用於實時監控資料傳輸質量,為系統提供擁塞控制和流控制。RTP 協議在RFC3550 中有詳細介紹。每一個 RTP 資料包都由固定包頭(Header )和載荷(Payload)兩個部分組成,其中包頭前12個位元組的含義是固定的,而載荷則可以是音訊或視訊資料。RTP 固定包頭的格式如圖1所示: 

       其中比較關鍵的引數設定解釋如下: 
      (1)標示位(M ):1 位,該標示位的含義一般由具體的媒體應用框架(profile )定義, 目的在於標記處RTP 流中的重要事件。
      (2)載荷型別(PT):7 位,用來指出RTP負載的具體格式。在RFC3551中,對常用的音視訊格式的RTP 傳輸載荷型別做了預設的取值規定,例如,型別2 表明該RTP資料包中承載的是用ITU G.721 演算法編碼的語音資料,採用頻率為 8000HZ,並且採用單聲道。 
      (3)序號:16 位,每傳送一個 RTP 資料包,序號加 1。接受者可以用它來檢測分組丟失和恢復分組順序。
      (4)時間戳:32 位,時間戳表示了 RTP 資料分組中第一個位元組的取樣時間,反映出各RTP 包相對於時間戳初始值的偏差。對於RTP 傳送端而言,取樣時間必須來源於一個線性單調遞增的時鐘。 
       從 RTP 資料包的格式不難看出,它包含了傳輸媒體的型別、格式、序列號、時間戳以及是否有附加資料等資訊。這些都為實時的流媒體傳輸提供了相應的基礎。而傳輸控制協議RTCP為 RTP傳輸提供了擁塞控制和流控制,它的具體包結構和各欄位的含義可參考RFC3550,此處不再贅述。 

3.  H.264 基本流結構及其傳輸機制

3.1  H.264 基本流的結構

H.264 的基本流(elementary stream,ES)的結構分為兩層,包括視訊編碼層(VCL)和網路適配層(NAL)。視訊編碼層負責高效的視訊內容表示,而網路適配層負責以網路所要求的恰當的方式對資料進行打包和傳送。引入NAL並使之與VCL分離帶來的好處包括兩方面:其一、使訊號處理和網路傳輸分離,VCL 和NAL 可以在不同的處理平臺上實現;其二、VCL 和NAL 分離設計,使得在不同的網路環境內,閘道器不需要因為網路環境不同而對VCL位元流進行重構和重編碼。
       H.264 的基本流由一系列NALU (Network Abstraction Layer Unit )組成,不同的NALU資料量各不相同。H.264 草案指出[2],當資料流是儲存在介質上時,在每個NALU 前新增起始碼:0x000001,用來指示一個 NALU的起始和終止位置。在這樣的機制下,解碼器在碼流中檢測起始碼,作為一個NALU得起始標識,當檢測到下一個起始碼時,當前NALU結束。每個NALU單元由一個位元組的 NALU頭(NALU Header)和若干個位元組的載荷資料(RBSP)組成。其中NALU 頭的格式如圖2 所示:

 

        F:forbidden_zero_bit.1 位,如果有語法衝突,則為 1。當網路識別此單元存在位元錯誤時,可將其設為 1,以便接收方丟掉該單元。 
        NRI:nal_ref_idc.2 位,用來指示該NALU 的重要性等級。值越大,表示當前NALU越重要。具體大於0 時取何值,沒有具體規定。

 Type:5 位,指出NALU 的型別。具體如表1 所示:

 

       需要特別指出的是,NRI 值為 7 和 8 的NALU 分別為序列引數集(sps)和影象引數集(pps)。引數集是一組很少改變的,為大量VCL NALU 提供解碼資訊的資料。其中序列引數集作用於一系列連續的編碼影象,而影象引數集作用於編碼視訊序列中一個或多個獨立的影象。如果解碼器沒能正確接收到這兩個引數集,那麼其他NALU 也是無法解碼的。因此它們一般在傳送其它 NALU 之前傳送,並且使用不同的通道或者更加可靠的傳輸協議(如TCP)進行傳輸,也可以重複傳輸。

 

3.2  適用於 H.264 視訊的傳輸機制 
       前面分別討論了RTP 協議及H.264基本流的結構,那麼如何使用RTP協議來傳輸H.264視訊了?一個有效的辦法就是從H.264視訊中剝離出每個NALU,在每個NALU前新增相應的RTP包頭,然後將包含RTP 包頭和NALU 的資料包傳送出去。下面就從RTP包頭和NALU兩方面分別闡述。 
      完整的 RTP 固定包頭的格式在前面圖 1 中已經指出,根據RFC3984[3],這裡詳細給出各個位的具體設定。 
      V:版本號,2 位。根據RFC3984,目前使用的RTP 版本號應設為0x10。 
      P:填充位,1 位。當前不使用特殊的加密演算法,因此該位設為 0。 
      X:擴充套件位,1 位。當前固定頭後面不跟隨頭擴充套件,因此該位也為 0。 
      CC:CSRC 計數,4 位。表示跟在 RTP 固定包頭後面CSRC 的數目,對於本文所要實現的基本的流媒體伺服器來說,沒有用到混合器,該位也設為 0x0。 
       M:標示位,1 位。如果當前 NALU為一個接入單元最後的那個NALU,那麼將M位置 1;或者當前RTP 資料包為一個NALU 的最後的那個分片時(NALU 的分片在後面講述),M位置 1。其餘情況下M 位保持為 0。 
       PT:載荷型別,7 位。對於H.264 視訊格式,當前並沒有規定一個預設的PT 值。因此選用大於 95 的值可以。此處設為0x60(十進位制96)。 
      SQ:序號,16 位。序號的起始值為隨機值,此處設為 0,每傳送一個RTP 資料包,序號值加 1。 
      TS:時間戳,32 位。同序號一樣,時間戳的起始值也為隨機值,此處設為0。根據RFC3984, 與時間戳相應的時鐘頻率必須為90000HZ。 
      SSRC:同步源標示,32 位。SSRC應該被隨機生成,以使在同一個RTP會話期中沒有任何兩個同步源具有相同的SSRC 識別符。此處僅有一個同步源,因此將其設為0x12345678。
      對於每一個NALU,根據其包含的資料量的不同,其大小也有差異。在IP網路中,當要傳輸的IP 報文大小超過最大傳輸單元MTU(Maximum Transmission Unit )時就會產生IP分片情況。在乙太網環境中可傳輸的最大 IP 報文(MTU)的大小為 1500 位元組。如果傳送的IP資料包大於MTU,資料包就會被拆開來傳送,這樣就會產生很多資料包碎片,增加丟包率,降低網路速度。對於視訊傳輸而言,若RTP 包大於MTU 而由底層協議任意拆包,可能會導致接收端播放器的延時播放甚至無法正常播放。因此對於大於MTU 的NALU 單元,必須進行拆包處理。

RFC3984 給出了3 中不同的RTP 打包方案:

(1)Single NALU Packet:在一個RTP 包中只封裝一個NALU,在本文中對於小於 1400位元組的NALU 便採用這種打包方案。 
       (2)Aggregation Packet:在一個RTP 包中封裝多個NALU,對於較小的NALU 可以採用這種打包方案,從而提高傳輸效率。 
       (3)Fragmentation Unit:一個NALU 封裝在多個RTP包中,在本文中,對於大於1400位元組的NALU 便採用這種方案進行拆包處理。

4.  H.264 流媒體傳輸系統的實現

       一個完整的流媒體傳輸系統包含伺服器端和客戶端兩個部分[5][6]。對於伺服器端,其主要任務是讀取H.264 視訊,從碼流中分離出每個NALU 單元,分析NALU 的型別,設定相應的 RTP 包頭,封裝 RTP 資料包併發送。而對於客戶端來說,其主要任務則是接收 RTP資料包,從RTP 包中解析出NALU 單元,然後送至解碼器進行解碼播放。該流媒體傳輸系統的框架如圖3 所示。

分類: VS2010 C++開發