H.264視頻流的傳輸與載荷——將H264碼流打包成RTP包

http://blog.csdn.net/bytxl/article/details/50393198

從攝像頭獲取的視頻數據,經過編碼後(當然,也可以不編碼,如果你覺得也很ok的話),可以視頻錄製,同時如果需要,當然也可以視頻遠程傳輸咯,而實時傳輸協議(Real-time Transport Protocol,RTP)是在Internet上處理多媒體數據流的一種網絡協議,利用它能夠在一對一(unicast,單播)或者一對多(multicast,多播)的網絡環境中實現傳流媒體數據的實時傳輸(不需要下載完畢後才能看視頻)。RTP通常使用UDP來進行多媒體數據的傳輸,但如果需要的話可以使用TCP等其它協議,整個RTP協議由兩個密切相關的部分組成:RTP數據協議和RTCP控制協議。

   RTP數據協議負責對流媒體數據進行封包並實現媒體流的實時傳輸,每一個RTP數據報都由頭部(Header)和負載(Payload)兩個部分組成,其中頭部前12個字節的含義是固定的,而負載則可以是音頻或者視頻數據。

   RTCP 控制協議需要與RTP數據協議一起配合使用,當應用程序啓動一個RTP會話時將同時佔用兩個端口,分別供RTP和RTCP使用RTP本身並不能爲按序傳輸數據包提供可靠的保證,也不提供流量控制和擁塞控制,這些都由RTCP來負責完成。通常RTCP會採用與RTP相同的分發機制,向會話中的所有成員週期性地發送控制信息,應用程序通過接收這些數據,從中獲取會話參與者的相關資料,以及網絡狀況、分組丟失概率等反饋信息,從而能 夠對服務質量進行控制或者對網絡狀況進行診斷。

   實時流協議(RealTime Streaming Protocol,RTSP),它的意義在於使得實時流媒體數據的受控和點播變得可能。總的說來,RTSP是一個流媒體表示協議,  主要用來控制具有實時特性的數據發送,但它本身並不傳輸數據,而是必須依賴於下層傳輸協議所提供的某些服務。RTSP 可以對流媒體提供諸如播放、暫停、快進等操作,它負責定義具體的控制消息、操作方法、狀態碼等,此外還描述了與RTP間的交互操作。

 

一、JRTPLIB庫的安裝

Linux:

rtp的運行當然少不了JRTPLIB庫的支持,JRTPLIB是一個面向對象的RTP封裝庫,安裝過程如下:

    1)下載開發包解壓。這裏用的是jrtplib-3.7.1,下載地址:http://download.csdn.net/detail/huangminqiang201209/4925142 。

    2)  解壓後出現兩個目錄,一個是jrtplib-3.7.1,一個是jthread-1.2.1。JRTPLib是一個開源的RTP庫。JThread是一個開源的線程類。

    3)進入jthead解壓目錄,運行./configure配置環境. 配置完畢後運行make,  接着安裝make install。

    4)jrtplib安裝同上。裝好以後系統環境如下,靜態動態庫安裝到了/usr/local/lib目錄下,包括libjrtplib-3.7.1.so和libjthread-1.2.1.so等。頭文件在/usr/local/include目錄jrtplib*目錄下。

    5)linux默認會在路徑爲/lib和/usr/lib下的庫文件收縮,而上面的庫文件在/usr/local/lib下,可以在/lib或者在/usr/lib下創建該庫的快捷方式: ln -s /usr/local/lib/libjrtp-3.7.1.so /usr/lib/libjrtp-3.7.1.so
    6)在jrtplib源代碼目錄裏有例子程序,make文件都是寫好的,試驗一下編譯example1.cpp,使用靜態庫libjrtp.a鏈接,編譯語句如下:g++ -o example1 example1.cpp -I /usr/local/include/jrtplib3/ -ljrtp

    7)最後執行命令:ldconfig,更新庫的信息,這樣執行文件./example1,就可以了

