版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2017.09.04 |
前言
大家都知道很多視頻應(yīng)用的app中都是使用RTMP格式的協(xié)議,這個(gè)是國(guó)際上共同使用的協(xié)議,我自己雖然做過(guò)了直播類(lèi)型的app枝秤,但是從沒(méi)時(shí)間深入的了解這個(gè)協(xié)議的基礎(chǔ)零蓉,從這一篇開(kāi)始讓我們逐步揭開(kāi)RTMP協(xié)議的神秘面紗,從應(yīng)用層逐步進(jìn)入原理層和底層大刊。
定義
以下內(nèi)容部分來(lái)自百度百科
RTMP是Real Time Messaging Protocol
(實(shí)時(shí)消息傳輸協(xié)議)的首字母縮寫(xiě)为迈。該協(xié)議基于TCP,是一個(gè)協(xié)議族缺菌,包括RTMP基本協(xié)議及RTMPT/RTMPS/RTMPE等多種變種葫辐。RTMP是一種設(shè)計(jì)用來(lái)進(jìn)行實(shí)時(shí)數(shù)據(jù)通信的網(wǎng)絡(luò)協(xié)議,主要用來(lái)在Flash/AIR平臺(tái)和支持RTMP協(xié)議的流媒體/交互服務(wù)器之間進(jìn)行音視頻和數(shù)據(jù)通信伴郁。支持該協(xié)議的軟件包括Adobe Media Server/Ultrant Media Server/red5
等耿战。
RTMP又是Routing Table Maintenance Protocol
(路由選擇表維護(hù)協(xié)議)的縮寫(xiě)。 在 AppleTalk 協(xié)議組中焊傅,路由選擇表維護(hù)協(xié)議(RTMP剂陡,Routing Table Protocol
)是一種傳輸層協(xié)議,它在 AppleTalk 路由器中建立并維護(hù)路由選擇表狐胎。RTMP 基于路由選擇信息協(xié)議(RIP)鸭栖。正如 RIP 一樣,RTMP 使用跳數(shù)作為路由計(jì)量標(biāo)準(zhǔn)握巢。一個(gè)數(shù)據(jù)包從源 網(wǎng)絡(luò)發(fā)送到目標(biāo)網(wǎng)絡(luò)晕鹊,必須通過(guò)的路由器或其它中間介質(zhì)節(jié)點(diǎn)數(shù)目的計(jì)算結(jié)果即為跳數(shù)。
下面我們看一下兩張?jiān)韴D理解一下镜粤。
協(xié)議概述
RTMP(Real Time Messaging Protocol)
實(shí)時(shí)消息傳送協(xié)議是Adobe Systems公司為Flash播放器和服務(wù)器之間音頻捏题、視頻和數(shù)據(jù)傳輸 開(kāi)發(fā)的開(kāi)放協(xié)議。
它有多種變種:
-
RTMP
工作在TCP之上肉渴,默認(rèn)使用端口1935公荧; -
RTMPE
在RTMP的基礎(chǔ)上增加了加密功能; -
RTMPT
封裝在HTTP請(qǐng)求之上同规,可穿透防火墻循狰; -
RTMPS
類(lèi)似RTMPT窟社,增加了TLS/SSL
的安全功能。
協(xié)議詳細(xì)介紹
RTMP
協(xié)議(Real Time Messaging Protocol)
是被Flash用于對(duì)象绪钥,視頻灿里,音頻的傳輸。這個(gè)協(xié)議建立在TCP協(xié)議或者輪詢HTTP協(xié)議之上程腹。
RTMP協(xié)議就像一個(gè)用來(lái)裝數(shù)據(jù)包的容器,這些數(shù)據(jù)既可以是AMF
格式的數(shù)據(jù)匣吊,也可以是FLV
中的視/音頻數(shù)據(jù)。
一個(gè)單一的連接可以通過(guò)不同的通道傳輸多路網(wǎng)絡(luò)流寸潦,這些通道中的包都是按照固定大小的包傳輸?shù)摹?br>
網(wǎng)絡(luò)連接(Connection)
一個(gè)Actionscript
連接并播放一個(gè)流的簡(jiǎn)單代碼:
var videoInstance:Video = your_video_instance;
var nc:NetConnection = new NetConnection();
var connected:Boolean = nc.connect("rtmp:/localhost/myapp");
var ns:NetStream = new NetStream(nc);
videoInstance.attachVideo(ns);
ns.play("flvName");
默認(rèn)端口為1935
握手請(qǐng)求及應(yīng)答
1. 握手過(guò)程
Client → Server
:向服務(wù)器發(fā)出握手請(qǐng)求.這不屬于協(xié)議包一部分,該握手請(qǐng)求第一個(gè)字節(jié)為(0×03),其后跟著1536個(gè)字節(jié)色鸳。盡管看上去這部分的內(nèi)容對(duì)于RTMP協(xié)議來(lái)說(shuō)并不是至關(guān)重要的,但也不可隨意對(duì)待。
Server → Client
:服務(wù)器向客戶端回應(yīng)握手請(qǐng)求见转,這部分的數(shù)據(jù)仍然不屬于RTMP協(xié)議的部分命雀。該回應(yīng)的起始字節(jié)仍然為(0x03),但是后邊跟著兩個(gè)長(zhǎng)度為1536個(gè)字節(jié)(一共為3072字節(jié) )的包塊斩箫。第一個(gè)1536塊看上去似乎可以是任意內(nèi)容吏砂,甚至好像可以是Null都沒(méi)有關(guān)系。第二個(gè)1536的代碼塊乘客,是上一步客戶端向服務(wù)器端發(fā)送的握手請(qǐng)求的內(nèi)容狐血。
Client→Server
:把上一步服務(wù)器向客戶端回應(yīng)的第二塊1536個(gè)字節(jié)的數(shù)據(jù)塊。
至此客戶端與服務(wù)器端的握手結(jié)束寨典,下面將發(fā)送RTMP協(xié)議的包內(nèi)容氛雪。
Client → Server
:向服務(wù)器發(fā)送連接包。
Server → Client
:服務(wù)器回應(yīng)耸成。
... .... 等等... ...
2. RTMP數(shù)據(jù)類(lèi)型
0×01 Chunk Size changes the chunk size for packets
0×02 Unknown anyone know this one?
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 anyone know this one?
0×08 Audio Data packet containing audio
0×09 Video Data packet containing video data
0x0A - 0×11 Unknown anyone know?
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.
Shared Object 數(shù)據(jù)類(lèi)型
0×01 Connect
0×02 Disconnect
0×03 Set Attribute
0×04 Update Data
0×05 Update Attribute
0×06 Send Message
0×07 Status
0×08 Clear Data
0×09 Delete Data
0x0A Delete Attribute
0x0B
Initial Data
3. RTMP包結(jié)構(gòu)
RTMP包 包含一個(gè)固定長(zhǎng)度的包頭和一個(gè)最長(zhǎng)為128字節(jié)的包體报亩,包頭可以是下面4種長(zhǎng)度的任意一種:12, 8, 4, or 1 byte(s)
。
第一個(gè)字節(jié)的前兩個(gè)Bit很重要井氢,它決定了包頭的長(zhǎng)度弦追,它可以用掩碼0xC0進(jìn)行"與"計(jì)算。下面羅列了可能的包頭長(zhǎng)度Bits Header Length
花竞。
00 12 bytes
01 8 bytes
10 4 bytes
11 1 byte
其實(shí)RTMP
包結(jié)構(gòu)就是使用了AMF
格式.
下面是一個(gè)關(guān)于客戶端向服務(wù)器端發(fā)送流的流程:
-
Client → Server
:發(fā)送一個(gè)創(chuàng)建流的請(qǐng)求 -
Server → Client
:返回一個(gè)表示流的索引號(hào) -
Client → Server
:開(kāi)始發(fā)送 -
Client → Server
:發(fā)送視音頻數(shù)據(jù)包(這些包在同一個(gè)頻道(channel)并用流的索引號(hào)來(lái)唯一標(biāo)識(shí))
4. RTMP Chunk Stream - RTMP塊流
Chunk Stream
是對(duì)傳輸RTMP Chunk
的流的邏輯上的抽象劲件,客戶端和服務(wù)器之間有關(guān)RTMP的信息都在這個(gè)流上通信。這個(gè)流上的操作也是我們關(guān)注RTMP協(xié)議的重點(diǎn)
Message
Message
是指滿足該協(xié)議格式的约急、可以切分成Chunk
發(fā)送的消息零远,消息包含的字段如下所示。
-
Timestamp
(時(shí)間戳):消息的時(shí)間戳(但不一定是當(dāng)前時(shí)間厌蔽,后面會(huì)介紹)牵辣,4個(gè)字節(jié)。 -
Length
(長(zhǎng)度):是指Message Payload
(消息負(fù)載)即音視頻等信息的數(shù)據(jù)的長(zhǎng)度奴饮,3個(gè)字節(jié)纬向。 -
TypeId
(類(lèi)型Id):消息的類(lèi)型Id择浊,1個(gè)字節(jié)。 -
Message Stream ID
(消息的流ID):每個(gè)消息的唯一標(biāo)識(shí)逾条,劃分成Chunk
和還原Chunk為Message
的時(shí)候都是根據(jù)這個(gè)ID來(lái)辨識(shí)是否是同一個(gè)消息的Chunk
的琢岩,4個(gè)字節(jié),并且以小端格式存儲(chǔ)师脂。
Chunking(Message分塊)
RTMP
在收發(fā)數(shù)據(jù)的時(shí)候并不是以Message
為單位的担孔,而是把Message拆分成Chunk發(fā)送,而且必須在一個(gè)Chunk
發(fā)送完成之后才能開(kāi)始發(fā)送下一個(gè)Chunk危彩。每個(gè)Chunk中帶有MessageID代表屬于哪個(gè)Message攒磨,接受端也會(huì)按照這個(gè)id來(lái)將chunk組裝成Message。
為什么RTMP要將Message拆分成不同的Chunk呢汤徽?通過(guò)拆分,數(shù)據(jù)量較大的Message可以被拆分成較小的“Message”灸撰,這樣就可以避免優(yōu)先級(jí)低的消息持續(xù)發(fā)送阻塞優(yōu)先級(jí)高的數(shù)據(jù)谒府,比如在視頻的傳輸過(guò)程中,會(huì)包括視頻幀浮毯,音頻幀和RTMP控制信息完疫,如果持續(xù)發(fā)送音頻數(shù)據(jù)或者控制數(shù)據(jù)的話可能就會(huì)造成視頻幀的阻塞,然后就會(huì)造成看視頻時(shí)最煩人的卡頓現(xiàn)象债蓝。同時(shí)對(duì)于數(shù)據(jù)量較小的Message壳鹤,可以通過(guò)對(duì)Chunk Header的字段來(lái)壓縮信息,從而減少信息的傳輸量饰迹。
Chunk的默認(rèn)大小是128字節(jié)芳誓,在傳輸過(guò)程中,通過(guò)一個(gè)叫做Set Chunk Size的控制信息可以設(shè)置Chunk數(shù)據(jù)量的最大值啊鸭,在發(fā)送端和接受端會(huì)各自維護(hù)一個(gè)Chunk Size锹淌,可以分別設(shè)置這個(gè)值來(lái)改變自己這一方發(fā)送的Chunk的最大大小。大一點(diǎn)的Chunk減少了計(jì)算每個(gè)chunk的時(shí)間從而減少了CPU的占用率赠制,但是它會(huì)占用更多的時(shí)間在發(fā)送上赂摆,尤其是在低帶寬的網(wǎng)絡(luò)情況下,很可能會(huì)阻塞后面更重要信息的傳輸钟些。小一點(diǎn)的Chunk可以減少這種阻塞問(wèn)題烟号,但小的Chunk會(huì)引入過(guò)多額外的信息(Chunk中的Header),少量多次的傳輸也可能會(huì)造成發(fā)送的間斷導(dǎo)致不能充分利用高帶寬的優(yōu)勢(shì)政恍,因此并不適合在高比特率的流中傳輸汪拥。在實(shí)際發(fā)送時(shí)應(yīng)對(duì)要發(fā)送的數(shù)據(jù)用不同的Chunk Size去嘗試,通過(guò)抓包分析等手段得出合適的Chunk大小抚垃,并且在傳輸過(guò)程中可以根據(jù)當(dāng)前的帶寬信息和實(shí)際信息的大小動(dòng)態(tài)調(diào)整Chunk的大小喷楣,從而盡量提高CPU的利用率并減少信息的阻塞機(jī)率趟大。
Chunk Format - Chunk格式
下面就說(shuō)一下快格式里面的組成。
- Basic Header:它是基本的頭信息铣焊。
包含了chunk stream ID
(流通道Id)和chunk type
(chunk的類(lèi)型)逊朽,chunk stream id
一般被簡(jiǎn)寫(xiě)為CSID
,用來(lái)唯一標(biāo)識(shí)一個(gè)特定的流通道曲伊,chunk type決定了后面Message Header的格式叽讳。Basic Header的長(zhǎng)度可能是1,2坟募,或3個(gè)字節(jié)岛蚤,其中chunk type的長(zhǎng)度是固定的(占2位,注意單位是位懈糯,bit)涤妒,Basic Header的長(zhǎng)度取決于CSID的大小,在足夠存儲(chǔ)這兩個(gè)字段的前提下最好用盡量少的字節(jié)從而減少由于引入Header增加的數(shù)據(jù)量赚哗。
RTMP協(xié)議支持用戶自定義[3她紫,65599]之間的CSID,0屿储,1贿讹,2由協(xié)議保留表示特殊信息。
0代表Basic Header總共要占用2個(gè)字節(jié)够掠,CSID在[64民褂,319]之間;
1代表占用3個(gè)字節(jié)疯潭,CSID在[64赊堪,65599]之間;
2代表該chunk是控制信息和一些命令信息袁勺,后面會(huì)有詳細(xì)的介紹雹食。
chunk type的長(zhǎng)度固定為2位,因此CSID的長(zhǎng)度是(6=8-2)期丰、(14=16-2)群叶、(22=24-2)中的一個(gè)。
當(dāng)Basic Header為1個(gè)字節(jié)時(shí)钝荡,CSID占6位街立,6位最多可以表示64個(gè)數(shù),因此這種情況下CSID在[0埠通,63]之間赎离,其中用戶可自定義的范圍為[3,63]端辱。
下面看一下Basic Header不同字節(jié)時(shí)的字節(jié)示意圖梁剔。
需要注意的是虽画,Basic Header是采用小端存儲(chǔ)的方式,越往后的字節(jié)數(shù)量級(jí)越高荣病÷胱可以看到2個(gè)字節(jié)和3個(gè)字節(jié)的Basic Header所能表示的CSID是有交集的[64,319]
个盆,但實(shí)際實(shí)現(xiàn)時(shí)還是應(yīng)該秉著最少字節(jié)的原則使用2個(gè)字節(jié)的表示方式來(lái)表示[64脖岛,319]
的CSID
。
- Message Header
包含了要發(fā)送的實(shí)際信息(可能是完整的颊亮,也可能是一部分)的描述信息柴梆。Message Header的格式和長(zhǎng)度取決于Basic Header
的chunk type
,共有4種不同的格式终惑,由上面所提到的Basic Header中的fmt字段控制绍在。其中第一種格式可以表示其他三種表示的所有數(shù)據(jù),但由于其他三種格式是基于對(duì)之前chunk的差量化的表示雹有,因此可以更簡(jiǎn)潔地表示相同的數(shù)據(jù)揣苏,實(shí)際使用的時(shí)候還是應(yīng)該采用盡量少的字節(jié)表示相同意義的數(shù)據(jù)。以下按照字節(jié)數(shù)從多到少的順序分別介紹這4種格式的Message Header
件舵。
(1) type=0時(shí)Message Header占用11個(gè)字節(jié),其他三種能表示的數(shù)據(jù)它都能表示脯厨,但在chunk stream的開(kāi)始的第一個(gè)chunk和頭信息中的時(shí)間戳后退(即值與上一個(gè)chunk相比減小铅祸,通常在回退播放的時(shí)候會(huì)出現(xiàn)這種情況)的時(shí)候必須采用這種格式丑蛤。
(2) type=1時(shí)Message Header占用7個(gè)字節(jié)账磺,省去了表示msg stream id的4個(gè)字節(jié),表示此chunk和上一次發(fā)的chunk所在的流相同荧止,如果在發(fā)送端只和對(duì)端有一個(gè)流鏈接的時(shí)候可以盡量去采取這種格式稼跳。
(3) type=2時(shí)Message Header占用3個(gè)字節(jié)盟庞,相對(duì)于type=1格式又省去了表示消息長(zhǎng)度的3個(gè)字節(jié)和表示消息類(lèi)型的1個(gè)字節(jié),表示此chunk和上一次發(fā)送的chunk所在的流汤善、消息的長(zhǎng)度和消息的類(lèi)型都相同什猖。余下的這三個(gè)字節(jié)表示timestamp delta,使用同type=1 红淡。
(4) 0字節(jié)2皇ā!在旱!好吧摇零,它表示這個(gè)chunk的Message Header和上一個(gè)是完全相同的,自然就不用再傳輸一遍了桶蝎。當(dāng)它跟在Type=0的chunk后面時(shí)驻仅,表示和前一個(gè)chunk的時(shí)間戳都是相同的谅畅。什么時(shí)候連時(shí)間戳都相同呢?就是一個(gè)Message拆分成了多個(gè)chunk噪服,這個(gè)chunk和上一個(gè)chunk同屬于一個(gè)Message毡泻。而當(dāng)它跟在Type=1或者Type=2的chunk后面時(shí),表示和前一個(gè)chunk的時(shí)間戳的差是相同的芯咧。比如第一個(gè)chunk的Type=0牙捉,timestamp=100,第二個(gè)chunk的Type=2敬飒,timestamp delta=20邪铲,表示時(shí)間戳為100+20=120,第三個(gè)chunk的Type=3无拗,表示timestamp delta=20带到,時(shí)間戳為120+20=140。
- Extended Timestamp(擴(kuò)展時(shí)間戳)
上面我們提到在chunk中會(huì)有時(shí)間戳timestamp和時(shí)間戳差timestamp delta英染,并且它們不會(huì)同時(shí)存在揽惹,只有這兩者之一大于3個(gè)字節(jié)能表示的最大數(shù)值0xFFFFFF=16777215時(shí),才會(huì)用這個(gè)字段來(lái)表示真正的時(shí)間戳四康,否則這個(gè)字段為0搪搏。擴(kuò)展時(shí)間戳占4個(gè)字節(jié),能表示的最大數(shù)值就是0xFFFFFFFF=4294967295闪金。當(dāng)擴(kuò)展時(shí)間戳啟用時(shí)疯溺,timestamp字段或者timestamp delta要全置為1,表示應(yīng)該去擴(kuò)展時(shí)間戳字段來(lái)提取真正的時(shí)間戳或者時(shí)間戳差哎垦。注意擴(kuò)展時(shí)間戳存儲(chǔ)的是完整值囱嫩,而不是減去時(shí)間戳或者時(shí)間戳差的值。
- Chunk Data(塊數(shù)據(jù)):
用戶層面上真正想要發(fā)送的與協(xié)議無(wú)關(guān)的數(shù)據(jù)漏设,長(zhǎng)度在[0,chunkSize]
之間墨闲。
協(xié)議控制消息(Protocol Control Message)
在RTMP的chunk流會(huì)用一些特殊的值來(lái)代表協(xié)議的控制消息,它們的Message Stream ID必須為0(代表控制流信息)郑口,CSID必須為2鸳碧,Message Type ID可以為1,2潘酗,3杆兵,5,6仔夺,具體代表的消息會(huì)在下面依次說(shuō)明琐脏。控制消息的接受端會(huì)忽略掉chunk中的時(shí)間戳,收到后立即生效日裙。
Set Chunk Size(Message Type ID=1)
:設(shè)置chunk中Data字段所能承載的最大字節(jié)數(shù)吹艇,默認(rèn)為128B,通信過(guò)程中可以通過(guò)發(fā)送該消息來(lái)設(shè)置chunk Size
的大邪悍鳌(不得小于128B)受神,而且通信雙方會(huì)各自維護(hù)一個(gè)chunkSize,兩端的chunkSize是獨(dú)立的格侯。Abort Message(Message Type ID=2)
:當(dāng)一個(gè)Message被切分為多個(gè)chunk鼻听,接受端只接收到了部分chunk時(shí),發(fā)送該控制消息表示發(fā)送端不再傳輸同Message的chunk联四,接受端接收到這個(gè)消息后要丟棄這些不完整的chunk撑碴。Data數(shù)據(jù)中只需要一個(gè)CSID,表示丟棄該CSID的所有已接收到的chunk朝墩。Acknowledgement(Message Type ID=3)
:當(dāng)收到對(duì)端的消息大小等于窗口大凶硗亍(Window Size)時(shí)接受端要回饋一個(gè)ACK給發(fā)送端告知對(duì)方可以繼續(xù)發(fā)送數(shù)據(jù)。窗口大小就是指收到接受端返回的ACK前最多可以發(fā)送的字節(jié)數(shù)量收苏,返回的ACK中會(huì)帶有從發(fā)送上一個(gè)ACK后接收到的字節(jié)數(shù)亿卤。Window Acknowledgement Size(Message Type ID=5)
:發(fā)送端在接收到接受端返回的兩個(gè)ACK間最多可以發(fā)送的字節(jié)數(shù)。Set Peer Bandwidth(Message Type ID=6)
:限制對(duì)端的輸出帶寬鹿霸。接受端接收到該消息后會(huì)通過(guò)設(shè)置消息中的Window ACK Size來(lái)限制已發(fā)送但未接受到反饋的消息的大小來(lái)限制發(fā)送端的發(fā)送帶寬排吴。如果消息中的Window ACK Size與上一次發(fā)送給發(fā)送端的size不同的話要回饋一個(gè)Window Acknowledgement Size
的控制消息。
(1)Hard(Limit Type=0)
:接受端應(yīng)該將Window Ack Size
設(shè)置為消息中的值
(2)Soft(Limit Type=1)
:接受端可以講Window Ack Size
設(shè)為消息中的值懦鼠,也可以保存原來(lái)的值(前提是原來(lái)的Size小與該控制消息中的Window Ack Size
)
(3)Dynamic(Limit Type=2)
:如果上次的Set Peer Bandwidth
消息中的Limit Type為0傍念,本次也按Hard處理,否則忽略本消息葛闷,不去設(shè)置Window Ack Size
。
5. 不同類(lèi)型的RTMP Message
-
Command Message
(命令消息双藕,Message Type ID=17或20
):表示在客戶端和服務(wù)器間傳遞的在對(duì)端執(zhí)行某些操作的命令消息淑趾,如connect表示連接對(duì)端,對(duì)端如果同意連接的話會(huì)記錄發(fā)送端信息并返回連接成功消息忧陪,publish表示開(kāi)始向?qū)Ψ酵屏骺鄄矗邮芏私拥矫詈鬁?zhǔn)備好接受對(duì)端發(fā)送的流信息,后面會(huì)對(duì)比較常見(jiàn)的Command Message具體介紹嘶摊。當(dāng)信息使用AMF0編碼時(shí)延蟹,Message Type ID=20,AMF3編碼時(shí)Message Type ID=17叶堆。 -
Data Message
(數(shù)據(jù)消息阱飘,Message Type ID=15或18
):傳遞一些元數(shù)據(jù)(MetaData,比如視頻名,分辨率等等)或者用戶自定義的一些消息沥匈。當(dāng)信息使用AMF0編碼時(shí)蔗喂,Message Type ID=18,AMF3編碼時(shí)Message Type ID=15高帖。 -
Shared Object Message
(共享消息缰儿,Message Type ID=16或19):表示一個(gè)Flash類(lèi)型的對(duì)象,由鍵值對(duì)的集合組成散址,用于多客戶端乖阵,多實(shí)例時(shí)使用。當(dāng)信息使用AMF0編碼時(shí)预麸,Message Type ID=19瞪浸,AMF3
編碼時(shí)Message Type ID=16
。 -
Audio Message
(音頻信息师崎,Message Type ID=8
):音頻數(shù)據(jù)默终。 -
Video Message
(視頻信息,Message Type ID=9
):視頻數(shù)據(jù)犁罩。 -
Aggregate Message
(聚集信息齐蔽,Message Type ID=22
):多個(gè)RTMP子消息的集合 。 -
User Control Message Events
(用戶控制消息床估,Message Type ID=4):告知對(duì)方執(zhí)行該信息中包含的用戶控制事件含滴,比如Stream Begin事件告知對(duì)方流信息開(kāi)始傳輸。和前面提到的協(xié)議控制信息(Protocol Control Message)不同丐巫,這是在RTMP協(xié)議層的谈况,而不是在RTMP chunk流協(xié)議層的,這個(gè)很容易弄混递胧。該信息在chunk流中發(fā)送時(shí)碑韵,Message Stream ID=0,Chunk Stream Id=2,Message Type Id=4
。
6. 基于RTMP協(xié)議的推流和拉流播放過(guò)程
先看一下推流過(guò)程缎脾。
再看一下拉流過(guò)程
參考文章
后記
未完祝闻,待續(xù)~~~