rtmp_specification_1.0翻譯

英文原文: rtmp_specification_1.0.pdf

5 RTMP Chunk Stream

本節定義RTMP chunk stream。它爲高層的媒體流協議提供多路複用和包封裝的服務。

當RTMP chuck stream被設計成爲RTMP協議服務的時候,它能處理任何消息流的協議。每個消息包含時間戳和負載類型。RTMP chunk stream和RTMP在一起是非常適合各種音視頻應用做點到點、點到多點的直播,或VOD服務,或會議應用。

當用可靠傳輸協議來傳輸,如TCP(RFC0793),RTMP chunk stream對所有流的消息提供可靠時序的點到點傳輸。RTMP chunk stream不提供任何優先級或類似控制,但可以在上層協議來提供優先級。例如,直播視頻服務對網速慢的用戶,可以選擇丟棄視頻消息以此保證音頻消息的實時接收,無論基於時間發送還是回覆每個消息的時間。

RTMP chunk stream包括它自己的帶內協議控制消息,並且也爲高層協議提供機制內嵌用戶控制消息。

5.1 消息格式(Message Format)

消息格式能被分片成多個chunk,依次在上層協議上支持多路複用。消息格式因爲應該包含下面幾個字段,其是用來創建chunk的必要條件。

  • Timestamp: 消息的時間戳。這個字段是4個字節,單位毫秒;
  • Length: 消息負載的長度。如果消息頭被省略,它也應該包括在這個長度中。這個字段在chunk頭中是3個字節。
  • Type Id: type id的範圍是爲協議控制信息保留的。傳播信息的消息體被RTMP chunk stream協議和上層協議處理。所有其他的type id都能爲上層協議服務,並且可以作爲透明值對rtmp chunk stream來說。實際上,在rtmp chunk stream裏並不需要這些只;所有的非協議消息可以用同一個type,或者應用可以用這個值去傳遞其他的信息。這個字段在chunk header中佔用一個字節。
  • Message Stream ID: 它可以是個任意的值。不同的message流可以被複用到同一個chunk stream中,然後通過不同的message stream id被解複用成不同的message流。當然其也可以本當做透明的值。這個字段佔用4個字節在chunk header中,以小字節序排列。

5.2 握手協議(Handshake)

一個RTMP連接開始於握手。握手完全不同於rtmp的其他協議。它有3個同等大小的chunk組成,而不是變長的chunk並帶有頭部。

客戶端和服務器各自發送同樣3個chunk。客戶端發送C0, C1和C2;服務端發送S0, S1和S2。

5.2.1 握手順序

一開始客戶端發送C0和C1的chunck。

客戶端發送C2前需要先收到服務端恢復的S1。客戶端必須在收到S2之後,才能發送其他的數據。

服務端必須收到C0後,才能發送S0和S1,也可以等到收到C0後才發送S0和S1。服務端必須等到收到C1才發送S2。服務端必須接收到C2後,才能發送其他的數據。

5.2.2 C0和S0格式

C0和S0報文只有一個字節,也就是8-bit的字段:

0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+ 
|   version     | 
+-+-+-+-+-+-+-+-+
C0 and S0 bits

C0/S0報文字段:
Version(8bits): 在C0中,這個字段是客戶端定義RTMP版本。在S0中,這個字段由服務端選擇支持的版本。在本文中,協議定義爲3。值0-2是早期的版本好,已經不再使用;4-31是爲未來的保留號;32-255不允許。服務端如果不認識客戶端發來的版本好,就應該回復版本號3。客戶端可以選擇遵循協議3,或放棄握手。


5.2.3 C1和S1格式