Windows: 

    1)解壓 jrtplib-3.7.1和 jthread-1.2.1

    2)用 VC打開工程文件jthread.dsw

    3)編譯 jrtplib.lib和jthread.lib需要注意VC6要求安裝Vs6sp6,在編譯jrtplib.lib和jthread.lib前,在  project——settings——C/C++——Codegeneration:use run-time library中,對於 debug,選擇:DebugMultithreaded DLL,對於release,則選擇:Multithreaded DLL。

    4)首先編譯 jthread 庫,然後將 jthread-1.2.1\src內的"jmutex.h"和"jthread.h"兩個頭文件放入jrtplib-3.7.1\src目錄下,然後將 jrtplib-3.7.1\src 文件夾下所有頭文件中的和語句修改爲"jmutex.h"和"jthread.h",需要修改的文件爲 rtpudpv4transmitter.h、rtpsession.h和 rtppollthread.h。編譯時注意編譯方式和 jthread.lib一致。

    5)編譯生成的 jthread.lib 和 jrtplib.lib 拷貝到系統目錄:C:\Program  Files\Microsoft Visual Studio\VC98\Lib 下,將 jrtplib-3.7.1\src下所有的.h 頭文件複製到 C:\Program Files\MicrosoftVisual Studio\VC98\Include,以便以後使用。

    6)現在我們就可以編譯 jrtplib-3.7.1\examples 下的實例程序了。建立 VC 工程,打開example1.c,在 Project  Settings 的 link 頁添加 jthread.lib  jrtplib.lib ws2_32.lib,在project——settings——C/C++——Code  generation:use  run-time library 中,對於 debug,選擇:DebugMultithreaded DLL,對於 release,則選擇:Multithreaded DLL。

    7)編譯源程序,運行就OK 啦

二、H.264 RTP PAYLOAD 載荷

  在傳輸前,先要了解H.264 RTP PAYLOAD 格式(負載格式):

1. 網絡抽象層單元類型 (NALU)

NALU 頭由一個字節組成, 它的語法如下:

      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |F|NRI|  Type   |
      +---------------+

F: 1 個比特.
  forbidden_zero_bit. 在 H.264 規範中規定了這一位必須爲 0.

NRI: 2 個比特.
  nal_ref_idc. 取 00 ~ 11, 似乎指示這個 NALU 的重要性, 如 00 的 NALU 解碼器可以丟棄它而不影響圖像的回放. 不過一般情況下不太關心這個屬性.

Type: 5 個比特.
  nal_unit_type. 這個 NALU 單元的類型. 簡述如下:

  0     沒有定義
  1-23  NAL單元   單個 NAL 單元包.
  24    STAP-A   單一時間的組合包
  25    STAP-B   單一時間的組合包
  26    MTAP16   多個時間的組合包
  27    MTAP24   多個時間的組合包
  28    FU-A     分片的單元
  29    FU-B     分片的單元
  30-31 沒有定義

2. 打包模式

  下面是 RFC 3550 中規定的 RTP 頭的結構.

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |V=2|P|X|  CC   |M|     PT      |       sequence number         |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           timestamp                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |           synchronization source (SSRC) identifier            |
      +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
      |            contributing source (CSRC) identifiers             |
      |                             ....                              |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

  負載類型 Payload type (PT): 7 bits
  序列號 Sequence number (SN): 16 bits
  時間戳 Timestamp: 32 bits
  
  H.264 Payload 格式定義了三種不同的基本的負載(Payload)結構. 接收端可通過 RTP Payload 的第一個字節來識別它們. 這一個字節類似 NALU 頭的格式, 而這個頭結構的 NAL 單元類型字段則指出了代表的是哪一種結構。這個字節的結構如下, 可以看出它和 H.264 的 NALU 頭結構是一樣的:

      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |F|NRI|  Type   |
      +---------------+
  字段 Type: 這個 RTP payload 中 NAL 單元的類型. 

  這個字段和 H.264 中類型字段的區別是, 當 type 的值爲 24 ~ 31 表示這是一個特別格式的 NAL 單元, 而 H.264 中, 只取 1~23 是有效的值.
   
  24    STAP-A   單一時間的組合包
  25    STAP-B   單一時間的組合包
  26    MTAP16   多個時間的組合包
  27    MTAP24   多個時間的組合包
  28    FU-A     分片的單元
  29    FU-B     分片的單元
  30-31 沒有定義

 

  可能的結構類型分別有:

  1. 單一 NAL 單元模式
     即一個 RTP 包僅由一個完整的 NALU 組成. 這種情況下 RTP NAL 頭類型字段和原始的 H.264的 NALU 頭類型字段是一樣的.

  2. 組合封包模式
    即可能是由多個 NAL 單元組成一個 RTP 包. 分別有4種組合方式: STAP-A, STAP-B, MTAP16, MTAP24.
  那麼這裏的類型值分別是 24, 25, 26 以及 27.

  3. 分片封包模式
    用於把一個 NALU 單元封裝成多個 RTP 包. 存在兩種類型 FU-A 和 FU-B. 類型值分別是 28 和 29.

