RTMP協(xié)議解析(一) —— 基本了解

版本記錄

版本號(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為1個(gè)字節(jié)時(shí)
Basic Header為2或3個(gè)字節(jié)時(shí)

需要注意的是虽画,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 Headerchunk 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í)候必須采用這種格式丑蛤。

Message Header type 0

(2) type=1時(shí)Message Header占用7個(gè)字節(jié)账磺,省去了表示msg stream id的4個(gè)字節(jié),表示此chunk和上一次發(fā)的chunk所在的流相同荧止,如果在發(fā)送端只和對(duì)端有一個(gè)流鏈接的時(shí)候可以盡量去采取這種格式稼跳。

Message Header type 1

(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 红淡。

Message Header type 2

(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ò)程

再看一下拉流過(guò)程

拉流播放過(guò)程

參考文章

1. 帶你吃透RTMP

后記

未完祝闻,待續(xù)~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市遗菠,隨后出現(xiàn)的幾起案子联喘,更是在濱河造成了極大的恐慌,老刑警劉巖辙纬,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件豁遭,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡贺拣,警方通過(guò)查閱死者的電腦和手機(jī)蓖谢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)捂蕴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人蜈抓,你說(shuō)我怎么就攤上這事启绰。” “怎么了沟使?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)着倾。 經(jīng)常有香客問(wèn)我崇决,道長(zhǎng),這世上最難降的妖魔是什么盈厘? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任契吉,我火速辦了婚禮玩徊,結(jié)果婚禮上胶哲,老公的妹妹穿的比我還像新娘把敢。我一直安慰自己桑阶,他們只是感情好割择,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布玛歌。 她就那樣靜靜地躺著确憨,像睡著了一般吞歼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上塔猾,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天篙骡,我揣著相機(jī)與錄音,去河邊找鬼丈甸。 笑死糯俗,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的睦擂。 我是一名探鬼主播得湘,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼顿仇!你這毒婦竟也來(lái)了淘正?” 一聲冷哼從身側(cè)響起摆马,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鸿吆,沒(méi)想到半個(gè)月后囤采,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惩淳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年蕉毯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片黎泣。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡恕刘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出抒倚,到底是詐尸還是另有隱情褐着,我是刑警寧澤,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布托呕,位于F島的核電站含蓉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏项郊。R本人自食惡果不足惜馅扣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望着降。 院中可真熱鬧差油,春花似錦、人聲如沸任洞。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)交掏。三九已至妆偏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盅弛,已是汗流浹背钱骂。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留挪鹏,地道東北人见秽。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像讨盒,于是被迫代替她去往敵國(guó)和親解取。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容