C1和S1包是1536字節長,由一下字段組成:

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 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                        time (4 bytes)                         | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                        zero (4 bytes)                         | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                        random bytes                           | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                        random bytes                           | 
|                            (cont)                             | 
|                             ....                              | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                         C1 and S1 bits
  • Time(4字節):這個字段包含時間戳,這個時間戳應該被後續所有的chuck作爲時間開始。其可以是0,或者是其他任何數字。爲了同步多個chuck流,服務端/客戶端希望發送其他chunk流的時間戳。
  • Zero(4字節): 這個字段必須是0。
  • Random data (1528 bytes): 這個字段可以保護任何自定義信息。因爲客戶端和服務端爲了區分發起握手的消息和響應握手的消息,這個數據塊應該發送隨機數值。但也不必一定是密碼級別的隨機值,或者可以是變量。

5.2.4 C2和S2格式

C2和S2都是1536字節長,是對S1/C1分別的回覆,由以下字段組成:

 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 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                        time (4 bytes)                         | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                        time2 (4 bytes)                        | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                        random echo                            | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                        random echo                            | 
|                           (cont)                              |
|                            ....                               | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                       C2 and S2 bits
  • Time (4 bytes): 這個字段是時間戳,S1的對C2,或C1對S2;
  • Time2 (4 bytes): 這個字段必須包含上一個報文(s1或c1)發過來的時間戳;
  • Random echo (1528 bytes): 這個字段必須包含隨機數據對端發過來的,S1(對C2)或者S2(對C1)。雙方都可以用time, time2字段來估計帶寬和連接的延時,當然這比一定有用;

5.2.5. Handshake圖解

rtmp handshake.png
下面的描述握手圖解的流程,3個狀態:

  • Uninitialized: 協議版本在過程中發送。客戶端和服務端都沒有初始化。客戶端用C0發送協議版本。如果服務器支持該版本,服務端回覆S0/S1。如果沒有,服務端回覆該有的行爲。在RTMP中,就是中斷連接。
  • Version Sent: 客戶端和服務端在非初始化狀態後,能進入確定版本狀態。客戶端等待S1,服務端等待C1。當收到報文,客戶端發送C2,服務端發送S2。狀態就成Ack sent狀態。
  • Ack Sent: 客戶端和服務端相互等待S2/C2狀態。
  • Handshake Done: 握手完成,客戶端和服務端可以開始交換信息。

5.3 Chunking

握手後,連接可以服用一路或多路chunk stream。每個chunk stream都能從一個消息流中承載一種類型消息。每個chunk都能由唯一的ID定義,也就是chunk stream ID。chunk是通過網絡發送。當網絡傳輸時,每個chunk在前一個chunk發送完成後才發送。在接收端,chunk分片會被根據chunk stream id組包成完整的消息體。

Chunking運行上層協議把大報文分片成小報文,以此防止大尺寸低優先級報文(如視頻)阻塞到小尺寸高優先級報文(如控制報文)。

Chunking也允許小報文能節省的報文頭髮送,也就是chunk header能壓縮頭信息,信息能包含在消息本身中。

chunk size是可配置的。它能通過set chunk size控制協議來定義(在5.4.1中)。大的chunk size能降低CPU佔用率,但是大尺寸的chunk能對低帶寬連接導致高延時。而過小的chunk對高帶寬流不是很好。chunk size是雙方單方向來獨立維護的。

5.3.1 Chunk格式

每個chunk由header和data組成。頭由3部分組成:

+--------------+----------------+--------------------+--------------+ 
| Basic Header | Message Header | Extended Timestamp | Chunk Data   | 
+--------------+----------------+--------------------+--------------+ 
|<-------------------         Chunk Header        ----------------->|
  • Basic Header (1 to 3 bytes): 這個字段包括stream id和chunk type。chunk type定義了message header的格式。長度完全由chunk stream id決定,其是可變長度的字段
  • Message Header (0, 3, 7, or 11 bytes): 這個字段包含消息要發送的信息(無論是全部還是部分)。該長度通過chunk header中的chunk type來定義
  • Extended Timestamp (0 or 4 bytes): 這個字段chunk message header中的時間戳。 5.3.1.3中有詳細信息。
  • Chunk Data (variable size): chunk的負載數據,數據填充到chunk size的大小。