2.1 單一 NAL 單元模式

  對於 NALU 的長度小於 MTU 大小的包, 一般採用單一 NAL 單元模式.
  對於一個原始的 H.264 NALU 單元常由 [Start Code] [NALU Header] [NALU Payload] 三部分組成, 其中 Start Code 用於標示這是一個 NALU 單元的開始, 必須是 "00 00 00 01" 或 "00 00 01", NALU 頭僅一個字節, 其後都是 NALU 單元內容.

  打包時去除 "00 00 01" 或 "00 00 00 01" 的開始碼, 把其他數據封裝成 RTP 包即可.

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |F|NRI|  type   |                                               |
      +-+-+-+-+-+-+-+-+                                               |
      |                                                               |
      |               Bytes 2..n of a Single NAL unit                 |
      |                                                               |
      |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                               :...OPTIONAL RTP padding        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


  如有一個 H.264 的 NALU 是這樣的:

  [00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]

  這是一個序列參數集 NAL 單元. [00 00 00 01] 是四個字節的開始碼, 67 是 NALU 頭, 42 開始的數據是 NALU 內容.

  封裝成 RTP 包將如下:

  [ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F ]

  即只要去掉 4 個字節的開始碼就可以了.

 

2.2 組合封包模式

  當 NALU 的長度特別小時, 可以把幾個 NALU 單元封在一個 RTP 包中.

  
       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          RTP Header                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |STAP-A NAL HDR |         NALU 1 Size           | NALU 1 HDR    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                         NALU 1 Data                           |
      :                                                               :
      +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |               | NALU 2 Size                   | NALU 2 HDR    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                         NALU 2 Data                           |
      :                                                               :
      |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                               :...OPTIONAL RTP padding        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

2.3 Fragmentation Units (FUs).

  當 NALU 的長度超過 MTU 時, 就必須對 NALU 單元進行分片封包. 也稱爲 Fragmentation Units (FUs).
  
       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      | FU indicator  |   FU header   |                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
      |                                                               |
      |                         FU payload                            |
      |                                                               |
      |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                               :...OPTIONAL RTP padding        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      Figure 14.  RTP payload format for FU-A

   The FU indicator octet has the following format:

      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |F|NRI|  Type   |
      +---------------+

   The FU header has the following format:

      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |S|E|R|  Type   |
      +---------------+

FU indicator和FU header參考下面的例子的計算。

3. SDP 參數

  下面描述瞭如何在 SDP 中表示一個 H.264 流:

  . "m=" 行中的媒體名必須是 "video"
  . "a=rtpmap" 行中的編碼名稱必須是 "H264".
  . "a=rtpmap" 行中的時鐘頻率必須是 90000.
  . 其他參數都包括在 "a=fmtp" 行中.

  如:

  m=video 49170 RTP/AVP 98
  a=rtpmap:98 H264/90000
  a=fmtp:98 profile-level-id=42A01E; sprop-parameter-sets=Z0IACpZTBYmI,aMljiA==

  下面介紹一些常用的參數.

3.1 packetization-mode:

  表示支持的封包模式. 
  當 packetization-mode 的值爲 0 時或不存在時, 必須使用單一 NALU 單元模式.
  當 packetization-mode 的值爲 1 時必須使用非交錯(non-interleaved)封包模式.
  當 packetization-mode 的值爲 2 時必須使用交錯(interleaved)封包模式.
  這個參數不可以取其他的值.

3.2 sprop-parameter-sets:

  這個參數可以用於傳輸 H.264 的序列參數集和圖像參數 NAL 單元. 這個參數的值採用 Base64 進行編碼. 不同的參數集間用","號隔開.

3.3 profile-level-id:

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

三個字節表示 H.264 的 Profile 級別:
  

3.4 max-mbps:

  這個參數的值是一個整型, 指出了每一秒最大的宏塊處理速度.

三、數據(無攝像頭,即黑屏數據)

1)H.246部分數據:

  這是一個序列參數集 NAL 單元. [00 00 00 01] 是四個字節的開始碼, 67 是 NALU 頭, 42 開始的數據是NALU內容.

2)rtp,即sendpacket()發送的部分數據:

  FU indicator0x7c  = ( NALU_header & 0x60 ) | 28  ==  (0110 0111 & 0110 0000) | 28  ==  01100000 | 0001 1100  ==  0111 1100  ==  0x7c

  FU header0x87  = ( NALU_header & 0x1f ) | 0x80  ==  (0110 0111 &0001 1111) | 0x80  ==  0000 0111 | 1000 0000  ==  1000 0111 == 0x87

  這2個字節取代了開始碼[00 00 00 01] 。其他的都一樣。

  NALU:0x67:  0 11 00111(7)

  FU indicator:0x7C:0 11 11100(28)

3)網絡抓包數據

14 E6 E4 1C C9 7A06 ED B5 C3 AA 23 0800 45 00 00 30 00 00 40 00 40 11 B6 B8 C0 A8 01 42 C0 A801 72 3E D0 04 D200 1CF5 DA 80E2 A8C1 8C 94F8 DD 31 1F06 D7 61 E2 0B 14 28 00 C6 30(62字節)

