H264 NALU RTP

對h.264壓縮視頻碼流中i幀的提取(firstime)
2010-06-30 09:15
 
這 個問題要說清楚還是有點複雜:首先判斷 NALU 類型是否是 5,如果是,那麼以後連續出現的 NALU 類型爲 5 的 NALU 就屬於 IDR 幀(一種特殊的 I 幀);如果 NALU 不是 5,則要進一步判斷 slice_type 是否是 7,如果是,那麼連續出現的 slice_type = 7 的 slice 就屬於 I 幀;如果 slice_type = 2,那麼就要判斷與當前 slice 同屬一幀的 slice 是否都是 I slice,如果都是,那麼這些 slice 就屬於一個 I 幀。當然這必須是在碼流沒有錯誤的情況下才可行。

實際應用中,碼流中一般不會出現複雜的情況,所以可以直接判斷 slice_type   是否等於 2 或 7 就可以了。




H.264的NALU,RTP封包說明(轉自牛人)
2010-06-30 16:28

H.264 RTP payload 格式


H.264 視頻 RTP 負載格式

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


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:
這個參數的值是一個整型, 指出了每一秒最大的宏塊處理速度.

 



【轉】
 H264關於RTP協議的實現
2010-07-22 13:35

        完整的C/S架構的基於RTP/RTCP的H.264視頻傳輸方案。此方案中,在服務器端和客戶端分別進行了功能模塊設計 。服務器端 :RTP封裝模塊主要是對H.264碼流進行打包封裝;RTCP分析模塊負責產牛和發送RTCP包並分析接收到的RTCP包;QoS反饋控制模塊則根據RR報文反饋信息動態的對發送速率進行調整;發送緩衝模塊則設置端口發送RTP、RTCP包。客戶端 :RTP模塊對接收到的RTP包進行解析判斷;RTCP模塊根據SR報文統計關鍵信息,產牛併發送RR包。然後,在VC++6.0下用Socket編程,完成基於RTP/UDP/IP的H.264視頻傳輸,並在局域網內運行較好。

基於RTP/UDP/lP的H.264視頻傳輸結構設計

        對於H.264視頻的實時傳輸應用來說,TCP的重傳機制引入的時延和抖動是無法容忍的,因此我們採用UDP傳輸協議。但是UDP協議本身是面向無連接的,不能提供質量保證。而基於UDP之上的高層協議RTP/RTCP可以一起提供流量控制和擁塞控制 服務。圖給出了基於RTP/UDP/IP的H.264視頻傳輸的框架。

  

H264實時編碼及NALU,RTP傳輸(續)(ZZ) - 加菲 - 視頻會議 - 加菲
 


H.264視頻流的RTP封裝策略

        從圖4—1可以看出,H.264視頻數據首先經RTP進行封裝 ,打包成適合網絡傳輸的數據包才能進行傳輸。所以,如何設計合適的RTP封裝策略對H.264視頻數據進行封裝是十分重要的。一般來說,在H.264中,RTP封裝應該遵循幾個設計原則:
1、較低的開銷,因此MTU的尺寸應該限制在100—64K字節範圍內。
2、易於區分分組的重要性,而不必對分組內的數據解碼。
3、應能檢測到數據的類型,而不需解碼整個數據流,並能根據編碼流之間的相關性丟棄無用數據,如網關應能檢測A型分割的丟失,並能丟棄相應的B型和C型分割。

4、應支持將一個NALU拆分爲若干個RTP包:不同大小的輸入圖片決定了NALU的長度可能會大於MTU,只有拆分後纔會避免IP層在傳輸時出現分片。
5、支持將多個NALU彙集在一個RTP分組中,即在一個RTP包中傳輸超過一個NALU,當多個圖片的編碼輸出小於M1IU時就考慮此模式,以提高網絡傳輸效率。

RTP載荷封裝設計

         本文的網絡傳輸是基於IP協議,所以最大傳輸單元(MTU )最大爲1500字節,在使用IP/UDP/RTP的協議層次結構的時候,這其中包括至少20字節的IP頭 ,8字節的UDP頭 ,以及12字節的RTP頭 。這樣,頭信息至少要佔用40個字節,那麼RTP載荷的最大尺寸爲1460字節。