5.3.1.1. Chunk Basic Header

這個chunk basic header包含chunk stream id 和chunk type(有fmt字段表示)。chunk type定義message header的格式類型。chunk basic header字段可以是1,2或3字節,其有由chunk stream id決定。

協議支持到65597,streamid的範圍是3–65599。ID中0,1,2是保留的。值0定義id爲兩個字節,64-319(第二個字節+64)。值1定義3個字節,範圍64-65599(第三個字節*256+第二個字節+64)。值範圍3-63代表完整的streamid。chunk stream id爲2表示底層協議的控制消息和命令。

bit 0-5(低字節)在chunk basic header中代表chunk stream id。

chunk streamid 2-63 是這個字段的第一個版本。

 0 1 2 3 4 5 6 7 
+-+-+-+-+-+-+-+-+ 
|fmt|   cs id   | 
+-+-+-+-+-+-+-+-+
Chunk basic header 1

chunk stream id值範圍64-319是其頭中的兩個字節。ID爲第二個字節+64。

 0                   1
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|fmt|     0     |   cs id - 64  | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     Chunk basic header 2

chunk streamid 54-65599範圍在3個字節的版本中編碼。ID等於:第三個字節*256+第二個字節+64。

 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|fmt|     1     |         cs id - 64            | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
               Chunk basic header 3
  • cs id (6 bits): 這個字段包含chunk stream ID,值2-63。值0和1的是2或3字節的版本。
  • fmt (2 bits): 這個字段定義4中類型的chunk message header。這個chunk message header的類型介紹在下一節。
  • cs id - 64 (8 or 16 bits): 這個字段包含最小爲64的chunk stream id。舉例,ID 365就是一個1的cs id字段和16bit的301字段。

chunk stream ID是值64-319,是頭中兩個字節或三個字節的格式模式。

5.3.1.2 chunk message header

有chunk message header的不同格式,其有chunk basic header中的fmt字段定義。

在應用中,應該用選擇使用壓縮比例最高的chunk message header。

5.3.1.2.1 Type 0

Type 0 chunk header是11字節長。這個type 0類型必須是在chunk stream的最開始使用,並且無論什麼時候stream timestamp都應該是向後發展的。

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 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                timestamp                      |message length | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|     message length (cont)     |message type id| msg stream id | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|             message stream id (cont)          | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                       Chunk Message Header - Type 0
  • timestamp (3 bytes): 對於type-0的chunk,消息使用絕對時間戳。如果時間戳大於等於16777215 (16進制0xFFFFFF),這個字段必須是16777215,意味着Extended Timestamp字段32bit的時間戳。此外,這個字段代表完整的時間戳。
5.3.1.2.2 Type 1

Type 1 chunk headers是7字節長。message stream ID不在其內。這個chunk帶有上個chunk相同的chunk stream id。流都是變長的消息(舉例,多種視頻格式)應該用這個格式作爲第二個stream的chunk報文。

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 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                timestamp delta                |message length | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|      message length (cont)    |message type id| 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
               Chunk Message Header - Type 1
5.3.1.2.3 Type 2

類型2chunk headers是3字節長。stream ID和message length都不包含;chunk有與前一個chunk相同的stream ID和message length。流是定長的消息(例如,音頻和數據格式)應該用這個類型,作爲第二個stream的chunk報文。

 0                   1                   2
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                timestamp delta                | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                       Chunk Message Header - Type 2
5.3.1.2.4 Type 3

類型3其實沒有message header。stream ID,message length和timestamp都不存在。這個chunk類型都繼承前一個相同chunk stream ID的chunk所有字段。當單個消息被切分多個chunk,所有的消息除了第一個chunk外都用這個類型。

對於示例2(5.3.2.2節),流都是同等大小的消息組成,stream ID和時間間隔應該使用類型3,其緊跟着chunk類型2.

