[关闭]
@sheepbao 2016-09-12T21:56:52.000000Z 字数 8894 阅读 8471

RTMP协议笔记

请用电脑或者手机横屏查看,不然会格式乱。

RTMP的背景和应用

每项技术都有起来源,RTMP也不例外,RTMP是Adobe公司公布的一项协议,Adobe是一家世界领先数字媒体和在线营销方案的供应商。在H5崛起之前,几乎所有的浏览器都用Flash player播放多媒体资源,而服务端和浏览器之间就是用RTMP协议或者在RTMP协议变种后的协议进行通信的。

RTMP协议概览

握手、消息块概念
握手的目的是为了确认对端RTMP的Version和确认对端能互相通信。
消息块就是消息的载体,是RTMP协议最重要的载体,这个载体是有一定格式的,如果把Client和Server端当作铁路的两个站点,那这个消息块就是火车,它负责运输货物。正如火车有火车头、车厢一样,消息块也有基本头,消息头和消息负载。RTMP协议当中,除了握手协议,其他的数据都是以消息块的方式发送的,发送一个消息时,当块大小比需要发送的消息的字节数更大时,一个消息块就相当于一个消息,否则消息需要分成多个消息块。

握手

  1. +-+-+-+-+-+-+ +-+-+-+-+-+-+
  2. | Client | | Server |
  3. +-+-+-+-+-+-+ +-+-+-+-+-+-+
  4. |-------- C0C1 -------->|
  5. |<------ S0S1S2 --------|
  6. |--------- C2 --------->|
  1. +-+-+-+-+-+-+-+-+
  2. | version |
  3. +-+-+-+-+-+-+-+-+
  1. +-+-+-+-+-+-+-+-+-+-+
  2. | time (4 bytes) |
  3. +-+-+-+-+-+-+-+-+-+-+
  4. | zero (4 bytes) |
  5. +-+-+-+-+-+-+-+-+-+-+
  6. | random bytes |
  7. +-+-+-+-+-+-+-+-+-+-+
  8. |random bytes(cont) |
  9. | .... |
  10. +-+-+-+-+-+-+-+-+-+-+
time: 4 字节
本字段包含时间戳。该时间戳应该是发送这个数据块的端点的后续块的时间起始点。可以是 0 ,或其他的任何值。为了同步多个流,端点可能发送其块流的当前值。
zero: 4 字节
本字段必须是全零。
random bytes: 1528 字节。
本字段可以包含任何值。因为每个端点必须用自己初始化的握手和对端初始化的
  1. +-+-+-+-+-+-+-+-+-+-+
  2. | time (4 bytes) |
  3. +-+-+-+-+-+-+-+-+-+-+
  4. | time2(4 bytes) |
  5. +-+-+-+-+-+-+-+-+-+-+
  6. | random bytes |
  7. +-+-+-+-+-+-+-+-+-+-+
  8. |random bytes(cont) |
  9. | .... |
  10. +-+-+-+-+-+-+-+-+-+-+
time: 4 字节
本字段必须包含对等段发送的时间(对C2来说是S1 ,对S2来说是C1)。
time2 : 4 字节
本字段必须包含先前发送的并被对端读取的包的时间戳。
random bytes: 1528 字节
本字段必须包含对端发送的随机数据字段(对C2来说是S1 ,对S2来说是C1)。  

消息块-Chunk Block(由Header、TimeStamp(不一定有)和Data组成)

  1. +-------------+----------------+-------------------+-----------+
  2. | Basic header|Chunk Msg Header|Extended Time Stamp|Chunk Data |
  3. +-------------+----------------+-------------------+-----------+
  1. +-+-+-+-+-+-+-+-+
  2. | fmt | cs id |
  3. +-+-+-+-+-+-+-+-+
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作为保留。

  1. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  2. | timestamp | message length |
  3. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  4. |message length (cont)|message type id| msg stream id |
  5. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  6. |message stream id (cont) |
  7. +-+-+-+-+-+-+-+-+-+-+-+-+-+
  1. fmt=0:长度11 byte,
    在一个块流的开始和时间戳返回的时候必须有这种块
  2. fmt=1:长度为7 byte,与fmt=0时,相比,该类型少了Message Stream Id
    具有可变大小消息的流,在第一个消息之后的每个消息的第一个块应该使用这个格式
  3. fmt=2:长度3 byte,不包含Message Stream IdMessage Length
    具有固定大小消息的流,在第一个消息之后的每个消息的第一个块应该使用这个格式
  4. fmt=3:长度为0 byte,
    当一个消息被分成多个块,除了第一块以外,所有的块都应使用这种类型

    • Extend Time Stamp (0,4 byte)
  1. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  2. | timestamp |
  3. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
只有当块消息头中的普通时间戳设置为 0x00ffffff 时,本字段才被传送。  
如果普通时间戳的值小于 0x00ffffff ,那么本字段一定不能出现。如果时间戳  
字段不出现本字段也一定不能出现。类型 3 的块一定不能含有本字段。本字段  
在块消息头之后,块时间之前  