H264實時編碼及NALU,RTP傳輸(續)(ZZ) - 加菲 - 視頻會議 - 加菲
 

          一方面,如果每個IP分組都填滿1500字節,那麼協議頭的開銷爲2.7%,如果RTP載荷的長度爲730字節,協議頭的開銷仍達到5.3%,而假設 RTP載荷的長度不到40字節,那麼將有50%的開銷用於頭部,這將對網絡造成嚴重資源浪費。另一方面,如果將要封裝進RTP載荷的數據大於1460字 節,並且我們沒有在應用層數據裝載迸RTP包之前進行載荷分割 ,將會產生大於MTU的包。在IP層其將會被分割成幾個小於MTU尺寸的包 , 這樣將會無法檢測數據是否丟失。因爲IP和UDP協議都沒有提供分組到達的檢測,如果分割後第一個包成功接收而後續的包丟失,由於只有第一個包中包含有完 整的RTP頭信息,而RTP頭中沒有關於載荷長度的標識,因此判斷不出該RTP包是否有分割丟失,只能認爲完整的接收了。並且在IP層的分割無法在應用層 實現保護從而降低了非平等包含方案的效果。由於UDP數據分組小於64K字節,而且一個片的長度對某些應用場合來說有點太小,所以應用層的打包 也是RTP打包機制的一個必要部分。最新的RFC3984標準中提供了針對H.246媒體流的RTP負載格式,主要有三種:
單個NAL單元分組、聚合分組、片分組。

NAL單元單一打包

將一個NAL單元封裝進一個包中,也就是說RTP負載中只包含一個NAL單元,NAL頭部兼作RTP頭部。RTP頭部類型即NAL單元類型1-23,如下圖所示:

H264實時編碼及NALU,RTP傳輸(續)(ZZ) - 加菲 - 視頻會議 - 加菲
 

NAL單元的重組 
此分組類型用於將多個NAL單元聚合在一個RTP分組 中。一些H.264的NAL單元的大小,如SEI NAL單元 、參數集等都非常小,有些只有幾個字節,因此應該把它們組合到一個RTP包中,將會有利於減小頭標(RTP/UDP/IP)的開銷。目前存在着兩種類型聚合分組:

NAL單元的分割

將一個NAL單元分割,使用多個RTP分組 進行傳輸。共有兩個類型FU—A和FU—B,單元類型中分別爲28和29。根據IP層MTU的大小,對大尺寸的NALU必須要進行分割,可以在分別在兩個層次上進行分割:
1)視頻編碼層VCL上的分割

爲了適應網絡MTU的尺寸,可以使用編碼器來選擇編碼Slice NALU 的大小,從而使其提供較好的性能。一般是對編碼Slice的大小進行調整,使其小於1460字節 ,以免IP層的分割。


2)網絡提取層NAL上的分割 
在網絡提取層上對NALU的分割主要是採用分片單元方案 ,H.264標準中提出了分割機制,可以使NAL單元的尺寸小於1460字節。注意:此方式是針對同一個NAL單元進行分割的 ,不適用於聚合分組。一個NAL單元採用分割分組後,每個RTP分組序列號依次遞增l,RTP時間戳相同且惟一 。NAL單元的分割是RTP打包機制的一個重要環節,總結其分割機制主要有如下幾個特點:
①分割NALU時,是以RTP次序號升序進行 傳輸。在序列號不循環的前提下,屬於前一幀圖像的所有圖像片包以及A/B/C數據分割包的序列號要小於後幀圖像中的圖像片及數據分割包的序列號。
②一個符號機制來標記一個分割的NALU是第一個還是最後一個NAL單元。
3.存在另外一個符號機制用來檢測是否有丟失的分塊。
④輔助增強信息包和頭信息包可以任意時間發送。
⑤同一幀圖像中的圖像片可以以任意順序發送,但是對於低時延要求的網絡系統,最好是以他們原始的編碼順序來發送。

 


1)單一時間聚合分組 (STAP):包括單一時間聚合分組A(STAP—A)和單一時間聚合分組B(STAP—B),按時間戳進行組合,他們的NAL單元具有相同的時間戳,一般用於低延遲環境。STAP—ASTAP—B的單元類型分別爲24和25。
2)多時間聚合分組 (MTAP):包括16比特偏移多時間聚合分組(MTAPl6)和24比特偏移多時間聚合分組 (MTAP24)不同時間戳也可以組合,一般用於高延遲的網絡環境,比如流媒體應用.它的打包方案相對複雜,但是大大增強了基於流媒體的H.264的性 能。MTAPl6 MTAP24的單元類型分別爲26和27。

RTP包的封裝流程設計

根據H.264NAL單元的分割重組的性質以及RTP打包規則,本文實行的對RTP打包的設計 如下:
1、若接收到的NAL單元小於MAX—SIZE(此時MAX-sIZE爲設定的最大傳輸單元 ),則對它進行單一打包,也就是將此NAL單元直接放進RTP包的載荷部分,生成一個RTP包。
2、若接收到的NAL單元大於MAx—SIZE字節,則對它進行分割,然後對分割後的NAL單元進行步驟1方式打包。分割方案如下:

H264實時編碼及NALU,RTP傳輸(續)(ZZ) - 加菲 - 視頻會議 - 加菲
 

 

 

