本文梳理了理解RTMP協議的基本概念
訪問 個人博客瞭解更多
message 是 RTMP 中的 M,是消息的單位html
RTMP Message Header +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Message Type| Payload length| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Timestamp | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Stream ID | +-+-+-+-+-+-+-+-+-+-+-+-+
消息主要分爲三類: 協議控制消息、數據消息、命令消息等shell
協議控制消息服務器
數據消息網絡
Message Type ID = 8 9 18tcp
命令消息 Command Message (20, 17)ide
更多的瞭解見 Adobe’s Real Time Messaging Protocol 的 5.4 章節函數
rtmp 的 message 會切分爲 n 個 chunk,再經過 tcp 協議傳輸post
爲何 rtmp 基於 tcp 協議,tcp 協議已經有化整爲零的方式, rtmp 還須要將 message 劃分更小的單元 chunk 呢?優化
分析緣由:編碼
在互聯網中傳輸數據時, 消息(Message)會被拆分紅更小的單元, 稱爲消息塊(Chunk)。RTMP Chunk Stream 層級容許在Message stream 層次,將大消息切割成小消息,這樣能夠避免大的低優先級的消息(如視頻消息)阻塞小的高優先級的消息(如音頻消息或控制消息)。
重複強調,RTMP 是設計用來多路複用的特色,傳輸內容有視頻、音頻、控制命令。其中一個很是重要的概念是 multiplexing
(複用)
不一樣類型的消息會被分配不一樣的優先級,當網絡傳輸能力受限時,優先級用來控制消息在網絡底層的排隊順序。
好比當客戶端網絡不佳時,流媒體服務器可能會選擇丟棄視頻消息,以保證音頻消息可及時送達客戶端。
Chunk 的大小設置,經過 Message Type = 1 的控制消息聲明
若是 message length 大於 max chunk size,則須要將這個message切分爲多個 chunk 。前面幾個 chunk size 必須是 max size,最後一個就是剩餘的大小。
以上圖爲例,Message大小爲 300 bytes,默認Chunk size 爲 128 bytes,進行拆分紅chunk的過程。
接下來,探尋 chunk 的結構
RTMP Chunk Header +-------------+----------------+-------------------+-----------+ | Basic header|Chunk Msg Header|Extended Time Stamp|Chunk Data | +-------------+----------------+-------------------+-----------+ 1 byte (0,3,7,11 byte) (0,4 byte)
設計基於TCP協議的上層協議時,爲了防止粘包問題,通常的方法有:一、使用分隔符; 二、在報文header中聲明長度。
RTMP Chunk Basic Header (1 byte) +-+-+-+-+-+-+-+-+-+-+-+-+-+- | format | chunk stream id | +-+-+-+-+-+-+-+-+-+-+-+-+-+- 2 bits 6 bits
RTMP Chunk Header 的長度不是固定的,由RTMP Chunk Basic Header 前2位二進制決定,有4種類型。chunk stream id 的範圍 3~65599,0~2做爲保留。
00
,Chunk Header length = 12 bytes,在一個 chunk 流的開始、時間戳返回的時候必須有這種塊,好比:onMetaData, 音視頻流剛開始的絕對時間戳,控制消息Basic header + Chunk Msg Header +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | format | chunk stream id | timestamp | message length | msg type id | msg stream id | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2 bits 6 bits 3 bytes 3 bytes 1 bytes 4 bytes
01
,Chunk Header length = 8 bytes,對於可變大小消息的chunk流,在第一個消息以後的每一個消息的第一個塊應該使用這個格式Basic header + Chunk Msg Header +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | format | chunk stream id | timestamp | message length | msg type id | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2 bits 6 bits 3 bytes 3 bytes 1 bytes
10
,Chunk Header length = 4 bytes,對於固定大小消息的chunk流,在第一個消息以後的每一個消息的第一個塊應該使用這個格式Basic header + Chunk Msg Header +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- | format | chunk stream id | timestamp | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 2 bits 6 bits 3 bytes
11
,Chunk Header length = 1 bytes,當一個消息被分紅多個塊,除了第一塊之外,全部的塊都應使用這種類型Basic header + Chunk Msg Header +-+-+-+-+-+-+-+-+-+-+-+-+-+- | format | chunk stream id | +-+-+-+-+-+-+-+-+-+-+-+-+-+- 2 bits 6 bits
注意 timestamp
的長度爲 3 bytes,當 timestamp
被設置爲 0x00ffffff
,chunk header 會加上 Extended Time Stamp
字段,不然 Extended Time Stamp
不會出現。
由於一個流當中能夠傳輸多個Chunk,那麼多個Chunk怎麼標記同屬於一個 Message 的呢?
Message type 1~6:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Basic Header|Message Header|Ex Timestamp|Set chunk size | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Basic Header|Message Header|Ex Timestamp|Chunk Stream ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Basic Header|Message Header|Ex Timestamp| Sequence Number| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
是可變長的。
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++-+-+-+ |Basic Header|Message Header|Ex Timestamp| Event Type| Event Data| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++-+-+-+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |Basic Header|Message Header|Ex Timestamp| Acknowledgement Window size | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |Basic Header|Message Header|Ex Timestamp| Acknowledgement Window size | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | Limit type | ++++++++++++++++
Message type = 8,Audio message, 客戶端或服務端發送本消息用於發送音頻數據。消息類型 8 ,保留爲音頻消息
以 FLV ACC 的 RTMP Audio Chunk 爲例
協議層:
協議層 封裝層 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |RTMP Chunk Header | FLV AudioTagHeader | FLV AudioTagBody | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
封裝層(FLV):
FLV AudioTagHeader ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |SoundFormat | SoundRate | SoundSize | SoundType | AACPacketType | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 bits 2 bits 1 bit 1 bit 8 bits
Message type = 9, Video message, 客戶端或服務端使用本消息向對方發送視頻數據。消息類型值 9 ,保留爲視頻消息。
以 FLV H.264/AVC 的 RTMP Video Chunk 爲例
協議層:
協議層 封裝層 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |RTMP Chunk Header | FLV VideoTagHeader | FLV VideoTagBody | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
封裝層(FLV):
FLV VideoTagHeader +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |Frame Type | CodecID | AVCPacketType | CompositionTime | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 bits 4 bits 1 byte 3 bytes
編碼層:
FLV VideoTagBody +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | Size | AVCDecoderConfigurationRecord or ( one or more NALUs ) | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 bytes
NALU: Network Abstract Layer Unit 網絡抽象層單元