對於示例1(5.3.2.1節)。如果第一個消息與第二個消息的時間戳一樣,那麼type3可以作爲第二個chunk緊跟着第一個chunk(type0),二不需要type 2。如果type 3緊跟着type0的chunk,那麼type3 chunk的時間戳與type0 chunk的時間戳絕對一致。

5.3.1.2.5. Common Header Fields
  • timestamp delta (3 bytes): 針對type-1或type-2的chunk,前一個時間戳與後一個時間戳的差值,那麼就該使用這個字段。如果這個delta大於等於16777215(16進制0xFFFFFF),這個字段就必須是16777215,意味着Extended Timestamp字段會有32bits的值。此外這個字段就是表示準確的時間戳。
  • message length (3 bytes): 針對type-0或type-1的chunk,消息的長度就在這個字段中。注意這個不是chunk負載的長度。chunk負載的長度是chunk size的最大值,針對所有chunk除了最後一個chunk,剩餘的字節就放在最後一個chunk中(當然其也可能是整個長度,針對小消息來說)
  • message type id (1 byte): 針對type-0或type-1,這個消息的type在這個字段中。注意
  • message stream id (4 bytes): 針對type-0的chunk,消息stream ID會被髮送。特別是,所有同一個chunk stream的消息都將來源於同一個消息流。也可能把多個不同的消息放入同一個chunk stream中,當然這就失去了頭部壓縮的好處。如果一個message流關閉,而另外下一個流打開,沒有什麼理由上次存在的chunk stream 不能被新的type-0 chunk重用。

5.3.1.3. Extended Timestamp

extended timestamp字段用於timestamp字段大於等於16777215(0xFFFFFF);那是爲了時間戳不能滿足於在type0,1,2 chunk中24bits大小的字段。這個字段是完整的32bit的時間戳或時間戳差值。這個字段在chunk type 0中表示時間戳,或type-1或type-2 chunk中表示timestamp的差值,timestamp字段的值必須是16777215(0xFFFFFF)。這個字段當先前使用的type 0, 1, 或2 chunk對同一個chunk stream ID, 表示type3該字段是上次extended timesamp field。

5.3.2. Examples

5.3.2.1. Example 1

本例展示了單個音頻消息。這個例子展示了消息有很多重複信息。
chunk audio example1.png
下一張圖表顯示chunk在流中的構成。從message 3往後,數據傳輸頭部都優化了。在message 3後,每個message的頭部只有1個字節
在這裏插入圖片描述

5.3.2.2. Example 2

本例演示了一個消息大於128字節的chunk,被切分成多個chunks。
chunk video example1.png

下圖是chunk的組成:

chunk video example2.pngchunk 1的頭數據表明了這個message總共307字節長。

從上面兩個例子看,chunk type 3能有兩種使用方法。第一種是連續的message。第二種是一個新消息其頭部能被後續的數據繼續使用。

5.4 Protocal Control Message(控制消息)

協議控制消息必須是message stream ID等於0(0表示控制協議),並且chunk stream ID必須是2。協議控制消息在收到後需要即刻處理;他們的時間戳可以忽略。

5.4.1 Set Chunk Size(1)

控制消息1,Set Chunk Size,用於通知對端最新的chunk size。

chunk size最大值默認是128bytes,但是客戶端和服務器可以改變這個值,並用這個消息來通知對方。舉個例子,假想一個客戶端想要發送音頻包131bytes,且其chunk size是128字節。在這種情況下,客戶端可以發送這個控制消息給服務端,通知它chunk size現在修改爲131字節了。然後,客戶端就可以在一個chunk中發送音頻數據了。