14 E6 E4 1C C9 7A06 ED B5 C3 AA 23 0800 45 00 00 31 00 00 40 00 40 11 B6B7 C0 A8 01 42 C0 A8 01 72 3E D0 04 D2 00 1D CE BE 80 E2 A8 D4 8C 96 04 0D 31 1F 06 D7 61E8 01 5C 50 A003 18 C0(63字節) 

14 E6 E4 1C C9 7A06 ED B5 C3 AA 23 0800 45 00 04 29 00 00 40 00 40 11 B2 BF C0 A8 01 42 C0 A8 01 72 3E D0 04 D2 04 15 5A 5B 80 62 A8 C08C 94 EA CD 31 1F 06 D77C 8742E0 1E DB 02 C0 49 1000 00 00 01 68 CE 30 A4 80 0000 00 01 06 E5 01 DB 80 00 00 00 01 65 B8 00 02 7C 80 6C50 A2 62 80 00 90 3D F7 DF 7DF7 DF 7D F7 DF 7D F7 DF 7D F7 DF 7D F7 DF 7D F7 DF 7D F7 DF 7D F7 DF 7D F7 DF7D F7 DF 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D75D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D75 D7 5D 75 D7 5D 75 D7 5D 75 D7 5D 75(第一個包,1079字節)

四、RTP視頻傳輸代碼

#define PLOAD_TYPE 98
#define DefaultTimestampIncrement 90000/25
static RTPSession sess;

//創建rtp會話
static int  RtpSetup( uint16_t portbase)
{
    int status;
    ******************************* 
    *******************************
    status = sess.Create(sessparams,&transparams);
    checkerror(status);
    return status;
}

//錯誤判斷
void checkerror(int err)

      if (err < 0)
      {   
         char* errstr = RTPGetErrorString(err);  
         printf("Error:%s\\n", errstr);   
         exit(-1); 
      }
}

 

//增加rtp傳輸目標ip地址,參數爲目標ip和端口
int AddDestination(uint32_t ipaddr, uint16_t destport)
{
    int status;
 
    RTPIPv4Address addr(ipaddr,destport);
    status = sess.AddDestination(addr);
    checkerror(status);
    return status;
}

 

//rtp視頻傳輸,val爲一幀數據流(264的原始數據),包含0x00 0x00 0x00 0x01信息,length爲數據的長度

int H264SendPacket(unsigned char *val, uint32_t length)
{
    int status=0;
    uint32_t  TimestampIncrement;
    uint32_t send_length,valid_len=length-4;
    char NALU=val[4]
,*sendStartAddr=NULL;
    #define  MAX_STREAM_SLICE 1024

   //獲取默認設置
   TimestampIncrement=sess.GetDefaultTimestampIncrement();
   //如果數據小於1024字節,直接發送:單一NAL單元模式
    if(valid_len <= MAX_STREAM_SLICE)
    {
        status = sess.SendPacket((void *)&val[4],valid_len,PLOAD_TYPE,true,DefaultTimestampIncrement);
        checkerror(status);
    }
    else
    {
             //切分爲很多個包發送,每個包前要對頭進行處理,如第一個包

             sendStartAddr=(char *)(val+4);//發送數據的起始地址
             sendStartAddr[pos-1]=(NALU&0x60)|28;//FU indicator
             sendStartAddr[pos]=(NALU&0x1f)|0x80;//FU header
             send_length=MAX_STREAM_SLICE+1;//要發送數據的長度,1025字節

                  ………………………………

                  //第二個至倒數第二個包

                  ………………………………

                  //最後一個包

    }

    checkerror(status);
end:
    return status;
}

 對了,記得要連接rtp庫哦!!!!

五、SDP參數

    因爲程序是在Hi35XX開發板上運行,所以我的工作是把編碼後的視頻發送出去就ok了偷笑

在windows下,寫了一個腳本xxx.dsp,內容如下:
     m=video 1234 RTP/AVP 98
     a=rtpmap:98 H264/90000;
     a=decode_buf=300;

     a=framerate:15
     c=IN IP4 192.168.2.105   //板子的ip

注:

    1)"m=" 行中的媒體名必須是 "video",端口爲1234.
    2)"a=rtpmap" 行中的編碼名稱必須是 "H264".時鐘頻率必須是 90000.

    然後把腳本拖到VLCPortable.exe軟件中(VLC是一個標準),就能顯示攝像頭獲取的視頻,就說明rtp傳輸沒問題,我的工作就完成了再見

 

http://blog.sina.com.cn/s/blog_8795b0970101ifun.html

http://www.cppblog.com/czanyou/archive/2009/12/25/67940.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章