其中Nsize是分割前的NAL單元大小 ,N是分割後NAL單元的大小 。K分割後的單元數 。分割後最後一個單元的大小可能會小於N,這時必須使用RTP載荷填充 是其同前面的分塊大小相同,此時RTP頭中的填充標識位值爲 1。

3、對SEI,參數集等小NAL單元重組,將它們合併到一個RTP 包中。雖然步驟3中的重組方案可以減小IP/UDP/RTP頭部開銷,但是對於包丟失率比較高的網絡環境,這意味着一個RTP包的丟失可能會導致多片的丟失,往往一個片中就有一個P圖像,解碼後的視頻質量必然會嚴重下降。因此,在丟失率的網絡中可以採用NAL單元的重組方案 ,而在高丟失率的網絡環境中採用NAL單元重組時要進行有效的差錯控制.在本文中不使用重組方案。

RTP/RTCP包的封裝實現

RTP包封裝設計

H264實時編碼及NALU,RTP傳輸(續)(ZZ) - 加菲 - 視頻會議 - 加菲
 

RTcP包的封裝設計

        RTCP報文封裝在UDP數據報 中進行傳輸,發送時使用比它所屬的RTP流的端口號大1 的協議號(RTP使用偶數號,RTCP使用奇數號)。以下是RTCP頭部數據結構:

H264實時編碼及NALU,RTP傳輸(續)(ZZ) - 加菲 - 視頻會議 - 加菲
 

 

H264實時編碼及NALU,RTP傳輸(續)(ZZ) - 加菲 - 視頻會議 - 加菲

  





------------------------------------



H264實時編碼及NALU,RTP傳輸(ZZ)
2010-07-25 11:46

 

H264 視頻文件 幀格式 傳輸封裝等 雜碎

rfc3984
Standards Track [Page 2] RFC 3984 RTP Payload Format for H.264 Video February 2005 1.
按照RFC3984協議實現H264視頻流媒體

nalu單元 包起始 0x 00 00 00 01

H.264 NAL格式及分析器
http://hi.baidu.com/zsw_davy/b ... c409cc7cd92ace.html 
http://hi.baidu.com/zsw_davy/blo ... 081312c8fc7acc.html 

----------------------------------比特流信息 ----------------------------------------------

①NALU(Network Abstract Layer Unit):兩標準中的比特流都是以NAL爲單位,每個NAL單元包含一個RBSP,NALU的頭信息定義了RBSP所屬類型。類型一般包括序列參數集 (SPS)、圖像參數集(PPS)、增強信息(SEI)、條帶(Slice)等,其中,SPS和PPS屬於參數集,兩標準採用參數集機制是爲了將一些主要 的序列、圖像參數(解碼圖像尺寸、片組數、參考幀數、量化和濾波參數標記等)與其他參數分離,通過解碼器先解碼出來。此外,爲了增強圖像的清晰 度,AVS-M添加了圖像頭(Picture head)信息。讀取NALU流程中,每個NALU前有一個起始碼0x000001,爲防止 內部0x000001序列競爭,H.264編碼器在最後一字節前插入一個新的字節——0x03,所以解碼器檢測到該序列時,需將0x03刪掉,而AVS- M只需識別出起始碼0x000001。


②讀取宏塊類型(mb type)和宏塊編碼模板(cbp):編解碼圖像以宏塊劃分,一個宏塊由一個16*16亮度塊和相應的一個8*8cb和一個8*8cr色度塊組成。


(a) 兩標準的幀內、幀間預測時宏塊的劃分是有區別的。H.264中,I_slice亮度塊有Intra_4*4和Intra_16*16兩種模式,色度塊只有 8*8模式;P_slice宏塊分爲16*16、16*8、8*16、8*8、8*4、4*8、4*4共7種模式。而AVS-M中,I_slice亮度塊 有I_4*4和I_Direct兩模式,P_slice時宏塊的劃分和H.264中的劃分一致。