最大的chunk size至少是128字節,內容至少1字節。chunk size的最大值每個方向獨立維護。

 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 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|0|                    chunk size (31 bits)                     | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        Payload for the ‘Set Chunk Size’ protocol message
  • 0: 這個bit必須是0;
  • chunk size (31 bits): 這個字段包含chunk size的最大值,發送端接下來的chunk都以這個chunk size作爲有效尺寸來發送,直到有新的set chunk size消息來到。值的範圍是1到2147483647(0x7fffffff);然後,所有值大於16777215(0xffffff)的都被認爲是16777215,因爲沒有哪個chunk大小會比message還有大,因爲message都是小於16777215字節的。

5.4.2 Abort Message(2)

協議控制消息2,Abort Message,被用於通知對端如果還在等待chunk包來完成message組播啊,可以丟棄掉已經接收到的chunk報文。對端接收到這個類型協議的報文,其負載是chunk stream ID。一個應用應該在開始關閉連接是發送這個消息,爲了對端不用在等待未完成的message。

 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 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                  chunk stream id (32 bits)                    | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       Payload for the ‘Abort Message’ protocol message

chunk stream ID (32 bits): 這個字段包含chunk stream ID。也就是這個chunk stream ID的消息將被丟棄。

5.4.3 Acknowledgement(3)

客戶端或服務器必須在接收到window size消息後,發送Acknowledgement給對端。這個windows size是發送者還沒有接收到acknowledgement前發送最大的字節數。消息定義了sequence number,其是目前已經接收到的字節數。

 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 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                  sequence number (4 bytes)                    | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       Payload for the ‘Acknowledgement’ protocol message

sequence number (32 bits): 這個字段表示當前接收到的sequence number。

5.4.4 Window Acknowledgement Size(5)

客戶端或服務器發送此消息去通知對端window size在發送acknowledgments之前。發送端期望收到acknowledgment在發送端發送完window size的字節數後。接收端必須在接收到windows size的數據後,發送acknowledgement(5.4.3節),或者從會話一開始還沒有acknowledgement被髮送前。

 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 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|           Acknowledgement Window size (4 bytes)               | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 Payload for the ‘Window Acknowledgement Size’ protocol message

5.4.5 Set Peer Bandwidth(6)

客戶端或服務器發送這個消息以限制對端發送帶寬。對端收到這個消息後通過限制發送數量來限制輸出帶寬,但是不需要針對這個消息的回覆。對端接收到這個消息,如果window size與上次這個消息的發送者發送的不一樣,就應該返回一個window acknowledgement size massage。

 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 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|                  Acknowledgement Window size                  | 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
|    Limit Type |
+-+-+-+-+-+-+-+-+
      Payload for the ‘Set Peer Bandwidth’ protocol message

Limit type是如下幾種:

  • 0 - Hard: 對端應該限制出口帶寬到window size。
  • 1 - Soft: 對端應該限制其出口帶寬到消息中的window size,或限制效果更小的帶寬。
  • 2 - Dynamic: 如果錢一個Limit Type是Hard,那麼就認爲這個消息類型是Hard,否則丟棄這個消息。

6. RTMP Message Formats

這部分定義了RTMP消息的格式,其在RTMP chunk steam上進行傳輸。
當RTMP被設計來用RTMP chunk stream上來傳輸,它能用任何傳輸協議來傳輸。RTMP chunk stream和RTMP一起工作,是非常適合廣泛的音視頻應用的,點到點和點到多點的直播,VOD的點播業務,和互相交互的視頻會議。

6.1 RTMP Message Format

服務端和客戶端直接通過發送RTMP message來進行通信。消息包括音頻,視頻,數據和其他信息。

RTMP消息有兩部分: 頭部和載體。

6.1.1 Message Header

消息頭包括以下部分:

  • Message Type: 一個字節的字段,表示消息類型。範圍是1-6是爲協議控制消息而保留的。
  • Length: 3個字節字段表示負載長度,其是大字節序。
  • Timestamp: 4字節字段表示消息的時間戳,4字節是大字節序。
  • Message Stream Id: 3個字節的字段,定義消息流的唯一性。其爲大字節序。
    rtmp message header.png

