流媒體協議 之 RTMP

來源:互聯網
上載者:User
RTMP協議

  RTMP協議封包 由一個包頭和一個包體組成,包頭可以是4種長度的任意一種:12, 8, 4,  1 byte(s).完整的RTMP包頭應該是12bytes,包含了時間戳記,AMFSize,AMFType,StreamID資訊, 8位元組的包頭只紀錄了時間戳記,AMFSize,AMFType,其他位元組的包頭紀錄資訊依次類推 。包體最大長度預設為128位元組,通過chunkSize可改變包體最大長度,通常當一段AFM資料超過128位元組後,超過128的部分就放到了其他的RTMP封包中,包頭為一個位元組.
完整的12位元組RTMP包頭每個位元組的含義:

用途 大小(Byte) 含義
Head_Type 1 包頭
TiMMER 3 時間戳記
AMFSize 3 資料大小
AMFType 1 資料類型
StreamID 4 流ID

一、Head_Type
第一個位元組Head_Type的前兩個Bit決定了包頭的長度.它可以用掩碼0xC0進行"與"計算: 
Head_Type的前兩個Bit和長度對應關係:
Bits Header Length
00 12 bytes
01 8 bytes
10 4 bytes
11 1 byte

Head_Type的後面6個Bit和StreamID決定了ChannelID。  StreamID和ChannelID對應關係:StreamID=(ChannelID-4)/5+1 參考red5
ChannelID Use
02 Ping 和ByteRead通道
03 Invoke通道 我們的connect() publish()和自字寫的NetConnection.Call() 資料都是在這個通道的
04 Audio和Vidio通道
05 06 07 伺服器保留,經觀察FMS2用這些Channel也用來發送音頻或視頻資料

例如在rtmp包裡面經常看到的0xC2, 就表示一位元組的包頭,channel=2.

二、TiMMER
TiMMER佔3個位元組紀錄的是時間戳記,音視頻流的時間戳記是統一排的。可分為絕對時間戳記和相對時間戳記。
fms對於同一個流,發布的時間戳記接受的時間戳記是有區別的
publish時間戳記,採用相對時間戳記,時間戳記值等於當前媒體包的絕對時間戳記與上個媒體包的絕對時間戳記之間的差距,也就是說音視頻時間戳記在一個時間軸上面.單位毫秒。
play時間戳記,相對時間戳記,時間戳記值等於當前媒體包的絕對時間戳記與上個同類型媒體包的絕對時間戳記之間的差距, 也就是說音視頻時間戳記分別為單獨的時間軸,單位毫秒。
flv格式檔案時間戳記,絕對時間戳記,時間戳記長度3個位元組。超過0xFFFFFF後時間戳記值等於TimeStamp & 0xFFFFFF。
flv格式檔案影片總時間長度儲存在onMetaData的duration屬性裡面,長度為8個位元組,是一個翻轉的double類型。

三、AMFSize
AMFSize佔三個位元組,這個長度是AMF長度,可超過RTMP包的最大長度128位元組。如果超過了128位元組,那麼由多個後續RTMP封包組合,每個後續RTMP封包的頭只佔一個位元組。一般就是以0xC。開頭。

四、AMFType
AMFSize佔三個位元組,這個長度是AMF長度,可超過RTMP包的最大長度128位元組。
AMFType是包的類型

0×01 Chunk Size changes the chunk size for packets
0×02 Unknown  
0×03 Bytes Read send every x bytes read by both sides
0×04 Ping ping is a stream control message, has subtypes
0×05 Server BW the servers downstream bw
0×06 Client BW the clients upstream bw
0×07 Unknown  
0×08 Audio Data packet containing audio
0×09 Video Data packet containing video data
0x0A-0x0E Unknown  
0x0F FLEX_STREAM_SEND TYPE_FLEX_STREAM_SEND
0x10 FLEX_SHARED_OBJECT TYPE_FLEX_SHARED_OBJECT
0x11 FLEX_MESSAGE TYPE_FLEX_MESSAGE
0×12 Notify an invoke which does not expect a reply
0×13 Shared Object has subtypes
0×14 Invoke like remoting call, used for stream actions too.
0×16 StreamData 這是FMS3出來後新增的資料類型,這種類型資料中包含AudioData和VideoData



五、StreamID
StreamID是音視頻流的ID,如果AMFType!=0x08 或!=0x09那麼 StreamID為0。
ChannelID 和StreamID之間的計算公式:StreamID=(ChannelID-4)/5+1 參考red5
例如當ChannelID為2、3、4時StreamID都為1 當ChannelID為9的時候StreamID為2

