1. 程式人生 > >基於RTP的h.264視頻傳輸系統設計(一)

基於RTP的h.264視頻傳輸系統設計(一)

-i 感謝 項目 頻率 算術 處理 rop sel 決定


一、H.264 的層次介紹

H.264 定義三個層次,每一個層次支持一組特定的編碼功能。而且按照各個層次指定所指定的功能。基礎層次(baselineprofile)支持 I 幀和 P 幀【1】的幀內和幀間編碼,支持自適應的可變長度的熵編碼(CAVLC)。主要層次(main profile)支持隔行掃描視頻,B 幀【2】的幀內編碼,使用加權預測的幀內編碼和使用上下文的算術編碼(CABAV)。擴展層次(extendedprofile)不支持隔行掃描視頻和CABAC,但添加了碼流之間高效的轉化模式(SP 和 SI 片)和增強了錯誤碼的恢復能力(數據切割)。

基礎層次的潛在應用主要包含可視電話、視頻會議和無線通訊。主要層次的應用在電視廣播和視頻存儲;擴展層次主要應用在流媒體應用程序中。

然而,每一個文件有足夠的靈活性,支持廣泛的應用。這些應用的實例,不應被視為終於固定的。

二、H.264 的分層結構

H264 將其功能主要分為兩層。即視頻編碼層(VCL)和網絡提取層(NAL, Network Abstraction Layer)。VCL層負責編碼,NAL層負責網絡傳輸。

H.264 的視頻提取層 NAL

H.264 的視頻編碼序列是由一系列的NAL 單元組成的。

我們知道00 00 00 01NALU的開始標記

1. 網絡抽象層單元類型 (NALU)
NALU 頭由一個字節組成,它的語法例如以下:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+


|F|NRI|Type |
+---------------+
F: 1 個比特(bit ).
forbidden_zero_bit. H.264規範中規定了這一位必須為 0.
NRI:2 個比特. nal_ref_idc. 00 ~ 11,似乎指示這個 NALU的重要性, 00 NALU解碼器能夠丟棄它而不影響圖像的回放.只是普通情況下不太關心這個屬性.
Type:5 個比特.
nal_unit_type.這個 NALU單元的類型.簡述例如以下:
0 未定義
1-23NAL單元單個 NAL單元包.
24STAP-A 單一時間的組合包
24STAP-B 單一時間的組合包
26MTAP16
多個時間的組合包
27MTAP24 多個時間的組合包
28FU-A 分片的單元
29FU-B 分片的單元
30-31未定義
2. 打包模式rfc3550

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             |
   |                             ....                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

RTP包頭格式

 前12個字節出如今每一個RTP包中。只在被混合器插入時。才出現CSRC識別符列表。這些域有下面意義:

 版本號(V):2比特 此域定義了RTP的版本號。此協議定義的版本號是2。(值1被RTP草案版本號使用。值0用在最初"vat"語音工具使用的協議中。)

 填充(P):1比特 若填料比特被設置,則此包包括一到多個附加在末端的填充比特,填充比特不算作負載的一部分。

填充的最後一個字節指明能夠忽略多少個填充比特。

填充可能用於某些具有固定長度的加密算法,或者用於在底層數據單元中傳輸多個RTP包。

 擴展(X):1比特 若設置擴展比特。固定頭(僅)後面尾隨一個頭擴展。

 CSRC計數(CC):4比特 CSRC計數包括了跟在固定頭後面CSRC識別符的數目。

 標誌(M):1比特 標誌的解釋由詳細協議規定。它用來同意在比特流中標記重要的事件,如幀邊界。

 負載類型(PT):7比特 此域定義了負載的格式,由詳細應用決定其解釋。協議能夠規定負載類型碼和負載格式之間一個默認的匹配。

其它的負載類型碼能夠通過非RTP方法動態定義。

RTP發送端在隨意給定時間發出一個單獨的RTP負載類型;此域不用來復用不同的媒體流。

  序列號(sequence number):16比特 每發送一個RTP數據包,序列號加1。接收端能夠據此檢測丟包和重建包序列。序列號的初始值是隨機的(不可預測),以使即便在源本身不加密時(有時包要通過翻譯器,它會這樣做),對加密算法泛知的普通文本攻擊也會更加困難。

時間戳(timestamp) 32比特 時間戳反映了RTP數據包中第一個字節的採樣時間。

SSRC:32比特 用以識別同步源。標識符應該被隨機生成。以使在同一個RTP會話期中沒有不論什麽兩個同步源有同樣的SSRC識別符。

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是有效的值.
24STAP-A 單一時間的組合包
24STAP-B 單一時間的組合包
26MTAP16 多個時間的組合包
27MTAP24 多個時間的組合包
28FU-A 分片的單元
29FU-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單元模式(Single NAL Unit Packet:一個RTP Payload僅包括一個NAL單元, NALU類型號為1~23,H264標準碼流很接近.)
對於 NALU的長度小於 MTU大小的包,一般採用單一 NAL單元模式.對於一個原始的 H.264 NALU單元常由 [Start Code] [NALU Header][NALU Payload]三部分組成,當中 StartCode用於標示這是一個NALU單元的開始,必須是 "00 00 00 01""00 00 01", NALU頭僅一個字節,其後都是 NALU單元內容.
打包時去除 "00 00 01""00 00 00 01"的開始碼,把其它數據封包的 RTP包就可以.
0 1 23
0 1 23 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是這種:
[0000 00 01 67 42 A0 1E 23 56 0E 2F ... ]
這是一個序列參數集 NAL單元. [00 00 00 01]是四個字節的開始碼, 67 NALU, 42開始的數據是 NALU內容.
封裝成 RTP包將例如以下:
[ RTPHeader ] [ 67 42 A0 1E 23 56 0E 2F ]
即僅僅要去掉 4個字節的開始碼就能夠了.

