adobe修改了握手部分的協議,可是沒有公開。根據rtmp specification 1.0裏面的握手過程,flash player是播不了h264編碼的視頻。修正後的握手協議能夠參照:http://blog.csdn.net/winlinvip/article/details/7714493html
rtmp 使用塊(chunk)的概念來發送數據,默認的塊大小是128(不包括頭部數據大小),若是要發送的數據超過了設定的塊大小,就要分爲多塊進行發送。rtmp chunk的整體格式以下所示,rtmp
chunk頭部信息包括三部分:基本頭,消息頭,擴展時間戳。網絡
+----------------+--------------------+-------------------------+----------------+ide
| Basic Header | Message Header | Extended Timestamp | Chunk Data |編碼
+----------------+--------------------+-------------------------+----------------+spa
| |.net
|<------------------- Chunk Header ------------------------->|code
rtmp 塊的基本頭包手兩個信息:塊格式(chunk format) 和 塊流ID(chuck stream id)orm
0 1 2 3 4 5 6 7視頻
+-+-+-+-+-+-+-+-+server
| fmt | cs id |
+-+-+-+-+-+-+-+-+
fmt: rtmp塊頭的格式,有4種類型
cs_id:
cs_id 塊流ID 基本頭的長度(字節) >=2 cs_id 1 0 【第二字節的值】 + 64 2 1 【第三字節的值】*256+【第二字節的值】+64 3
rtmp 消息頭通常包括:時間戳(3Bytes),消息長度(3Bytes),消息類型(1Byte),消息流Id(4Bytes)。
可是並不老是會包含這些信息。可是能夠根據塊基本頭的fmt,來判斷消息頭中包含了哪些信息(如表格所示)。
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) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
fmt timestamp message length message type id msg stream id 消息頭長度 0 Y Y Y Y 11 1 Y Y Y x 7 2 Y x x x 3 3 x x x x 0
注意:a.發包的原則是同一個塊流ID,第一個包通常使用fmt0,而後再根據狀況選擇使用fmt1,fmt2,fmt3.
b.timestamp,只有當是fmt0時,才表示一個絕對時間戳,其它格式都是一個時間差值,即相對於上一個包的時間增量。
c.對於fmt1,fmt2,fmt3;缺失的信息,使用最近收到的的同一個塊流id的fmt0格式的包。
d.因此有信息使用大端編碼,除了消息流id是使用小端編碼。
擴展時間戳,4字節,當timestamp > 0xffffff,使用擴展時間戳,不然不使用
a. 發送alaw音頻包,編碼器的打包大小爲320字節,時間間隔爲40ms,假設塊大小設定爲1000,幾個音頻包的時間戳依次爲1000、1040、1080、1120.....,則可能的發送格式以下所示:
rtmp packet format timestamp message length packet size #1 fmt0 1000 320 320+1+11 #2 fmt2 40 x 320+1+3 #3 fmt3 x x 320+1 #4 fmt3 x x 320+1 注:上例咱們也能夠每一個包都用fmt0來發送,這樣的話,每一個包都要指定準確的時間戳和長度。
b. 發送視頻包,時間間隔爲40ms,假設塊大小設定爲1000,幾個視頻包的時間戳依次爲1000、1040.....,大小依次爲2500,1600,....則可能的發送格式以下所示:
rtmp packet format timestamp message length packet size #1 fmt0 1000 2500 1000+1+11 #2 fmt3 x x 1000+1 #3 fmt3 x x 500+1 #4 fmt0 1040 1500 1000+1+11 #5 fmt3 x x 600+1
注:上例中若是每幀的音頻間隔是相等,第二幀的第一個包(#4),咱們也能夠用fmt1來發送,將消息頭中的timestamp指定爲時間差。並指定幀長。
rtmp中各種消息的區分是經過消息頭中的消息類型id(message type id)來區分。控制消息(control message)包括設置塊大小(1),停止消息(2),應答消息(3),設定窗口應答大小(5),設置對方帶寬(6),用戶控制消息(4)。
控制消息發送時,消息流id(message stream id)必須爲0,塊Id必須爲2.
設置塊大小,默認塊大小爲128字節。直接在包頭部後面跟4字節的要設定的塊大小。
用於停止消息。接在包頭部後面跟4字節的要停止的塊流大小。
應答消息,用於接收端(flash player)報告,總共接收到的字節數。直接在包頭部後面跟4字節的收到的字節數。
指定應答的間隔,即距離上一次應答後收到的字節數。
用於限定對方發送帶寬
命令消息包括音頻消息(8),視頻消息(9),集成控制(22),共享對象消息(19【amf0】,16【amf3】),數據消息(18【amf0】,15【amf3】),命令(遠程調用)消息(20【amf0】,17【amf3】)。之後會針對性講解三類主要的消息(遠程調用 ,音頻,視頻消息)。
遠程調用消息,這類消息在我看來就是flash player的一個遠程方法調用。故稱之爲遠程調用消息。flash 的實現的兩個基本類:NetConnection和NetStream,分別負責建立鏈接和進行網絡流的點播控制。遠程調用消息主要是這兩個類的公有方法在服務端的遠程調用。這兩個類的具體介紹參見adobe的官網。其中有詳細的介紹有哪些公有方法,以及相關的參數和可能的返回值。全部的參數和返回值都是經過AMF0或AMF3來表示。
http://livedocs.adobe.com/flash/9.0_cn/ActionScriptLangRefV3/flash/net/NetConnection.html
http://livedocs.adobe.com/flash/9.0_cn/ActionScriptLangRefV3/flash/net/NetStream.html
鏈接請求:
返回鏈接失敗:
鏈接可用的返回值以下表所示,詳見:http://livedocs.adobe.com/flash/9.0_cn/ActionScriptLangRefV3/flash/events/NetStatusEvent.html#info
"NetConnection.Connect.Failed"
"error"
鏈接嘗試失敗。 "NetConnection.Connect.Success"
"status"
鏈接嘗試成功。 "NetConnection.Connect.Rejected"
"error"
鏈接嘗試沒有訪問應用程序的權限。 "NetConnection.Connect.InvalidApp"
"error"
鏈接時指定的應用程序名無效。
告知對方是否須要視頻數據。由boolean類型的參數指定是否須要視頻數據。該命令無需返回(應答)。
告知對方是否須要音頻數據。由boolean類型的參數指定是否須要音頻數據。該命令無需返回(應答)。格式相似NetStream.receiveVideo。
告知對方須要點播的文件。請求格式見下圖:
返回消息:
可用的返回值見下表:
"NetStream.Play.Start"
"status"
播放已開始。 "NetStream.Play.Failed"
"error"
出於此表中列出的緣由以外的某一緣由(例如訂閱者沒有讀取權限),播放發生了錯誤。 "NetStream.Play.StreamNotFound"
"error"
沒法找到傳遞給 play()
方法的 FLV。"NetStream.Play.Reset"
"status"
由播放列表重置致使。 "NetStream.Play.InsufficientBW"
"warning" 僅限 Flash Media Server。 客戶端沒有足夠的帶寬,沒法以正常速度播放數據。
在正式播放以前,必須發送stream begin(event type爲0)的用戶控制消息告知flash player爲播放作好準備。
視頻消息,消息id爲9。h264基本的封裝格式以下所示(關於flv的格式詳見adobe flash video file format specification version 10.1):
| rtmp header | FLV video tag header | nalu size | nalu data(不包含start code) |
若是nalu的大小超出了設定的chunk大小,就要進行分塊發送。分塊的方式見2.4例子
音頻消息,消息id爲8。基本的封裝格式以下所示(關於flv的格式詳見adobe flash video file format specification version 10.1):
| rtmp header | FLV audio tag header | audio data |
用戶控制消息。可用的用戶控制事件包括:stream begin(0),stream EOF(1),stream dry(2),SetBufferLength(3),StreamIsRecorded(4),PingRequest(6),PingResponse(7)
基本的播放流程:收到鏈接請求-》應答鏈接成功-》收到播放請求-》檢測點播的流是否存在-》發送stream begin消息-》發送paly.start消息—-》連續發送音視數據-》。。。-》直接收到關閉鏈接請求或播放到文件末尾。
【client】 | | 【server】
|-----------1: connect------------------------------------------------>|
|<-----2: NetConnection.Connect.Success ------------|
|---------3: play------------------------------------------------------->|
|<-------4: stream begin -------------------------------------------|
|<-------5: NetStream.Play.Start---------------------------|
|<-------6: SetChunksize-------------------------------------------|
|<--------------video message-------------------------------------|
|<-------------audio message-------------------------------------|
| ... |