六、封包分析
例如有一個RTMP封包的資料 03 00 00 00 00 01 02 14 00 00 00 00 02 00 07 63 6F 6E 6E 65 63 74 00 3F F0 00 00 00 00 00 00 08 ,,,
資料依次解析的含義 
03表示12位元組頭,channelid=3
000000表示Timmer=0
000102表示AMFSize=18
14表示AMFType=Invoke 方法調用
 00 00 00 00 表示StreamID = 0
//到此,12位元組RTMP頭結束
 
下面的是AMF資料分析,具體的AMF0資料格式請參考
http://www.cnweblog.com/fly2700/archive/2008/04/09/281432.html
02表示String
0007表示String長度7
63 6F 6E 6E 65 63 74 是String的Ascall值"connect"
00表示Double
3F F0 00 00 00 00 00 00 表示double的0.0
08表示Map資料開始







AMF0資料類型

Rtmp包預設的最大長度為128位元組,(或通過chunksize改變rtmp包最大長度), 當AMF資料超過128Byte的時候就可能有多個rtmp包組成,如果需要解碼的rtmp包太長則被TCP協議分割成多個TCP包.那麼解碼的時候需要先將包含rtmp包的tcp封包合并, 再把合并的資料解碼,解碼後可得到amf格式的資料,將這些AMF資料取出來就可以對AMF資料解碼了.伺服器和Flash用戶端之間的命令都是用AMF格式的資料在傳送,例如connect() publish()等命令和伺服器as指令碼裡面自己定義的一些方法. 常用的資料類型整理如下: 
類型說明(ObjType) 資料 dataSize
CORE_String 0x02 2位元組 (2位元組的資料紀錄了String的實際長度)
CORE_Object 0x03 0位元組(開始嵌套0x00000009表示嵌套結束)
NULL 0x05 0位元組 空位元組無意義
CORE_NUMBER 0x00 8位元組
CORE_Map 0x08 4位元組(開始嵌套)
CORE_BOOLEAN 0x01 1位元組


  AMF0資料的嵌套關係如下:
Object={ObjType + ObjValue}
ObjType={CORE_BOOLEAN、CORE_NUMBER、CORE_STRING、CORE_DATE、CORE_ARRAY、CORE_MAP、CORE_OBJECT}
CORE_BOOLEAN={Value(1 Byte)}
CORE_NUMBER={Value(8 Byte)}
CORE_String={StringLen(2 Byte) + StringValue(StringLen Byte)}
CORE_DATE={value(10 Byte)}
CORE_Array={ArrayLen(4 Byte) + Object}
CORE_Map={MapNum(4 Byte) + CORE_Object}
CORE_Object={CORE_String + Object}

例如完成握手後,Flash向FMS發送的第一個RTMP資料,內容如下:


上面一段資料由2個RTMP包組成,2個RTMP包頭分別用藍色表示,第一個藍色的是12位元組的包頭,後面一個藍色的C3是一個位元組的包頭,綠色部分是AMF資料,紅色的是AMF資料類型,整個RTMP解碼過程如下
[2008-06-18 16:59:20] DecodeInvoke:
[2008-06-18 16:59:20] InvokeName:String:connect
[2008-06-18 16:59:20] InvokeID:Double:0
[2008-06-18 16:59:20] Map:MapNum:0
[2008-06-18 16:59:20] Params:{
[2008-06-18 16:59:20] Key:String:objectEncoding
[2008-06-18 16:59:20] Value:Double:0
[2008-06-18 16:59:20] Key:String:app
[2008-06-18 16:59:20] Value:String:mediaserver
[2008-06-18 16:59:20] Key:String:fpda
[2008-06-18 16:59:20] Value:Bool:0
[2008-06-18 16:59:20] Key:String:tcUrl
[2008-06-18 16:59:20] Value:String:rtmp://127.0.0.1/mediaserver
[2008-06-18 16:59:20] Key:String:audioCodecs
[2008-06-18 16:59:20] Value:Double:615
[2008-06-18 16:59:20] Key:String:videoCodecs
[2008-06-18 16:59:20] Value:Double:76
[2008-06-18 16:59:20] }End Params
[2008-06-18 16:59:20] InvokeParams:String:PUBLISHER
[2008-06-18 16:59:20] InvokeParams:String:streamRecode
 