(b) 兩標準的宏塊cbp值計算也不相同。H.264中,Intra_16*16宏塊的亮度(色度)cbp直接通過讀mb type得到;非Intra_16*16宏塊的亮度cbp=coded_block_pattern,色度 cbp=coded_block_pattern/16 。其中,亮度cbp最低4位有效,每位決定對應宏塊的殘差係數能不能爲0;色度cbp爲0時,對應殘差係數爲0,cbp爲1時,DC殘差係數不爲0,AC 係數爲0,cbp爲2時,DC、AC殘差係數都不爲0。AVS-M中,當宏塊類型不是P_skip時,直接從碼流中得到cbp的索引值,並以此索引值查表 得到codenum值,再以codenum查表分別得到幀內/幀間cbp。此cbp爲6位,每位代表宏塊按8*8劃分時能不能包含非零係數,當變換系數不 爲0時,需進一步讀cbp_4*4中每位值來判斷一個8*8塊中4個4*4塊的係數能不能爲0。
---------------------------------------------------------------------------------------------
總的來說H264的碼流的打包方式有兩種,一種爲annex-b byte stream format 的格式,這個是絕大部分編碼器的默認輸出格式,就是每個幀的開頭的3~4個字節是H264的start_code,0x00000001或者0x000001。
另一種是原始的NAL打包格式,就是開始的若干字節(1,2,4字節)是NAL的長度,而不是start_code,此時必須藉助某個全局的數據來獲得編 碼器的profile,level,PPS,SPS等信息纔可以解碼。
----------------------------------------------------------------------------
AVC vs. H.264
AVC and H.264 are synonymous. The standard is known by the full names "ISO/IEC 14496-10" and "ITU-T Recommendation H.264". In addition, a number of alternate names are used (or have been) in reference to this standard. These include:

  • MPEG-4 part 10
  • MPEG-4 AVC
  • AVC
  • MPEG-4 (in the broadcasting world MPEG4 part 2 is ignored)
  • H.264
  • JVT (Joint Video Team, nowadays rarely used referring to actual spec)
  • H.26L (early drafts went by this name)