2.2 組合封包模式(Aggregation packet:一個RTP Payload包括多個NAL單元.STAP-A, STAP-B, MTAP-A,MTAP-B四種類型,編號依次為 24, 25,26, 27.)
其次, NALU的長度特別小時,能夠把幾個 NALU單元封在一個 RTP包中.
0 1 23
0 1 23 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RTPHeader |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|STAP-ANAL HDR | NALU 1 Size | NALU 1 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|NALU 1 Data |
: :
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |NALU 2 Size | NALU 2 HDR |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|NALU 2 Data |
: :
|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|:...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2.3Fragmentation Units (FUs).(Fragmentation unit:一個RTPPayload包括一個NAL單元的一部分.FU-A, FU-B兩種,分別標記為 28, 29.)
而當 NALU的長度超過 MTU,就必須對 NALU單元進行分片封包.也稱為 Fragmentation Units (FUs).
0 1 23
0 1 23 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| FUindicator | FU header | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+|
| |
| FUpayload |
| |
|+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|:...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure14. RTP payload format for FU-A
TheFU indicator octet has the following format:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI|Type |
+---------------+
TheFU header has the following format:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|R|Type |
+---------------+
{
1,將FU-A包依據rtp的包序號和FU-Aheader字節,組成完整264幀。
2。推斷幀類型假設是idr幀。須要在幀頭加上spspps,格式為:
起始碼(0x00000001+sps+起始碼+pps+起始碼+完整幀數據
3。幀末加入幀間分隔符“0x00, 0x00, 0x01, 0x09, 0x10
4,使用網上精簡過的"ff_264_dec_vc"進行解碼。該項目不支持imgconvert。可從最新ff源代碼查找
並拷貝yuv420p_to_xxx函數進行合適轉碼
}

3. SDP 參數【3】
以下描寫敘述了怎樣在 SDP中表示一個 H.264:
."m=" 行中的媒體名必須是 "video"
."a=rtpmap" 行中的編碼名稱必須是 "H264".
."a=rtpmap" 行中的時鐘頻率必須是 90000.
. 其它參數都包含在 "a=fmtp"行中.
:
m=video49170 RTP/AVP 98
a=rtpmap:98H264/90000
a=fmtp:98profile-level-id=42A01E; sprop-parameter-sets=Z0IACpZTBYmI,aMljiA==
以下介紹一些經常使用的參數.
3.1packetization-mode:表示支持的封包模式.
packetization-mode的值為 0時或不存在時,必須使用單一 NALU單元模式.
packetization-mode的值為 1時必須使用非交錯(non-interleaved)封包模式.
packetization-mode的值為 2時必須使用交錯(interleaved)封包模式.
這個參數不能夠取其它的值.
3.2sprop-parameter-sets:
這個參數能夠用於傳輸 H.264的序列參數集和圖像參數 NAL單元.這個參數的值採用 Base64進行編碼.不同的參數集間用","號隔開.
3.3profile-level-id:
這個參數用於指示 H.264流的 profile類型和級別. Base16(十六進制)表示的 3個字節.第一個字節表示 H.264 Profile類型,
三個字節表示 H.264 Profile級別:
3.4max-mbps:
這個參數的值是一個整型,指出了每一秒最大的宏塊處理速度.

問題一:怎樣把h.264的包打包成rtp包?

答:打包時去除H.264的開始碼,然後加上rtp頭就可以.


RTP打包H.264過程

1.打開.264文件

2.設置初始化套接字

3.從264碼流中推斷起始碼,先讀前3個字節,看是不是0x000001,假設不是的話,再多讀取一個字節,看前4個字節是不是0x00000001。

(讀到156行)


【1】簡單地說。I幀是關鍵幀。屬於幀內壓縮。

就是和AVI的壓縮是一樣的。 P是向前搜索的意思。他們都是基於I幀來壓縮數據。

I幀表示關鍵幀,你能夠理解為這一幀畫面的完整保留。解碼時僅僅須要本幀數據就能夠完畢(由於包括完整畫面)

P幀表示的是這一幀跟之前的一個關鍵幀(或P幀)的區別,P幀沒有完整畫面數據。僅僅有與前一幀的畫面區別的數據)


【2】B是雙向搜索,B幀記錄的是本幀與前後幀的區別

【3】會話描寫敘述協議(SDP)為會話通知、會話邀請和其他形式的多媒體會話初始化等目的提供了多媒體會話描寫敘述。

這裏是對網上資料自己的整理和自己加的東西,感謝網上各位的無私分享。


基於RTP的h.264視頻傳輸系統設計(一)