目录
RTMP
一、总体介绍
二、结构组成
1. Message结构
2. Chunk结构
注意事项:
音频Chunk
视频Chunk
3. Message和Chunk的组成关系
4. Message类型
三、建立握手
四、保存文件
五、与其他协议对比
RTMP
一、总体介绍
RTMP(Real Time Messaging Protocol)实时消息传送协议是Adobe公司为Flash播放器和服务器之间音频、视频和数据传输开发的开放协议。RTMP工作在TCP之上,默认使用端口1935。
工作原理:RTMP 的 message 会切分为 n 个 chunk,再通过TCP协议传输。
为什么 rtmp 基于 tcp 协议,tcp 协议已经有化整为零的方式, rtmp 还需要将 message 划分更小的单元 chunk 呢?
分析原因:
1. tcp 协议划分一个个 tcp 报文,是为了在网络传输层上保障数据连续性,丢包重发等特性。
2. rtmp 划分 chunk 消息块,是为了在网络应用层上实现低延迟的特性,防止大的数据块(如视频数据)阻塞小的数据块(如音频数据或控制信息)。
二、结构组成
1. Message结构
RTMP Message Header
- - - - - - - - - - - - - - -
| Message Type| Payload length|
- - - - - - - - - - - - - - -
| Timestamp |
- - - - - - - - - - - - - - -
| Stream ID |
- - - - - - - - - - - -
参数分析:
Message Type(1 byte),消息类型,这个参数很重要,当写程序的时候需要根据不同的消息,做不同的处理。
Payload length(3 bytes),表示负载的长度(big-endian 格式)。
Timestamp (4 bytes),时间戳(big-endian 格式),超过最大值后会翻转。
Stream ID (3 bytes) ,消息流ID(big-endian 格式),用于区分不同流的消息。
Message Payload,真实的数据。
2. Chunk结构
RTMP收发的数据称为Message,所谓Message不外乎音视频数据和信令,而真正收发数据时把Message拆分为Chunk发送,每个Chunk的默认大小是128字节,当然这个大小可以通过控制信息来修改。Chunk由Chunk Header和Chuk Data组成。
2.1 Chunk header:
RTMP Chunk Header
----------------- ------------------------- ---------------------------- ----------------
| Basic header|Chunk Msg Header|Extended Time Stamp|Chunk Data |
----------------- ------------------------- ----------------------------- ---------------
1 byte - (0,3,7,11 byte) - (0,4 byte)
2.2 Basic header:
RTMP Chunk Basic Header (1 byte)
- - - - - - - - - - - - - -
| format | chunk stream id |
- - - - - - - - - - - - - -
2 bits - 6 bits
RTMP Chunk包一般是由一个固定长度的包头和一个最长为chunk default size字节的包体(默认128Byte)组成,包头可以是下面4种长度的任意一种:12, 8, 4, or 1 byte(s)。
第一个字节的前两个Bit很重要,它决定了包头的长度,它可以用掩码0xC0进行"与"计算。
format=0,Chunk Header length = 12 bytes,在一个 chunk 流的开始、时间戳返回的时候必须有这种块,比如:onMetaData, 音视频流刚开始的绝对时间戳,控制消息。
Basic header Chunk Msg Header
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| format | chunk stream id | timestamp | message length | msg type id | msg stream id |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2 bits - 6 bits - 3 bytes - 3 bytes - 1 bytes - 4 bytes
format=1,Chunk Header length = 8 bytes,对于可变大小消息的chunk流,在第一个消息之后的每个消息的第一个块应该使用这个格式。
Basic header Chunk Msg Header
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| format | chunk stream id | timestamp | message length | msg type id |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2 bits - 6 bits - 3 bytes - 3 bytes - 1 bytes
format=2,Chunk Header length = 4 bytes,对于固定大小消息的chunk流,在第一个消息之后的每个消息的第一个块应该使用这个格式。
Basic header Chunk Msg Header
- - - - - - - - - - - - - - - - - - - -
| format | chunk stream id | timestamp |
- - - - - - - - - - - - - - - - - - - -
2 bits - 6 bits - 3 bytes
format=3,Chunk Header length = 1 bytes,当一个消息被分成多个块,除了第一块以外,所有的块都应使用这种类型。
Basic header Chunk Msg Header
- - - - - - - - - - - - - -
| format | chunk stream id |
- - - - - - - - - - - - - -
2 bits - 6 bits
注意事项:
1)timestamp 的长度为 3 bytes,当 timestamp 被设置为 0x00ffffff,chunk header 会加上 Extended Time Stamp 字段,否则 Extended Time Stamp 不会出现。
2)多个Chunk怎么标记同属于一个 Message 的呢?
其一、是通过Chunk Stream ID 区分的,同一个Chunk Stream ID 属于同一个 Message。
其二、因为TCP的有序,同一个 Message 中不同的 Chunk 会先后抵达。
音频Chunk
以FLV AAC为例
协议层 封装层
|RTMP Chunk Header | FLV AudioTagHeader | FLV AudioTagBody |
FLV AudioTagHeader:
|SoundFormat | SoundRate | SoundSize | SoundType | AACPacketType |
4 bits 2 bits 1 bit 1 bit 8 bits
视频Chunk
以FLV AVC为例
协议层 封装层
|RTMP Chunk Header | FLV VideoTagHeader | FLV VideoTagBody |
FLV VideoTagHeader:
|Frame Type | CodecID | AVCPacketType | CompositionTime |
4 bits - 4 bits - 1 byte - 3 bytes
FLV VideoTagBody:
| Size | AVCDecoderConfigurationRecord or ( one or more NALUs ) |
4 bytes
3. Message和Chunk的组成关系
3.1 Message结构组成:
3.2 Message拆分Chunk实例:
4. Message类型
消息主要分为三类: 协议控制消息、数据消息、命令消息等。
a.协议控制消息
Message Type ID = 1~6,主要用于协议内的控制。
b.数据消息
Message Type ID = 8 9 18(15),其中
8: Audio 音频数据
9: Video 视频数据
18(15): 对应AMF0(AMF3),Metadata 包括音视频编码、视频宽高等信息。
c.命令消息 Command Message (20, 17)
此类型消息主要有NetConnection和NetStream两个类,两个类分别有多个函数,该消息的调用,可理解为远程函数调用。
最后来张图吧,这样更形象点:
三、建立握手
1. 连接失败(两次试探)
2. 连接成功(握手)
2.1 握手流程:
2.1.1 简单握手模式
2.1.2 复杂握手模式
接下来看一个连接实例,结合wireshark抓包结果来看一下整个流程:
2.2 推流
2.3 拉流
四、保存文件
以flv文件格式为例,可以通过文件开头的三个字节来判断该文件是否为FLV,其中 F(46)、L(4c)、V(56)。
五、与其他协议对比
其实,与RTMP类似的流媒体协议,还有HLS、HTTP-FLV,下图对三者进行了一个简单的对比。
参考链接:
https://www.cnblogs.com/jimodetiantang/p/8974075.html
https://segmentfault.com/a/1190000018582618
https://www.adobe.com/content/dam/acom/en/devnet/rtmp/pdf/rtmp_specification_1.0.pdf