rtmp信令格式

rtmp以TCP方式推流,分爲一個個消息包。

一、握手

握手開始於客戶端發送 C0,C1 塊。

服務端在發送 S0 和 S1 之前必須等待接收 C0,也可以等待接收 C1。

服務端在發送 S2 之前必須等待接收 C1。

在發送 C2 之前客戶端必須等待接收 S1 。

客戶端在發送任何數據之前必須等待接收 S2。

服務端在發送任何數據之前必須等待接收 C2。

1、 C0 : s <= c

客戶端RTMP的版本號,一個字節,一般是3

rtmp1.0規範所定義的版本是 3;0-2 是早期產品所用的,已被丟棄;4-31保留在未來使用;32-255 不允許使用(爲了區分其他以某一字符開始的文本協議)。

如果服務無法識別客戶端請求的版本,應該返回 3 。客戶端可以選擇減到版本 3 或選擇取消握手

2、 C1 : s <= c

一共1536字節

4-time + 4-zero + 1528-random
  • 時間:4 字節 本字段包含時間戳。該時間戳應該是發送這個數據塊的端點的後續塊的時間起始點。可以是 0,或其他的 任何值。爲了同步多個流,端點可能發送其塊流的當前值。
  • 零:4 字節 本字段必須是全零。
  • 隨機數據:1528 字節。 本字段可以包含任何值。 因爲每個端點必須用自己初始化的握手和對端初始化的握 手來區分身份,所以這個數據應有充分的隨機性。但是並不需要加密安全的隨機值,或者動態值

3、 S0,S1,S2 : s => c

這裏可以一次性把S0,S1,S2 3個都發給客戶端。

  • S0 1 byte (服務端RTMP的版本號),範圍同C0

  • S1 1536 bytes (4-time + 4-zero + 1528-random),格式同C1

  • S2 1536 bytes (4-time + 4-zero + 1528-echo),是對C1的回覆,格式同C2

4、 C2 : s <= c

一共1536字節,是對S1的回覆

4-time + 4-time2 + 1528-echo
  • 時間:4 字節 本字段必須包含對等段發送的時間(對 C2 來說是 S1,對 S2 來說是 C1)。
  • 時間 2:4 字節 本字段必須包含先前發送的並被對端讀取的包的時間戳。
  • 隨機回覆:1528 字節 本字段必須包含對端發送的隨機數據字段(對 C2 來說是 S1,對 S2 來說是 C1) 。 每個對等端可以用時間和時間 2 字段中的時間戳來快速地估計帶寬和延遲。

  • 開始推送音視頻數據

二、推送音視頻數據

1、消息格式

  • [Message Type ID] (1 bytes)
  • [Payload Length] (1 bytes)
  • [Time Stamp] (1 bytes)
  • [Stream ID] (1 bytes)
  • [Message Body]

[Message Type ID][Payload Length][Time Stamp][Stream ID] 這四部分稱爲 Message Header。

Message Type ID: 在1-7的消息用於協議控制,這些消息一般是RTMP協議自身管理要使用的消息,用戶一般情況下無需操作其中的數據。Message Type ID爲8,9的消息分別用於傳輸音頻和視頻數據。Message Type ID爲15-20的消息用於發送AMF編碼的命令,負責用戶與服務器之間的交互,比如播放,暫停等等。

Payload Length: 負載的長度

Time Stamp: 時間戳

Stream ID: 流的ID

2、消息塊拆包

一幀數據有時候會很大,比如幾十M甚至更大。但是爲了方便在網絡上傳輸,需要把數據拆分成一個個較小的塊,這裏稱之爲消息塊(Chunk)。

  • [Chunk Basic Header]
  • [Chunk Message Header]
  • [Extended TimeStamp]
  • [Chunk Data]

[Chunk Basic Header][Chunk Message Header][Extended TimeStamp] 稱之爲 Chunk Header。

2.1 Chunk Basic Header

Header Type + Channel ID (一共1-3個字節)

2.1.1 Header Type (FMT)

第一個字節的高2位決定[Chunk Message Header]的長度

  • 00 12 bytes
  • 01 8 bytes
  • 10 4 bytes
  • 11 1 byte
2.1.2 Channel ID
  • 02 Ping 和ByteRead通道
  • 03 Invoke通道 我們的connect() publish()和自字寫的NetConnection.Call() 數據都是在這個通道的
  • 04 Audio和Vidio通道
  • 05 06 07 服務器保留,經觀察FMS2用這些Channel也用來發送音頻或視頻數據

計算公式如下:

/**
* data      :   Basic Header Data
* fmt       :   Header Type
* cid       :   Channel ID
* return    :   Basic Header Data Length
*/
int rtmp_chunk_basic_header_read(const uint8_t* data, uint8_t* fmt, uint32_t* cid)
{
    *fmt = data[0] >> 6;
    *cid = data[0] & 0x3F;

    if (0 == *cid)
    {
        *cid = 64 + (uint32_t)data[1];
        return 2;
    }
    else if (1 == *cid)
    {
        *cid = 64 + (uint32_t)data[1] + ((uint32_t)data[2] << 8) /* 256 */;
        return 3;
    }
    else
    {
        return 1;
    }
}

2.2 Chunk Message Header

以最大fmt =00 length(Chunk Message Header) == 12 爲例
Chunk Message Header的結構是:

timestamp + message_length + message_type + msg_stream_id

其中message_type是一個枚舉變量:

  • type爲1,2,3,5,6的時候是協議控制消息
  • type爲4的時候表示 User Control Messages [Event_type + Event_Data] Event_type有Stream Begin,Stream End…
  • type爲8,音頻數據
  • type爲9,視頻數據
  • type爲18 元數據消息[AMF0]
  • type爲20 命令消息 Command Message(RPC Message)

These messages are sent to perform some operations like connect, createStream, publish, play, pause on the peer.

命令消息主要分成兩種NetConnection和NetStream。

connect,call,close,createStream命令可以在NetConnection中發送。
coonect(name,TranscationID,Command Object pair),play,publish,seek,pause等命令可以在NetStream中發送。

2.3 Extended TimeStamp

時間戳

2.3 Chunk Data

塊數據,接收方把塊數據組合成完整的一幀flv tag數據

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