6.1.2 Message Payload

消息的另外一部分是負載,其是消息中實在的數據部分。舉例,它可以是音頻數據或視頻數據。負載的格式不是本文的內容範圍。

6.2 User Control Message(4)

RTMP用message type ID 4作爲User Control message。這些消息包含RTMP streaming層使用的信息。協議消息(protocal message)的ID是1, 2, 3, 5和6的RTMP chunk stream協議(5.4節)。

User Conntrol消息應該使用message stream ID 0(其是control stream) 和,當在rtmp chunk stream上發送,chunk stream ID是2。User Control消息在其在流中接收到時就有效,其時間戳可以忽略。

客戶端和服務端發送message去通知對端關於user control時間。消息承載事件類型和事件數據。

+------------------------------+-------------------------
|     Event Type (16 bits)     | Event Data
+------------------------------+-------------------------
     Payload for the ‘User Control’ protocol message

消息的頭兩個字節是Event Type。Event Type後面緊跟着Event Data。Event Data的size是可變的。注意,這個消息是需要在rtmp chunk stream上傳送的,最大的chunk size(5.4.1節)必須是足夠大而讓這個消息能放入一個chunk中。

7. RTMP Command Messages

本節介紹服務器與客戶端之間不同類型的消息和命令交互。

在服務器與客戶端之間交互消息的不同類型包括audio消息其承載音頻數據,video消息其承載video數據,data消息承載用戶信息數據,還有shared object消息和command消息。shared object消息提供方法爲管理多個客戶端和服務器之間的分發消息。Command消息承載AMF編碼命令。客戶端或服務器還可以發送RPC命令來進行交流。

7.1 Messages的類型

服務器和客戶端通過網絡發送消息來互相通信。消息類型能是很多種,包括音頻消息,視頻消息,命令消息,shared object消息,數據消息和user control消息。

7.1.1 Command Messages(20, 17)

Command消息承載服務器與客戶端之間的AMF編碼消息。這些消息Message type 20表示AMF0格式,Message type 17是AMF3格式。這些消息被用來發送完成如connect, createStream, publish, play, pause on the peer。Command消息中如onstatus, result等,被用來通知發送者命令指示的結果和狀態。命令消息有command name, transaction ID, 和command object其攜帶相關參數。客戶端和服務器能也能通過流執行RPC命令,其用command message發送給對端。

7.1.2 Data Message(18,15)

客戶單和服務器通過發送這個消息來發送Metadata,或用戶數據給對端。Metadata包括音頻、視頻的細節信息,如流創建時間,流時間長短等。這些消息使用message type 19表示AMF0編碼和message type 15作爲AMF3編碼。

7.1.3 Shared Object Message

使用率低,先不翻譯。

7.1.4 Audio Message(8)

客戶端或服務器發送此消息來承載音頻數據到對端,message type 8就是專門爲audio message。

7.1.5 Video Message(9)

客戶端或服務器發送此消息來承載視頻數據到對端,message type 9就是專門爲video message。

7.1.6 Aggregate Message(22)

使用率低,先不翻譯

7.1.7 User Control Message Events

使用率低,先不翻譯

7.2 命令類型(Types of Commands)

客戶端和服務器通過AMF編碼來交換命令信息。發送端發送命令消息,其由command name,transaction ID,和command object對象其包含相關參數信息。舉例,這個connect連接命令包含app參數,其是告知服務器關於客戶端想要連接的application name。返回的字符串有_result,_error,或者method name,舉例,verifyClient或contactExternalServer。

_result或_error的命令字符串標識着返回信息。transaction ID標識着返回信息的後續命令。它與IMAP或其他協議中的tag一樣。命令字符中的method nameb標識發送端想要在接收端調用一個方法。

接下來的命令分類如下:

  • NetConnection: rtmp上層協議中服務端和客戶單之間的connection命令系列。
  • NetStream: 其表示通道,音頻、視頻和相關數據都在上面傳輸。我們也發送命令如Play,pause等,其控制數據流。

