Adobe公司太坑人了,官方文档公布的信息根本就不全,如果只按照他上面的写的话,是没法用的。按照文档上面的流程,server和client连接之后首先要进行握手,握手成功之后进行一些交互,其实就是交互一些信息以确认大家都是用的同一个协议,交互成功之后就开始传数据了。
首先说下rtmp协议包的格式。握手之后,rtmp传输一个数据默认的长度是128bytes,这128bytes不包括包头的长度,只是数据的长度,文档上面没有说明,很憋了我一段时间,数据超过这个长度之后就要分块,超过128bytes的数据放到下一个块中,以此类推。块大小是可配置的,最大块是65535字节,最小块是128字节。块越大CPU使用率越低,但是也导致大的写入,在低带宽下产生其他内容的延迟。
Rtmp协议是包头加包体(数据)组成,包头可以是4种长度的任意一种:12, 8, 4, 1 byte(s)。包头包含了head type、时间戳、amf size、amf type、streamID。
完整的RTMP包头有12字节,由下面5个部分组成:
用途 |
大小(Byte) |
含义 |
Head_Type |
1 |
包头 |
TIMER |
3 |
时间戳 |
AMFSize |
3 |
数据大小 |
AMFType |
1 |
数据类型 |
StreamID |
4 |
流ID |
Head_Type占用RTMP包的第一个字节,这个字节里面记录了包的类型和包的ChannelID。Head_Type字节的前两个Bits决定了包头的长度。
Head_Type的前两个Bit和长度对应关系,header length是包头的长度:
Bits |
Header Length |
00 |
12 bytes |
01 |
8 bytes |
10 |
4 bytes |
11 |
1 byte |
一个视频流的第一个包必须是12bytes,也就是00,要告诉对方这个流的信息。
Head_Type的后面6个Bits记录着ChannelID,其为一下内容:
02 |
Ping 和ByteRead通道 |
03 |
Invoke通道 我们的connect() publish()和自字写的NetConnection.Call() 数据都是在这个通道的 |
04 |
Audio和Vidio通道 |
05 06 07 |
服务器保留,经观察FMS2用这些Channel也用来发送音频或视频数据 |
比如传一个视频流,第一个块的head type就是00 00 00 04.(0x04)。实测fms用4或者5在传影视频。官方文档上面说head_type可能会不止一个byte,但实际情况用一个byte也够了。
TiMMER - 时间戳
音视频的播放同步是由时间戳来控制的,单位是毫秒。如果时间戳大于或等于16777215(16进制0x00ffffff),该值必须为16777215,并且扩展时间戳必须出现,4bytes的扩展时间戳出现在包头之后包体之前。这个时间戳一般去flv文件里面每个tag里面的时间戳。
AMFSize - 数据大小
AMFSize占三个字节,这个长度是AMF长度,其实就是本次数据的长度。
AMFType - 数据类型
AMFType是RTMP包里面的数据的类型,占用1个字节。例如音频包的类型为8,视频包的类型为9。下面列出的是常用的数据类型:
0×01 |
Chunk Size |
changes the chunk size for packets |
0×02 |
Unknown |
|
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 |
|
0×08 |
Audio Data |
packet containing audio |
0×09 |
Video Data |
packet containing video data |
0x0A-0x0E |
Unknown |
|
0x0F |
FLEX_STREAM_SEND |
TYPE_FLEX_STREAM_SEND |
0x10 |
FLEX_SHARED_OBJECT |
TYPE_FLEX_SHARED_OBJECT |
0x11 |
FLEX_MESSAGE |
TYPE_FLEX_MESSAGE |
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. |
0×16 |
StreamData |
这是FMS3 |