All of the above (and those I've missed) include the Annex B byte-stream format . Unlike earlier MPEG1/2/4 and H.26x codecs, the H.264 specification proper does not define a full bit-stream syntax. It describes a number of NAL (Network Abstraction Layer) units, a sequence of which can be decoded into video frames. These NAL units have no boundary markers, and rely on some unspecified format to provide framing.

Annex B of of the document specifies one such format, which wraps NAL units in a format resembling a traditional MPEG video elementary stream, thus making it suitable for use with containers like MPEG PS/TS unable to provide the required framing. Other formats, such as ISO base media based formats, are able to properly separate the NAL units and do not need the Annex B wrapping.

The H.264 spec suffers from a deficiency. It defines several header-type NAL units (SPS and PPS) without specifying how to pack them into the single codec data field available in most containers. Fortunately, most containers seem to have adopted the packing used by the ISO format known as MP4.
1. H.264起始碼
   在網絡傳輸h264數據時,一個UDP包就是一個NALU,解碼器可以很方便的檢測出NAL分界和解碼。但是如果編碼數據存儲爲一個文件,原來的解碼器將 無法從數據流中分別出每個NAL的起始位置和終止位置,爲此h.264用起始碼來解決這一問題。

   H.264編碼時,在每個NAL前添加起始碼 0x000001,解碼器在碼流中檢測到起始碼,當前NAL結束。爲了防止NAL內部出現0x000001的數據,h.264又提出'防止競爭 emulation prevention"機制,在編碼完一個NAL時,如果檢測出有連續兩個0x00字節,就在後面插入一個0x03。當解碼器在NAL內部檢測到 0x000003的數據,就把0x03拋棄,恢復原始數據。
0x000000   >>>>>>   0x00000300
0x000001   >>>>>>   0x00000301
0x000002   >>>>>>   0x00000302
0x000003   >>>>>>   0x00000303

附上h.264解碼nalu中檢測起始碼的算法流程  
for(;;)
{
if next 24 bits are 0x000001
{
       startCodeFound = true
       break;
}
else
{
       flush 8 bits  
}
}// for(;;)
if(true == startCodeFound)
{
    //startcode found
    // Flush the start code found
    flush 24 bits  
    //Now navigate up to next start code and put the in between stuff
    // in the nal structure.
    for(;;)
    {
      get next 24 bits & check if it equals to 0x000001
      if(false == (next 24 bits == 000001))
      {
         // search for pattern 0x000000
         check if next 24 bits are 0x000000
         if(false == result)
         {
                // copy the byte into the buffer
                copy one byte to the Nal unit             
         }
         else
         {
                break;
         }
      }
      else
      {
             break;
      }
   }//for(;;)
}

   2. MPEG4起始碼
       MPEG4的特色是VOP,沒有NALU的概念,仍使用startcode對每幀進行分界。MPEG4的起始碼是0x000001. 另外MPEG4中很多起始碼也很有用,比如video_object_sequence_start_code 0x000001B0 表示一個視頻對象序列的開始,VO_start_code 0x000001B6 表示一個VOP的開始. 0x000001B6之後的兩位,是00表示 I frame, 01 表示 P frame, 10 表示 B frame.
1.引言

H.264的主要目標:

1.高的視頻壓縮比

2.良好的網絡親和性

解決方案:

VCL   video coding layer    視頻編碼層

NAL   network abstraction layer   網絡提取層

VCL:核心算法引擎,塊,宏塊及片的語法級別的定義

NAL:片級以上的語法級別(如序列參數集和圖像參數集),同時支持以下功能:獨立片解碼,起始碼唯一保證,SEI以及流格式編碼數據傳送

VCL設計目標:儘可能地獨立於網絡的情況下進行高效的編解碼

NAL設計目標:根據不同的網絡把數據打包成相應的格式,將VCL產生的比特字符串適配到各種各樣的網絡和多元環境中。

NALU頭結構:NALU類型(5bit)、重要性指示位(2bit)、禁止位(1bit)。

NALU類型:1~12由H.264使用,24~31由H.264以外的應用使用。

重要性指示:標誌該NAL單元用於重建時的重要性,值越大,越重要。

禁止位:網絡發現NAL單元有比特錯誤時可設置該比特爲1,以便接收方丟掉該單元。

2.NAL語法語義

NAL層句法:

在編碼器輸出的碼流中,數據的基本單元是句法元素。

句法表徵句法元素的組織結構。

語義闡述句法元素的具體含義。

分組都有頭部,解碼器可以很方便的檢測出NAL的分界,依次取出NAL進行解碼。

但爲了節省碼流,H.264沒有另外在NAL的頭部設立表示起始位置的句法元素。

如果編碼數據是存儲在介質上的,由於NAL是依次緊密相連的,解碼器就無法在數據流中分辨出每個NAL的起始位置和終止位置。

解決方案:在每個NAL前添加起始碼:0X000001

在某些類型的介質上,爲了尋址的方便,要求數據流在長度上對齊,或某個常數的整數倍。所以在起始碼前添加若干字節的0來填充。

檢測NAL的開始:

0X000001和0X000000

我們必須考慮當NAL內部出現了0X000001和0X000000

解決方案:

H.264提出了“防止競爭”機制:

0X000000——0X00000300

0X000001——0X00000301

0X000002——0X00000302

0X000003——0X00000303

爲此,我們可以知道:

在NAL單元中,下面的三字節序列不應在任何字節對齊的位置出現

0X000000

0X000001

0X000002

Forbidden_zero_bit =0;

Nal_ref_idc:表示NAL的優先級。0~3,取值越大,表示當前NAL越重要,需要優先受到保護。如果當前NAL是屬於參考幀的片,或是序列參 數集,或是圖像參數集這些重要的單位時,本句法元素必需大於0。

Nal_unit_type:當前NAL 單元的類型

3.H.264的NAL層處理

結構示意圖:

NAL以NALU(NAL unit)爲單元來支持編碼數據在基於分組交換技術網絡中傳輸。

它定義了符合傳輸層或存儲介質要求的數據格式,同時給出頭信息,從而提供了視頻編碼和外部世界的接口。

NALU:定義了可用於基於分組和基於比特流系統的基本格式

RTP封裝:只針對基於NAL單元的本地NAL接口。

三種不同的數據形式:

SODB 數據比特串-->最原始的編碼數據

RBSP 原始字節序列載荷-->在SODB的後面填加了結尾比特(RBSP trailing bits 一個bit“1”)若干比特“0”,以便字節對齊

EBSP 擴展字節序列載荷-->在RBSP基礎上填加了仿校驗字節(0X03)它的原因是: 在NALU加到Annexb上時,需要添加每組 NALU之前的開始碼StartCodePrefix,如果該NALU對應的slice爲一幀的開始則用4位字節表示,ox00000001,否則用3位 字節表示ox000001.爲了使NALU主體中不包括與開始碼相沖突的,在編碼時,每遇到兩個字節連續爲0,就插入一個字節的0x03。解碼時將 0x03去掉。也稱爲脫殼操作

處理過程:

1.   將VCL層輸出的SODB封裝成nal_unit, Nal_unit是一個通用封裝格式,可以適用於有序字節流方式和IP包交換方式。

2.   針對不同的傳送網絡(電路交換|包交換),將nal_unit 封裝成針對不同網絡的封裝格    式。



第一步的具體過程:

VCL層輸出的比特流SODB(String Of Data Bits),到nal_unit之間,經過了以下三步處理:

1.SODB字節對齊處理後封裝成RBSP(Raw Byte Sequence Payload)。

2.爲防止RBSP的字節流與有序字節流傳送方式下的SCP(start_code_prefix_one_3bytes,0x000001)出現字節競 爭情形,循環檢測RBSP前三個字節,在出現字節競爭時在第三字節前加入emulation_prevention_three_byte (0x03),具體方法:

nal_unit( NumBytesInNALunit ) {

forbidden_zero_bit

nal_ref_idc

nal_unit_type

NumBytesInRBSP = 0

for( i = 1; i < NumBytesInNALunit; i++ ) {

if( i + 2 < NumBytesInNALunit && next_bits( 24 ) = = 0x000003 ) {

rbsp_byte[ NumBytesInRBSP++ ]

rbsp_byte[ NumBytesInRBSP++ ]

i += 2

emulation_prevention_three_byte

} else

rbsp_byte[ NumBytesInRBSP++ ]

}

}

3. 防字節競爭處理後的RBSP再加一個字節的header(forbidden_zero_bit+ nal_ref_idc+ nal_unit_type),封裝成nal_unit.

第二步的具體過程:



case1:有序字節流的封裝



byte_stream_nal_unit( NumBytesInNALunit ) {

while( next_bits( 24 ) != 0x000001 )

zero_byte

if( more_data_in_byte_stream( ) ) {

start_code_prefix_one_3bytes nal_unit( NumBytesInNALunit )

}

}

類似H.320和MPEG-2/H.222.0等傳輸系統,傳輸NAL作爲有序連續字節或比特流,同時要依靠數據本身識別NAL單元邊界。在這樣的應用系 統中,H.264/AVC規範定義了字節流格式,每個NAL單元前面增加3個字節的前綴,即同步字節。在比特流應用中,每個圖像需要增加一個附加字節作爲 邊界定位。還有一種可選特性,在字節流中增加附加數據,用做擴充發送數據量,能實現快速邊界定位,恢復同步

Case2:IP網絡的RTP打包封裝

分組打包的規則

(1)額外開銷要少,使MTU尺寸在100~64k字節範圍都可以;

(2)不用對分組內的數據解碼就可以判別該分組的重要性;

(3)載荷規範應當保證不用解碼就可識別由於其他的比特丟失而造成的分組不可解碼;

(4)支持將NALU分割成多個RTP分組;

    (5)支持將多個NALU彙集在一個RTP分組中。

RTP的頭標可以是NALU的頭標,並可以實現以上的打包規則。

一個RTP分組裏放入一個NALU,將NALU(包括同時作爲載荷頭標的NALU頭)放入RTP的載荷中,設置RTP頭標值。爲了避免IP層對大分組的再 一次分割,片分組的大小一般都要小於MTU尺寸。由於包傳送的路徑不同,解碼端要重新對片分組排序,RTP包含的次序信息可以用來解決這一問題。

NALU分割

對於預先已經編碼的內容,NALU可能大於MTU尺寸的限制。雖然IP層的分割可以使數據塊小於64千字節,但無法在應用層實現保護,從而降低了非等重保 護方案的效果。由於UDP數據包小於64千字節,而且一個片的長度對某些應用場合來說太小,所以應用層打包是RTP打包方案的一部分。

新的討論方案(IETF)應當符合以下特徵:

(1)NALU的分塊以按RTP次序號升序傳輸;

(2)能夠標記第一個和最後一個NALU分塊;

(3)可以檢測丟失的分塊。

NALU合併

一些NALU如SEI、參數集等非常小,將它們合併在一起有利於減少頭標開銷。已有兩種集合分組:

(1)單一時間集合分組(STAP),按時間戳進行組合;

(2)多時間集合分組(MTAP),不同時間戳也可以組合。

NAL規範視頻數據的格式,主要是提供頭部信息,以適合各種媒體的傳輸和存儲。NAL支持各種網絡,包括:

1.任何使用RTP/IP協議的實時有線和無線Internet 服務

2.作爲MP4文件存儲和多媒體信息文件服務

3.MPEG-2系統

4.其它網

NAL規定一種通用的格式,既適合面向包傳輸,也適合流傳送。實際上,包傳輸和流傳輸的方式是相同的,不同之處是傳輸前面增加了一個起始碼前綴

在類似Internet/RTP面向包傳送協議系統中,包結構中包含包邊界識別字節,在這種情況下,不需要同步字節。

NAL單元分爲VCL和非VCL兩種

VCL NAL單元包含視頻圖像採樣信息,

非VCL包含各種有關的附加信息,例如參數集(頭部信息,應用到大量的VCL NAL單元)、提高性能的附加信息、定時信息等

參數集:

參數集是很少變化的信息,用於大量VCL NAL單元的解碼,分爲兩種類型:

1.序列參數集,作用於一串連續的視頻圖像,即視頻序列。

兩個IDR圖像之間爲序列參數集。IDR和I幀的區別見下面。

2.   圖像參數集,作用於視頻序列中的一個或多個個別的圖像

序列和圖像參數集機制,減少了重複參數的傳送,每個VCL NAL單元包含一個標識,指

向有關的圖像參數集,每個圖像參數集包含一個標識,指向有關的序列參數集的內容

因此,只用少數的指針信息,引用大量的參數,大大減少每個VCL NAL單元重複傳送的信息。

序列和圖像參數集可以在發送VCL NAL單元以前發送,並且重複傳送,大大提高糾錯能力。序列和圖像參數集可以在“帶內”,也可以用更爲可靠的其他“帶外”通道傳送。








H264實時編碼及NALU,RTP傳輸(續)(ZZ)
2010-07-25 11:47
存 儲單元:一組指定格式的NAL單元稱爲存儲單元,每個存儲單元對應一個圖像。每個存儲單元包含一組VCL NAL單元,組成一個主編碼圖像,VCL NAL單元由表示視頻圖像採樣的像條所組成。存儲單元前面可以加一個前綴,分界存儲單元,附加增強信息(SEI)(如圖像定時信息)也可以放在主編碼圖像 的前面。主編碼圖像後附加的VCL NAL單元,包含同一圖像的冗餘表示,稱爲冗餘編碼圖像,當主編碼圖像數據丟失或損壞時,可用冗餘編碼圖像解碼。編碼視頻序列一個編碼視頻序列由一串連續 的存儲單元組成,使用同一序列參數集。每個視頻序列可獨立解碼。編碼序列的開始是即時刷新存儲單元(IDR)。IDR是一個I幀圖像,表示後面的圖像不用 參考以前的圖像。一個NAL單元流可包含一個或更多的編碼視頻序列。RTP協議:實時傳輸協議(Real-time Transport Protocol,RTP)是在Internet上處理多媒體數據流的一種網絡協議,利用它能夠在一對一(單播)或者一對多(multicast,多播) 的網絡環境中實現傳流媒體數據的實時傳輸。RTP通常使用UDP來進行多媒體數據的傳輸,但如果需要的話可以使用TCP或者ATM等其它協議,整個RTP 協議由兩個密切相關的部分組成:RTP數據協議和RTP控制協議。實時流協議(Real Time Streaming Protocol, RTSP)最早由Real Networks和Netscape公司共同提出,它位於RTP和RTCP之上,其目的是希望通過IP網絡有效地傳輸多媒體數據。RTP數據協議 RTP數據協議負責對流媒體數據進行封包並實現媒體流的實時傳輸,每一個RTP數據報都由頭部(Header)和負載(Payload)兩個部分組成,其 中頭部前12個字節的含義是固定的,而負載則可以是音頻或者視頻數據。RTP數據報的頭部格式如圖1所示: 其中比較重要的幾個域及其意義如下: CSRC記數(CC)  表示CSRC標識的數目。CSRC標識緊跟在RTP固定頭部之後,用來表示RTP數據報的來源,RTP協議允許在同一個會話中存 在多個數據源,它們可以通過RTP混合器合併爲一個數據源。例如,可以產生一個CSRC列表來表示一個電話會議,該會議通過一個RTP混合器將所有講話者 的語音數據組合爲一個RTP數據源。 負載類型(PT)  標明RTP負載的格式,包括所採用的編碼算法、採樣頻率、承載通道等。例如,類型2表明該RTP數據包中承載的是用ITU G.721算法編碼的語音數據,採樣頻率爲8000Hz,並且採用單聲道。    序列號  用來爲接收方提供探測數據丟失的方法,但如何處理丟失的數據則是應用程序自己的事情,RTP協議本身並不負責數據的重傳。    時間戳 記錄了負載中第一個字節的採樣時間,接收方能夠時間戳能夠確定數據的到達是否受到了延遲抖動的影響,但具體如何來補償延遲抖動則是應用程序自己的 事情。從RTP數據報的格式不難看出,它包含了傳輸媒體的類型、格式、序列號、時間戳以及是否有附加數據等信息,這些都爲實時的流媒體傳輸提供了相應的基 礎。RTP協議的目的是提供實時數據(如交互式的音頻和視頻)的端到端傳輸服務,因此在RTP中沒有連接的概念,它可以建立在底層的面向連接或面向非連接 的傳輸協議之上;RTP也不依賴於特別的網絡地址格式,而僅僅只需要底層傳輸協議支持組幀(Framing)和分段(Segmentation)就足夠 了;另外RTP本身還不提供任何可靠性機制,這些都要由傳輸協議或者應用程序自己來保證。在典型的應用場合下,RTP一般是在傳輸協議之上作爲應用程序的 一部分加以實現的,如圖2所示:RTCP控制協議 RTCP控制協議需要與RTP數據協議一起配合使用,當應用程序啓動一個RTP會話時將同時佔用兩個端口,分別供RTP和RTCP使用。RTP本身並不能 爲按序傳輸數據包提供可靠的保證,也不提供流量控制和擁塞控制,這些都由RTCP來負責完成。通常RTCP會採用與RTP相同的分發機制,向會話中的所有 成員週期性地發送控制信息,應用程序通過接收這些數據,從中獲取會話參與者的相關資料,以及網絡狀況、分組丟失概率等反饋信息,從而能夠對服務質量進行控 制或者對網絡狀況進行診斷。 RTCP協議的功能是通過不同的RTCP數據報來實現的,主要有如下幾種類型: SR  發送端報告,所謂發送端是指發出RTP數據報的應用程序或者終端,發送端同時也可以是接收端。 RR  接收端報告,所謂接收端是指僅接收但不發送RTP數據報的應用程序或者終端。 SDES  源描述,主要功能是作爲會話成員有關標識信息的載體,如用戶名、郵件地址、電話號碼等,此外還具有向會話成員傳達會話控制信息的功能。 BYE  通知離開,主要功能是指示某一個或者幾個源不再有效,即通知會話中的其他成員自己將退出會話。 APP  由應用程序自己定義,解決了RTCP的擴展性問題,並且爲協議的實現者提供了很大的靈活性。 RTCP數據報攜帶有服務質量監控的必要信息,能夠對服務質量進行動態的調整,並能夠對網絡擁塞進行有效的控制。由於RTCP數據報採用的是多播方式,因 此會話中的所有成員都可以通過RTCP數據報返回的控制信息,來了解其他參與者的當前情況。在一個典型的應用場合下,發送媒體流的應用程序將週期性地產生 發送端報告SR,該RTCP數據報含有不同媒體流間的同步信息,以及已經發送的數據報和字節的計數,接收端根據這些信息可以估計出實際的數據傳輸速率。另 一方面,接收端會向所有已知的發送端發送接收端報告RR,該RTCP數據報含有已接收數據報的最大序列號、丟失的數據報數目、延時抖動和時間戳等重要信 息,發送端應用根據這些信息可以估計出往返時延,並且可以根據數據報丟失概率和時延抖動情況動態調整發送速率,以改善網絡擁塞狀況,或者根據網絡狀況平滑 地調整應用程序的服務質量。RTSP實時流協議 作爲一個應用層協議,RTSP提供了一個可供擴展的框架,它的意義在於使得實時流媒體數據的受控和點播變得可能。總的說來,RTSP是一個流媒體表示協 議,主要用來控制具有實時特性的數據發送,但它本身並不傳輸數據,而是必須依賴於下層傳輸協議所提供的某些服務。RTSP可以對流媒體提供諸如播放、暫 停、快進等操作,它負責定義具體的控制消息、操作方法、狀態碼等,此外還描述了與RTP間的交互操作。RTSP在制定時較多地參考了HTTP/1.1協 議,甚至許多描述與HTTP/1.1完全相同。RTSP之所以特意使用與HTTP/1.1類似的語法和操作,在很大程度上是爲了兼容現有的Web基礎結 構,正因如此,HTTP/1.1的擴展機制大都可以直接引入到RTSP中。由RTSP控制的媒體流集合可以用表示描述(Presentation Description)來定義,所謂表示是指流媒體服務器提供給客戶機的一個或者多個媒體流的集合,而表示描述則包含了一個表示中各個媒體流的相關信 息,如數據編碼/解碼算法、網絡地址、媒體流的內容等。雖然RTSP服務器同樣也使用標識符來區別每一流連接會話(Session),但RTSP連接並沒 有被綁定到傳輸層連接(如TCP等),也就是說在整個RTSP連接期間,RTSP用戶可打開或者關閉多個對RTSP服務器的可靠傳輸連接以發出RTSP 請求。此外,RTSP連接也可以基於面向無連接的傳輸協議(如UDP等)。RTSP協議目前支持以下操作: 檢索媒體  允許用戶通過HTTP或者其它方法向媒體服務器提交一個表示描述。如表示是組播的,則表示描述就包含用於該媒體流的組播地址和端口號;如果表 示是單播的,              爲了安全在表示描述中應該只提供目的地址。 邀請加入  媒體服務器可以被邀請參加正在進行的會議,或者在表示中回放媒體,或者在表示中錄製全部媒體或其子集,非常適合於分佈式教學。 添加媒體  通知用戶新加入的可利用媒體流,這對現場講座來講顯得尤其有用。與HTTP/1.1類似,RTSP請求也可以交由代理、通道或者緩存來進行處 理。 3. JM86中的處理涉及的函數:流程圖:I幀和IDR幀的區別:1.   在 H.264 中 I 幀並不具有隨機訪問的能力,這個功能由 IDR 承擔。以前的標準中由 I 幀承擔。2.   IDR 會導致 DPB (參考幀列表——這是關鍵所在)清空,而 I 不會。3.   I和IDR幀其實都是I幀,都是使用幀內預測的。但是IDR幀的作用是立刻刷新,使錯誤不致傳播,從IDR幀開始,重新算一個新的序列開始編碼。4.   IDR圖像一定是I圖像,但I圖像不一定是IDR圖像。一個序列中可以有很多的I圖像,I圖像之後的圖像可以引用I圖像之間的圖像做運動參考。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章