rtmp以TCP方式推流,分为一个个消息包。
握手开始于客户端发送 C0,C1 块。 服务端在发送 S0 和 S1 之前必须等待接收 C0,也可以等待接收 C1。 服务端在发送 S2 之前必须等待接收 C1。 在发送 C2 之前客户端必须等待接收 S1 。 客户端在发送任何数据之前必须等待接收 S2。 服务端在发送任何数据之前必须等待接收 C2。 |
客户端RTMP的版本号,一个字节,一般是3
rtmp1.0规范所定义的版本是 3;0-2 是早期产品所用的,已被丢弃;4-31保留在未来使用;32-255 不允许使用(为了区分其他以某一字符开始的文本协议)。
如果服务无法识别客户端请求的版本,应该返回 3 。客户端可以选择减到版本 3 或选择取消握手
一共1536字节
4-time + 4-zero + 1528-random
这里可以一次性把S0,S1,S2 3个都发给客户端。
S0 1 byte (服务端RTMP的版本号),范围同C0
S1 1536 bytes (4-time + 4-zero + 1528-random),格式同C1
S2 1536 bytes (4-time + 4-zero + 1528-echo),是对C1的回复,格式同C2
一共1536字节,是对S1的回复
4-time + 4-time2 + 1528-echo
随机回复:1528 字节 本字段必须包含对端发送的随机数据字段(对 C2 来说是 S1,对 S2 来说是 C1) 。 每个对等端可以用时间和时间 2 字段中的时间戳来快速地估计带宽和延迟。
开始推送音视频数据
[Message Type ID][Payload Length][Time Stamp][Stream ID] 这四部分称为 Message Header。
Message Type ID: 在1-7的消息用于协议控制,这些消息一般是RTMP协议自身管理要使用的消息,用户一般情况下无需操作其中的数据。Message Type ID为8,9的消息分别用于传输音频和视频数据。Message Type ID为15-20的消息用于发送AMF编码的命令,负责用户与服务器之间的交互,比如播放,暂停等等。
Payload Length: 负载的长度
Time Stamp: 时间戳
Stream ID: 流的ID
一帧数据有时候会很大,比如几十M甚至更大。但是为了方便在网络上传输,需要把数据拆分成一个个较小的块,这里称之为消息块(Chunk)。
[Chunk Basic Header][Chunk Message Header][Extended TimeStamp] 称之为 Chunk Header。
Header Type + Channel ID (一共1-3个字节)
第一个字节的高2位决定[Chunk Message Header]的长度
计算公式如下:
/**
* data : Basic Header Data
* fmt : Header Type
* cid : Channel ID
* return : Basic Header Data Length
*/
int rtmp_chunk_basic_header_read(const uint8_t* data, uint8_t* fmt, uint32_t* cid)
{
*fmt = data[0] >> 6;
*cid = data[0] & 0x3F;
if (0 == *cid)
{
*cid = 64 + (uint32_t)data[1];
return 2;
}
else if (1 == *cid)
{
*cid = 64 + (uint32_t)data[1] + ((uint32_t)data[2] << 8) /* 256 */;
return 3;
}
else
{
return 1;
}
}
以最大fmt =00 length(Chunk Message Header) == 12 为例
Chunk Message Header的结构是:
timestamp + message_length + message_type + msg_stream_id
其中message_type是一个枚举变量:
These messages are sent to perform some operations like connect, createStream, publish, play, pause on the peer.
命令消息主要分成两种NetConnection和NetStream。
connect,call,close,createStream命令可以在NetConnection中发送。
coonect(name,TranscationID,Command Object pair),play,publish,seek,pause等命令可以在NetStream中发送。
时间戳
块数据,接收方把块数据组合成完整的一帧flv tag数据