7.2.1 NetConnection命令

NetConnection管理一個在客戶端應用和服務器之間的雙向連接。此外,還能提供遠程過程調用RPC。

如下命令是NetConnection:

  • connect
  • call
  • close
  • createStream

7.2.1. connect

客戶端發送connect命令給服務端建立連接而得到應用實例。

客戶端到服務端的命令結構如下:

    +----------------+---------+---------------------------------------+
    |  Field Name    |  Type   |           Description                 |
    +--------------- +---------+---------------------------------------+
    | Command Name   | String  | Name of the command. Set to "connect".|
    +----------------+---------+---------------------------------------+
    | Transaction ID | Number  | Always set to 1.                      |
    +----------------+---------+---------------------------------------+
    | Command Object | Object  | Command information object which has  |
    |                |         | the name-value pairs.                 |
    +----------------+---------+---------------------------------------+
    | Optional User  | Object  | Any optional information              |
    | Arguments      |         |                                       |
    +----------------+---------+---------------------------------------+

下面是connect命令的command對象的name-value對描述介紹。
rtmp connect object.png
音頻編碼屬性的flag值:
rtmp connect audio property.png
視頻編碼屬性的flag值:
rtmp connect video property.png
對象編碼的值對應關係:
rtmp connect object.png
從服務器到客戶端的命令返回值:

rtmp connect response.png
connect消息的交互流程圖:

rtmp connect message flow.png
消息流的交互如下:

  1. 客戶端發送connect命令到服務端來建立app的連接;

  2. 服務端在接收到connect命令後,服務端發送協議消息’window acknowledgement size’到客戶端。服務端也開始對應的app的連接;

  3. 服務端發送‘set peer bandwidth’給客戶端;

  4. 客戶端在處理完成’set peer bandwidth’後,發送協議消息’window acknowledgement size’給服務端;

  5. 服務端發送另外一個user control消息給客戶端;

  6. 服務端發送result命令消息通知客戶端關於connection連接的結果。命令定義transaction ID(其對connect command一致爲1)。此消息也定義一些屬性,如Flag media Server version(string)。此外其定義其他的返回屬性,如level(string), code(string), desription(string), objectencoding(number),等等。

7.2.1.2 Call

使用率低,暫時不翻譯

7.2.1.3 createStream

客戶單發送此命令給服務器來爲消息通信創建邏輯通道,如audio,video和metadata,都會在這個createstream命令創建的邏輯通道上來傳輸。

從客戶端到服務端的命令結構:

    +--------------+----------+----------------------------------------+
    | Field Name   |   Type   |             Description                |
    +--------------+----------+----------------------------------------+
    | Command Name |  String  | Name of the command. Set to            |
    |              |          | "createStream".                        |
    +--------------+----------+----------------------------------------+
    | Transaction  |  Number  | Transaction ID of the command.         |
    | ID           |          |                                        |
    +--------------+----------+----------------------------------------+
    | Command      |  Object  | If there exists any command info this  |
    | Object       |          | is set, else this is set to null type. |
    +--------------+----------+----------------------------------------+

服務端返回消息的結構:

    +--------------+----------+----------------------------------------+
    | Field Name   |   Type   |             Description                |
    +--------------+----------+----------------------------------------+
    | Command Name |  String  | _result or _error; indicates whether   |
    |              |          | the response is result or error.       |
    +--------------+----------+----------------------------------------+
    | Transaction  |  Number  | ID of the command that response belongs|
    | ID           |          | to.                                    |
    +--------------+----------+----------------------------------------+
    | Command      |  Object  | If there exists any command info this  |
    | Object       |          | is set, else this is set to null type. |
    +--------------+----------+----------------------------------------+
    | Stream       |  Number  | The return value is either a stream ID |
    | ID           |          | or an error information object.        |
    +--------------+----------+----------------------------------------+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章