@sheepbao
2016-09-12T21:56:52.000000Z
字数 8894
阅读 8491
请用电脑或者手机横屏查看,不然会格式乱。
每项技术都有起来源,RTMP也不例外,RTMP是Adobe公司公布的一项协议,Adobe是一家世界领先数字媒体和在线营销方案的供应商。在H5崛起之前,几乎所有的浏览器都用Flash player播放多媒体资源,而服务端和浏览器之间就是用RTMP协议或者在RTMP协议变种后的协议进行通信的。
握手、消息块概念
握手的目的是为了确认对端RTMP的Version和确认对端能互相通信。
消息块就是消息的载体,是RTMP协议最重要的载体,这个载体是有一定格式的,如果把Client和Server端当作铁路的两个站点,那这个消息块就是火车,它负责运输货物。正如火车有火车头、车厢一样,消息块也有基本头,消息头和消息负载。RTMP协议当中,除了握手协议,其他的数据都是以消息块的方式发送的,发送一个消息时,当块大小比需要发送的消息的字节数更大时,一个消息块就相当于一个消息,否则消息需要分成多个消息块。
+-+-+-+-+-+-+ +-+-+-+-+-+-+
| Client | | Server |
+-+-+-+-+-+-+ +-+-+-+-+-+-+
|-------- C0C1 -------->|
|<------ S0S1S2 --------|
|--------- C2 --------->|
+-+-+-+-+-+-+-+-+
| version |
+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+
| time (4 bytes) |
+-+-+-+-+-+-+-+-+-+-+
| zero (4 bytes) |
+-+-+-+-+-+-+-+-+-+-+
| random bytes |
+-+-+-+-+-+-+-+-+-+-+
|random bytes(cont) |
| .... |
+-+-+-+-+-+-+-+-+-+-+
time: 4 字节
本字段包含时间戳。该时间戳应该是发送这个数据块的端点的后续块的时间起始点。可以是 0 ,或其他的任何值。为了同步多个流,端点可能发送其块流的当前值。
zero: 4 字节
本字段必须是全零。
random bytes: 1528 字节。
本字段可以包含任何值。因为每个端点必须用自己初始化的握手和对端初始化的
+-+-+-+-+-+-+-+-+-+-+
| time (4 bytes) |
+-+-+-+-+-+-+-+-+-+-+
| time2(4 bytes) |
+-+-+-+-+-+-+-+-+-+-+
| random bytes |
+-+-+-+-+-+-+-+-+-+-+
|random bytes(cont) |
| .... |
+-+-+-+-+-+-+-+-+-+-+
time: 4 字节
本字段必须包含对等段发送的时间(对C2来说是S1 ,对S2来说是C1)。
time2 : 4 字节
本字段必须包含先前发送的并被对端读取的包的时间戳。
random bytes: 1528 字节
本字段必须包含对端发送的随机数据字段(对C2来说是S1 ,对S2来说是C1)。
+-------------+----------------+-------------------+-----------+
| Basic header|Chunk Msg Header|Extended Time Stamp|Chunk Data |
+-------------+----------------+-------------------+-----------+
+-+-+-+-+-+-+-+-+
| fmt | cs id |
+-+-+-+-+-+-+-+-+
fmt:表示块类型,决定了Chunk Msg Header的格式,
它占第一个字节的0~1bit,2~7属于csid字节。
csid :表示块流id
csid在64~319的范围内时,
csidTS=0,csid=(第二个字节的值)+64
csid在64~65599的范围内时,
csidTS=0x3f,bit位全为1时,csid=(第二个字节的值×256)+(第三个字节的值)+64
csid在3~63的范围内时,
csidTS=1~0x3e,即6位bit非全0也非全1时,csid=csidTS
注意:这里第一个字节的2~7位暂时称为csidTS,协议里并没有这么说明,只是个人阐述需要
说明:BH的长度范围为1~3 byte,具体多少byte是csidTS决定的,csid的值范围3~65599,0~2作为保留。
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp | message length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|message length (cont)|message type id| msg stream id |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|message stream id (cont) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+
Message Stream Id
, Message Stream Id
和Message Length
fmt=3:长度为0 byte,
当一个消息被分成多个块,除了第一块以外,所有的块都应使用这种类型
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
只有当块消息头中的普通时间戳设置为 0x00ffffff 时,本字段才被传送。
如果普通时间戳的值小于 0x00ffffff ,那么本字段一定不能出现。如果时间戳
字段不出现本字段也一定不能出现。类型 3 的块一定不能含有本字段。本字段
在块消息头之后,块时间之前
* Chunk Data
+-----------+
|Chunk Data |
+-----------+
Chunk Data的实例就是Message
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type| Payload length|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Stream ID |
+-+-+-+-+-+-+-+-+-+-+-+-+
协议控制消息是用来与对端协调控制的,**MT的范围1~7**.
1~2 用于chunk协议,3~6 用于rtmp协议本身,协议控制消息必须要求
**Message Stream ID=0 和 Chunk Stream ID=2**.
* MT=1, Set Chunk Size 设置块的大小,通知对端用使用新的块大小,共4 bytes。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|Basic Header|Message Header|Ex Timestamp|Set chunk size |
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|Basic Header|Message Header|Ex Timestamp|Chunk Stream ID |
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|Basic Header|Message Header|Ex Timestamp| Sequence Number|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|Basic Header|Message Header|Ex Timestamp| Event Type|Event Data |
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|Basic Header|Message Header|Ex Timestamp| Acknowledgement Window size |
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|Basic Header|Message Header|Ex Timestamp| Acknowledgement Window size |
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
| Limit type |
++++++++++++++++
NetConnection:代表服务端和客户端之间连接的更高层的对象。包含4个命令类型。
NetStream:代表发送音频流,视频流和其他相关数据的通道的对象。我们也发送像播放,暂停等控制数据流动的命令。
+-------------+ +----------+
| Play Client | | | Server |
+-------------+ | +----------+
| |Handshaking and Application| |
| | connect done | |
| | |
---+---- |---------Command Message(createStream) --------->|
Create | |
Stream | |
---+---- |<-------------- Command Message -----------------|
| (_result- createStream response) |
| |
---+---- |------------ Command Message (play) ------------>|
play | |
| |<---------------- SetChunkSize ------------------|
| |<----- User Control (StreamIsRecorded) ----------|
| |<-------- UserControl (StreamBegin) -------------|
| |<---- Command Message(onStatus-play reset) ------|
| |<---- Command Message(onStatus-play start) ------|
| |------------------ Audio Message---------------->|
| |------------------ Video Message---------------->|
|
|
Keep receiving audio and video stream till finishes
a. 客户端从服务端接收到流创建成功消息,发送播放命令到服务端。
b. 接收到播放命令后,服务端发送协议消息设置块大小。
c. 服务端发送另一个协议消息(用户控制消息),并且在消息中指定事件” streamisrecorded” 和流 ID 。消息承载的头 2 个字,为事件类型,后4 个字节为流 ID 。
d. 服务端发送事件” streambegin” 的协议消息(用户控制),告知客户端流 ID 。
e. 服务端发送响应状态命令消息`NetStream.Play.Start`&`NetStream.Play.reset` , 如果客户端发送的播放命令成功的话。只有当客户端发送的播放命令设置了 `reset`命令的条件下,服务端才发送`NetStream.Play.reset`消息。如果要发送的流 没有找的话,服务端发送`NetStream.Play.StreamNotFound`消息。在此之后服务端发送客户端要播放的音频和视频数据。
2. play2
和播放命令不同,play2命令可以切换到不同的码率,而不用改变已经播放的内容的时间线。服务端对播放 2 命令可以请求的多个码率维护多个文件。
3. deleteStream
当 NetStream 对象销毁的时候发送删除流命令。
4. closeStream
5. receiveAudio
NetStream 对象发送接收音频消息通知服务端发送还是不发送音频到客户端。
6. receiveVideo
NetStream 对象发送 receiveVideo 消息通知服务端是否发送视频到客户端。
7. publish
+-------------+ +----------+
| Client | | | Server |
+-------------+ | +----------+
| |Handshaking and Application| |
| | connect done | |
| | |
---+---- |---------Command Message(createStream) --------->|
Create | |
Stream | |
---+---- |<-------------- Command Message -----------------|
| (_result- createStream response) |
| |
---+---- |--------- Command Message (publish) ------------>|
publish | |
| |<-------- UserControl (StreamBegin) -------------|
| |---------- Data Message (Metadata) ------------->|
| |------------------ Audio Message---------------->|
| |----------------- SetChunkSize ----------------->|
| |<--------------- Command Message ----------------|
| | (_result- publish result) |
| |------------------ Video Message---------------->|
|
|
Until the stream is complete
客户端发送一个发布命令,发布一个命名流到服务端。使用这个名字,任何客户端可以播放该流并且接收音频,视频,和数据消息。
8. seek
客户端发送搜寻命令在一个媒体文件中或播放列表中搜寻偏移。
9. pause
客户端发送暂停命令告诉服务端暂停或开始一个命令。
+---------+-------------------------+
| Header | Aggregate Message body |
+---------+-------------------------+
聚合消息的格式
+--------+--------------+--------------+--------+-------------+---------------+ - - - -
|Header 0|Message Data 0|Back Pointer 0|Header 1|Message Data 1|Back Pointer 1|
+--------+--------------+--------------+--------+--------------+--------------+ - - - -
聚合消息的body
Back Pointer包含了前面消息的大小(包括Header的大小)。这个设置匹配了 flv 文件格式,可用于后向搜索。
视智云-Sewise,流媒体云平台服务商。
Sewise提供最优秀的流媒体软件和技术服务,包括流媒体协议的接入、转换、封装、分析等;音视频的转码、裁剪、拼接、水印、抽帧、切片、元信息提取与处理、录制、HLS时移回播、编码、格式封装、加解密等;字幕的抽取、添加、匹配等。