rtmp官方協議詳解

來源:互聯網
上載者:User

標籤:

標準規範學習:rtmp訊息結構,包括幾個部分:時戳:4  byte,單位毫秒。超過最大值後會翻轉。長度:訊息負載的長度。類型ID:Type Id 一部分ID範圍用於rtmp的控制信令。還有一部分可以供上層使用,rtmp只是透傳。這樣可以方便的在rtmp上進行擴充。訊息流程ID:Message Stream ID,用於區分不同流的訊息。 兩個ID的區別:Message stream:傳輸訊息的邏輯通道。Message stream ID:每個訊息都有一個流id,用於指明屬於哪個流。 Chunk:是更底層的一個概念。Message有可能過大,需要分割成一個個片段,chunk就是一個訊息的部分片段。Chunk stream:傳輸chunk的邏輯通道。
Chunk stream ID:用於標示chunk屬於哪個邏輯通道。message stream和chunk stream應該屬於不同的層次,message屬於應用程式層次訊息,chunk屬於更底層rtmp協議層次。一個chunk stream 上能夠跑多個message stream。message stream id在一個chunk stream下要不相等。 訊息會切分成一個個小的塊進行傳輸。 rtmp的時戳單位是毫秒。串連握手流程圖:握手過程:伺服器和用戶端各自發送三個包:c0,c1,c2,s0,s1,s2,伺服器必須在收到c0後才發送s0和s1,也可以等到c1才發送;服務端必須收到c1才能夠發送s2,用戶端必須收到s2才能夠發送c2 c0和s0就是一個位元組:表示協議版本號碼。現在是03。01 234567+-+-+-+-+-+-+-+-+|    version    |+-+-+-+-+-+-+-+-+  C0 and S0 bits c1和s1長度1536,抓包發現,zero欄位不一定為0。 c2和s2的長度也是1536通過vlc和nginx rtmp抓的包發現和規範不對應。安裝規範,time和time2應該是為了計算頻寬和延遲。  互動過程:一般用戶端一起發生c0和c1,然後伺服器直接發送s0,1,2。用戶端收到後發送c2,握手完成。三次互動就可以了。 塊流:一個串連可以穿輸多個塊流。每個塊流有不同的id來區分。塊傳輸運行將大的訊息包切割為小的訊息包。防止大的資料比如視頻阻塞串連,導致音頻和信令也無法傳遞。小的訊息也可以成本更加低的傳輸,包頭會壓縮. 塊流大小可以配置。有一個訊息:set chunk size可以協商大小。大的塊可以降低cpu 負載,但是可能會阻塞重要訊息;小的塊不利於傳輸,特別是在低頻寬的情況下。 塊允許 層協議將大的訊息 解 更小的訊息,例如,防 體積大的但優先順序小的消 息 (比如視頻) 阻礙體積較小但優先順序高的訊息 (比如音頻或者控制命 )——傳送過程,音頻和控制的優先順序較高。 塊的大小是  配置的 它  使用一個設定塊大小的控制訊息 行設定 (參考 5.4.1) 更大的塊大小  降  CPU 開銷,但在  寬 接時因 它的大量的寫入也會延   他內容的傳遞 更小的塊不利於高位元速率的流化 所 塊的大小設定 決於 體情況。——這是使用tcp必須要考慮的問題。塊過大會影響音頻和控制的發送。過小會影響效率和位元速率。 塊類型: 塊基本頭:   第一個位元組都是這樣。其中fmt用來指示Message Header。cs id:cs id是chunk stream id的縮寫。範圍是3——65599。可變位元組,後面可以跟一個位元組,也可以跟兩個位元組。跟幾個位元組是有第一個位元組的後面6位的值決定的。這一點中文翻譯寫的不完整。如果最後6位值為0,則表示後面只有一個位元組。id範圍是64——319,其實就是0——255,最大和最小加64。如果最後6位值為1,則表示後面只有兩個位元組。id範圍是64 - 65599,其實就是0——65535,最大和最小加64。j計算方法比較特殊:(第三 個 節) * 256 + 第二 個 節 + 64 塊流id應該是區分每一個流,比如,一個視訊通話,包括視頻和音頻兩個流。這裡的意思應該是一個串連可以傳遞多個流,通過塊流id進行區分。 塊訊息頭塊訊息頭格式由塊基本頭的fmt欄位決定。共四種。 fmt:四種類型:0 1 2 3包頭必須儘可能的壓縮。 type 0:用在流開始,或者時戳重設的時候。message header訊息頭共11byte。三位元組時戳:表示範圍為0——16777215(0xffffff),如果大於等於16777215,則表示還有一個位元組的擴充時戳。chunk header的第三部分就是extend timestamp。這一本部分是否存在由三個位元組的值決定。注意,這個是絕對時戳,而後面的幾種類型trunk都是時戳的增量;區分訊息截止是根據訊息的長度來進行的。那麼輸入處理主動丟棄包的情況?   type 1:message header有7byte,比type 0少了4個位元組的message stream id,使用上一個塊的id。大小可變的訊息(比如視頻的每一幀資料)往往會在第一幀(第一幀的第一個chunk需要用type0)後面的幀的第一個chunk中使用type1。為什嗎?因為可變資料,必須有長度資訊記錄。 type2:只有三個位元組。沒有message stream id和message 長度。全部使用同一個chunk stream的上一個chunk的。適用於長度不變的步伐傳輸。 type 3:0個位元組的message header。時戳,長度,訊息流程id全部使用同一個chunk stream的上一個chunk。當一個訊息切分後劃分到多個chunk的時候,除了帶個chunk,所有的其他chunk應該使用type3。——如何判斷包結束?根據訊息的長度,第一個chunk中的長度應該是一個訊息完成的長度。 四種格式的使用:第一個訊息的第一個chunk 使用type0,攜帶全部的資訊;後面的chunk使用type3;第二個訊息,如果是影像訊息,長度可變,則第一個chunk使用type1,值丟棄message stream id即可。第二個訊息的其他chunk使用type3。 如果是音頻,且長度相同,則第一個訊息用type0+type3,第二個訊息用type2+type3。如果音頻訊息,長度,訊息間時戳增量(delta)都相同,則第一個訊息可以用type0+type3,後面的所有訊息全部用type3即可。這樣的話也要求第一個訊息的時戳必須和訊息間的時戳增量相同。  注意:除type0外,其他的全部是時戳的增量。而不是時戳絕對值。從上面來看,音頻和視頻的chunk id應該是不一樣的。否則無法區分。因為有些塊是沒有message stream id,只有chunk stream id的。 公用欄位定義:1、timestamp delta:表示的是上一個chunk 和當前chunk的時戳差。不是訊息的時間差。如果大於等於16777215,則表示還有一個位元組的擴充時戳。chunk header的第三部分就是extend timestamp。2、訊息長度:訊息的長度。他和chunk的payload的大小是不同的。chunk size length是所有chunk的大小再加最後一個大小。——訊息長度是訊息實際的大小。。3、message type id:標示訊息類型,比如音頻,視頻,控制等。4、message stream id:以小端序儲存。Extended Timestamp:當時戳大於 play2:可以實現位元速率的切換。 message length,chunk size,tcp分包和訊息的切割終於弄明白其中的原理了。本來這幾個概念和方法在規範中描述不是很清楚,結合抓包終於弄清楚 了。message length:及時訊息本身的大小。這個訊息要在chunk中進行傳輸。chunk size:chunk的大小。chunk的大小預設是128。可以通過訊息設定chunk size 的最大值。每個chunk的大小最大不能夠超過max chunk size。明白上面兩點後進行分析:1、如果message length小於等於max chunk size,則一個chunk中就包含著一個message。2、如果message length大於max chunk size,則需要將這個message切分為多個chunk。前面幾個chunk size必須是max size,最後一個就是剩餘的大小。 tcp分包過程:1、收到chunk,明確chunk stream id,對一個chunk stream的資料進行處理。2、判斷fmt類型,確定訊息長度。3、如果長度小於等於max chunk size,則這個chunk body的大小就是message length。4、處理完這個chunk,跳過chunk header 和chunk body,就是下一個chunk。5、如果長度大於max chunk size,則chunk body的大小就是max chunk size。處理這一部分資料,然後跳過max chunk size找到下一個chunk的頭。有訊息長度減去max chunk size計算剩餘的資料長度,判斷剩餘長度是否大於max chunk size,如果大於,則表明這個chunk 大小還是max chunk size。以此類推,直到最後一個長度小於等於max chunk size,那麼這個長度就是這個chunk的實際長度,並且是這個訊息的最後一個訊息切片。然後把所有的有效切片拼接起來,就是完整的訊息。後面收到的將是另外一個訊息。 協議控制訊息:RTMP使用1,2,3,4,5,6的message type id作為控制訊息。控制協議的message stream id必須是0, chunk stream id必須是2(2的作用。0,1用來表示位元組個數,2是信令,3-6xxxx是實際的。)。控制信令一收到就生效——就是沒有協商過程。。。——時戳可以忽略。 set chunk size (1):設定chunk的最大sizemessage type id 為1。共四個位元組:第一位必須為0。 預設值是128,服務端和用戶端都可以設定chunk size。注意,一個互動中chunk size是相互獨立的,也就是,用戶端可以設定他發送過去的chunk size,服務端也可以設定他發送過去的chunk size。兩個是沒有影響的。chunk size最小建議128,必須大於等於1。chunk size的範圍是1到0x7fffffff(2147483647),但是因為message header中message length只有三個位元組,所以chunk size的最大值是16777215  如果大於此,就去他。 Abort Message (2)message type id為2,四個位元組,攜帶的內容是chunk stream id。用於通知對端,如果這個chunk stream還有訊息正在等待接收未到達的訊息內容,則停止,並丟棄原先接受的內容。可以用在頻寬有限是優先發送音頻和信令,丟棄視頻。 Acknowledgement (3) Window Acknowledgement Size (5)Window Acknowledgement Size用於設定視窗確認大小,Acknowledgement是視窗確認訊息。會話開始時,雙方都要先對端發送Window Acknowledgement Size,用於指明期望獲得確認的大小。當一端收到內容大小超過Window Acknowledgement Size,就要像對方發送Acknowledgement。1、會話開始計算收到byte個數的時間點是收到Window Acknowledgement Size訊息開始。2、byte size不包括tcp包頭,應該是chunk的大小,即從tcp 的recv函數中獲得的內容大小。3、雙方都要向對方發送Window Acknowledgement Size和Acknowledgement。4、發送端發送完Window Acknowledgement Size訊息後,沒有收到Acknowledgement是不再發送進一步的訊息的——這樣會容易引起錯誤,導致再也發送不出訊息了。  Set Peer Bandwidth (6) 設定對端輸出頻寬。對端是通過設定Window Acknowledgement Size來實現流量控制的。超過Window Acknowledgement Size後未確認發送端將不再發送訊息。所以對端收到set peer bandwidth後,如果之前發送的Window Acknowledgement Size和這裡寫的的Window Acknowledgement Size不一樣,一般會發送一個Window Acknowledgement Size。  message format 上面的協議控制訊息的type id是1,2,3,5,6(這些是chunk stream的控制),沒有4。4是另外一個類型:User Control Messages (4):使用者控制協議,是RTMP stream的控制協議。同樣,chunk stream id要設定為2,message stream id要設定為0。 訊息體格式:兩個位元組的event type,後面跟可變長度的event data, RTMP Command Messages用戶端和伺服器之間可以發送的訊息包括:音頻訊息,影像訊息,資料訊息,命令訊息。命令訊息採用AMF編碼。 command message type 20,17表示是命令訊息。20表示使用AMF0編碼,17表示使用AMF3編碼。命令訊息包括connect, createStream, publish, play, pause ,響應訊息使用onstatus,result。 Data Message (18, 15):資料訊息,用於傳輸Metadata或使用者資料。18表示AMF0,15是AMF3。 Shared Object Message (19, 16):19表示AMF0,16是AMF3。 Audio Message (8):音頻訊息Video Message (9):影像訊息 Aggregate Message (22):一個訊息中包含多個訊息。 Types of Commands( 20,17)netConnetion 命令:connect :請求串連到伺服器的應用執行個體。 call:請求一個遠程調用。 creatStream:建立一個邏輯通道,用於用戶端來發送音頻,視頻,描述資料。netConnection是預設通道,message stream id是0,creatStream使用0作為message stream id。 NetStream Commands:多個Netstream可以共用一個netconnection。但是stream的id是在什麼時候確定的???——疑問 play2:切換到不同的位元速率的流上,而不用更改播放時間。這是一個有用的功能。這個訊息是在paly之後再發送。 deleteStream:刪除流。 receiveAudio:是否接受音頻。如果為false,伺服器不用回複。如果為true,伺服器回複兩個狀態:NetStream.Seek.Notify and   NetStream.Play.Start receiveVideo:同樣。 publish:發布一個流到server。需要onStatus響應。 seek:位移。毫秒為單位。 pause:暫停。 example:首先,connect是已連線的服務器端的應用(nginx rtmp有配置多個應用。) 視頻裸資料是如何打包進rtmp包的?ffmpeg在flv和h264檔案將的轉換是有問題的。 視頻性格的資料包格式和flv的格式非常的像,基本上就是flv格式的變種。參考flv檔案格式官方協議詳解。視頻相關包包括:onMetaData,AVCDecoderConfigurationRecord,h264資料。和flv檔案中的區別是flv檔案用tag頭,rtmp中相關資訊是放在rtmp頭中。至於內部內容是一樣的。  AMF0編碼格式
  1. *AMF資料類型: 
  2.  *Type      Byte code 
  3.  *Number    0x00 
  4.  *Boolean   0x01 
  5.  *String    0x02 
  6.  *Object    0x03 
  7.  *MovieClip 0x04 
  8.  *Null      0x05 
  9.  *Undefined 0x06 
  10.  *Reference 0x07 
  11.  *MixedArray    0x08 
  12.  *EndOfObject   0x09 
  13.  *Array         0x0a 
  14.  *Date          0x0b 
  15.  *LongString    0x0c 
  16.  *Unsupported   0x0d 
  17.  *Recordset     0x0e 
  18.  *XML           0x0f 
  19.  *TypedObject (Class instance)  0x10 
  20.  *AMF3 data 0×11 
 amf編碼:對個資料的合集,資料的邊界通過不同的類型,以及不同類型的長度來區分。第一個位元組是資料類型,然後根據資料類型確定資料的長度。其中,string是可變長度,兩個位元組長度值。如果是object,則object內部是個字典,key是字串,value是資料,這裡還要對資料根據類型對資料解析,同上。  

我 的公眾號



rtmp官方協議詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.