* Chunk Data

  1. +-----------+
  2. |Chunk Data |
  3. +-----------+
Chunk Data的实例就是Message  

消息-Message

  1. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  2. | Message Type| Payload length|
  3. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  4. | Timestamp |
  5. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  6. | Stream ID |
  7. +-+-+-+-+-+-+-+-+-+-+-+-+
  1. Message Type(1 byte)以下简写为MT
    消息类型很重要,它代表了这个消息是什么类型,当写程序的时候需要根据不同的消息,做不同的处理。
  2. Payload length(3 bytes)
    表示负载的长度(big-endian 格式)
  3. Timestamp (4 bytes)
    时间戳(big-endian 格式)
  4. Stream ID (3 bytes)
    消息流ID(big-endian 格式)
  5. Message Payload
    真实的数据

消息的分类

协议控制消息

协议控制消息是用来与对端协调控制的,**MT的范围1~7**.
1~2 用于chunk协议,3~6 用于rtmp协议本身,协议控制消息必须要求  
**Message Stream ID=0 和 Chunk Stream ID=2**.   

* MT=1, Set Chunk Size 设置块的大小,通知对端用使用新的块大小,共4 bytes。

  1. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. |Basic Header|Message Header|Ex Timestamp|Set chunk size |
  3. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. |Basic Header|Message Header|Ex Timestamp|Chunk Stream ID |
  3. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. |Basic Header|Message Header|Ex Timestamp| Sequence Number|
  3. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. |Basic Header|Message Header|Ex Timestamp| Event Type|Event Data |
  3. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. |Basic Header|Message Header|Ex Timestamp| Acknowledgement Window size |
  3. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. |Basic Header|Message Header|Ex Timestamp| Acknowledgement Window size |
  3. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  4. | Limit type |
  5. ++++++++++++++++

音频数据消息

视频数据消息

元数据消息

共享对象消息

命令消息

命令消息的类型
  1. +-------------+ +----------+
  2. | Play Client | | | Server |
  3. +-------------+ | +----------+
  4. | |Handshaking and Application| |
  5. | | connect done | |
  6. | | |
  7. ---+---- |---------Command Message(createStream) --------->|
  8. Create | |
  9. Stream | |
  10. ---+---- |<-------------- Command Message -----------------|
  11. | (_result- createStream response) |
  12. | |
  13. ---+---- |------------ Command Message (play) ------------>|
  14. play | |
  15. | |<---------------- SetChunkSize ------------------|
  16. | |<----- User Control (StreamIsRecorded) ----------|
  17. | |<-------- UserControl (StreamBegin) -------------|
  18. | |<---- Command Message(onStatus-play reset) ------|
  19. | |<---- Command Message(onStatus-play start) ------|
  20. | |------------------ Audio Message---------------->|
  21. | |------------------ Video Message---------------->|
  22. |
  23. |
  24. 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

  1. +-------------+ +----------+
  2. | Client | | | Server |
  3. +-------------+ | +----------+
  4. | |Handshaking and Application| |
  5. | | connect done | |
  6. | | |
  7. ---+---- |---------Command Message(createStream) --------->|
  8. Create | |
  9. Stream | |
  10. ---+---- |<-------------- Command Message -----------------|
  11. | (_result- createStream response) |
  12. | |
  13. ---+---- |--------- Command Message (publish) ------------>|
  14. publish | |
  15. | |<-------- UserControl (StreamBegin) -------------|
  16. | |---------- Data Message (Metadata) ------------->|
  17. | |------------------ Audio Message---------------->|
  18. | |----------------- SetChunkSize ----------------->|
  19. | |<--------------- Command Message ----------------|
  20. | | (_result- publish result) |
  21. | |------------------ Video Message---------------->|
  22. |
  23. |
  24. Until the stream is complete
    客户端发送一个发布命令,发布一个命名流到服务端。使用这个名字,任何客户端可以播放该流并且接收音频,视频,和数据消息。  

8. seek

客户端发送搜寻命令在一个媒体文件中或播放列表中搜寻偏移。  

9. pause

客户端发送暂停命令告诉服务端暂停或开始一个命令。  

聚合消息

  1. +---------+-------------------------+
  2. | Header | Aggregate Message body |
  3. +---------+-------------------------+
  4. 聚合消息的格式
  5. +--------+--------------+--------------+--------+-------------+---------------+ - - - -
  6. |Header 0|Message Data 0|Back Pointer 0|Header 1|Message Data 1|Back Pointer 1|
  7. +--------+--------------+--------------+--------+--------------+--------------+ - - - -
  8. 聚合消息的body
Back Pointer包含了前面消息的大小(包括Header的大小)。这个设置匹配了 flv 文件格式,可用于后向搜索。  

PS

视智云-Sewise,流媒体云平台服务商。
Sewise提供最优秀的流媒体软件和技术服务,包括流媒体协议的接入、转换、封装、分析等;音视频的转码、裁剪、拼接、水印、抽帧、切片、元信息提取与处理、录制、HLS时移回播、编码、格式封装、加解密等;字幕的抽取、添加、匹配等。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注