日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

rtmp官方协议详解

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

    總結(jié)

    以上是生活随笔為你收集整理的rtmp官方协议详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。