詳細的資料類型,參考Red5
FMS3中為了實現H.264資料的直播而增加了一個資料類型,這個類型的值為0x16,這個類型不在下表中,如果需要請參看 http://www.cnweblog.com/fly2700/archive/2009/02/06/297957.html
enum AMF
{
    /**
     * Boolean value marker constant
     */
    TYPE_BOOLEAN = 0x01, 
    /**
     * String marker constant
     */
 TYPE_STRING = 0x02,
    /**
     * Object marker constant
     */
    TYPE_OBJECT = 0x03,
    /**
     * Movieclip marker constant
     */
    TYPE_MOVIECLIP = 0x04 ,
    /**
     * Null marker constant
     */
 TYPE_NULL = 0x05,
    /**
     * Undefined marker constant
     */
 TYPE_UNDEFINED = 0x06,
    /**
     * Object reference marker constant
     */
 TYPE_REFERENCE = 0x07,
    /**
     * Mixed array marker constant
     */
 TYPE_MIXED_ARRAY = 0x08,
    /**
     * End of object marker constant
     */
 TYPE_END_OF_OBJECT = 0x09,
    /**
     * Array marker constant
     */
 TYPE_ARRAY = 0x0A,
    /**
     * Date marker constant
     */
 TYPE_DATE = 0x0B,
    /**
     * Long string marker constant
     */
 TYPE_LONG_STRING = 0x0C,
    /**
     * Unsupported type marker constant
     */
 TYPE_UNSUPPORTED = 0x0D,
    /**
     * Recordset marker constant
     */
 TYPE_RECORDSET = 0x0E,
    /**
     * XML marker constant
     */
 TYPE_XML = 0x0F,
    /**
     * Class marker constant
     */
 TYPE_CLASS_OBJECT = 0x10,
    /**
     * Object marker constant (for AMF3)
     */
 TYPE_AMF3_OBJECT = 0x11,
    /**
     * true marker constant
     */
 VALUE_TRUE = 0x01,
    /**
     * false marker constant
     */
 VALUE_FALSE = 0x00
};
關於rtmp封包中資料類型為0x16的封包
使用rtmp協議從FMS3中拉音視頻資料的時候,會收到AMFType=0x16的封包,這種包在FMS2中從沒有出現過.
rtmp包頭的第8個位元組就是AMFType,也就是資料類型。例如AMFType=0x08表示音頻包,AMFType=0x04表示Ping包等等。FMS3中為了實現H.264資料的直播而增加了一個資料類型,這個類型的值為0x16。AMFType=0x16的包中既包含了音訊框架也包含了視訊框架。其中音訊框架和視訊框架是一種新的格式存放的,類似FLV檔案儲存體格式,每個音視頻包作為一個Tag,許多的Tag組成了這個AMFType=0x16的資料類型,Tag的格式如下:
用途 大小(Byte) 資料含義 
StreamType 1 流的種類(0x08=音頻,0x09=視頻) 
MediaSize  3 媒體資料區域大小  
TiMMER 3 絕對時間戳記,單位毫秒 
Reserve 4 保留,值為0 
MediaData MediaSize 媒體資料,音頻或視頻 
TagLen 4 幀的大小,值為媒體資料區域大小+參數長度(MediaSize+1+3+3+4) 

關於rtmp封包中資料類型為0x16的封包
使用rtmp協議從FMS3中拉音視頻資料的時候,會收到AMFType=0x16的封包,這種包在FMS2中從沒有出現過.
rtmp包頭的第8個位元組就是AMFType,也就是資料類型。例如AMFType=0x08表示音頻包,AMFType=0x04表示Ping包等等。FMS3中為了實現H.264資料的直播而增加了一個資料類型,這個類型的值為0x16。AMFType=0x16的包中既包含了音訊框架也包含了視訊框架。其中音訊框架和視訊框架是一種新的格式存放的,類似FLV檔案儲存體格式,每個音視頻包作為一個Tag,許多的Tag組成了這個AMFType=0x16的資料類型,Tag的格式如下:
用途 大小(Byte) 資料含義 
StreamType 1 流的種類(0x08=音頻,0x09=視頻) 
MediaSize  3 媒體資料區域大小  
TiMMER 3 絕對時間戳記,單位毫秒 
Reserve 4 保留,值為0 
MediaData MediaSize 媒體資料,音頻或視頻 
TagLen 4 幀的大小,值為媒體資料區域大小+參數長度(MediaSize+1+3+3+4) 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.