RTMP:Real Time Messaging Protocol 实时消息传送协议字节序:大端Message Format:Timestamp:4 bytesLength:3 bytesType ID:1 bytesMessage Stream ID:4 bytes 小端Handshakethree static_sized chunksclient:C0 C1 C2server:S0 S1 S2simple handshake:handshake sequence握手开始于客户端发送C0、C1块客户端在发送C2块之前必须等待直到S1块被接收客户端在发送任何其他数据之前必须等待直到S2块被接收服务器在发送S0、S1之前必须等待直到C0被接收或是C1被接收服务器在发送S2之前必须等待直到C1被接收服务器在发送任何其他数据之前必须等待直到C2被接收C0和S0格式一个字节(8bits)本版本是3C1和S1格式1536个字节C2和S2格式1536个字节,是C1和S1的回复响应time:必须包含对等段发送的时间戳(对C2来说是S1,对S2来说是C1)time2:必须包含先前发送的被对端读取的包(S1或C1)的时间戳handshake diagramComplete handshakeChunkingChunk formatA header and data+--------------+----------------+--------------------+----------+ | Basic Header | Message Header | Extended Timestamp | Chunk Data| +--------------+----------------+--------------------+----------+ | ||<------------------- Chunk Header ----------------->|Chunk FormatBasic header:1-3bytes,chunk stream ID and chunk type(fmt) 长度可变type depend on the format of the encoded message headerthe length depend on the chunk stream IDID:3-65599,0\1\2 reserved0:2bytes,ID range 64-319 (the second byte+64)1:3bytes,ID range 64-65599(the third byte*256+the second byte+64)2:low-level protocol2-63:64-319:64-65599:Cs id:6bits 表示2-63的块流ID,0和1表示本字段2或3字节版本Fmt:2bits 表示4种typesCs id-64:块流ID-64的值Message header:0, 3, 7, or 11 bytes ,长度取决于chunk type(fmt)four different formatsType 0:11bytes,块流开始和时间戳返回时必须有这种块Timestamp:3bytes,消息的绝对时间戳在这里发送。
如果时间戳大于或等于16777215(16进制0x00ffffff),该值必须为16777215,并且扩展时间戳必须出现。
Message length:3bytes,数据大小Message type id:1bytes,数据类型Message stream id:4bytes,流IDMessage type:Type 1:7bytes,具有可变大小消息的流(many videoformats),在第一个消息之后的每个消息的第一个块应该使用这个格式。
Type 2:3bytes,具有固定大小消息的流(some audio and data formats),在第一个消息之后的每个消息的第一个块应该使用这个格式。
Type 3:块没有头。
流ID,消息长度,时间戳都不出现。
如果第一个消息和第二个消息的时间增量与第一个消息的时间戳相同,那么0类型的块之后必须是3类型的块而,不需要类型2的块来注册时间增量。
如果类型3的块在类型0的块之后,那么类型3的时间戳增量与0类型的块的时间戳相同。
Timestamp delta:3bytes,对于类型1的块和类型2的块,本字段表示先前块的时间戳与当前块的时间戳的差值。
如果增量大于等于1677215(16进制0x00ffffff),这个值必须是16777215 ,并且扩展时间戳必须出现。
否则这个值就是整个的增量。
Message length:3bytes,对于类型0或类型1的块本字段表示消息的长度。
注意,这个值通常与负载长度是不相同的。
Message type id:1bytes,对于0类型和1类型的块,本字段发送消息类型。
Message stream id:4bytes,对于0类型的块,本字段存储消息流ID Extended timestamp:0-4bytes,只有当块消息头中的普通时间戳设置为0x00ffffff时,本字段才被传送。
如果普通时间戳的值小于0x00ffffff,那么本字段一定不能出现。
如果时间戳字段不出现本字段也一定不能出现。
类型3的块一定不能含有本字段。
Chunk data:默认长度为128bytes,块的大小可配置,最大65535bytes,最小128bytes,块越大CPU使用率越低,但是也导致大的写入,在低带宽下产生其他内容的延迟。
总结:RTMP协议由包头和包体(数据)组成,包头可以是四种长度:12、8、4、1bytes,即basic header + message header。
Basic header:1bytes(官方文档即上面说可能不止1byte,但实际情况只用1byte 就够了,原因:chunk basic head的长度为1~3个字节,具体长度主要是依赖chunk stream ID的长度,所谓chunk stream ID是flash server用来管理连接的客户端的信令交互的标识,在red5的文档中称之为channel ID,协议最大支持65597个streamID 从3~65599。
ID 0,1,2为协议保留,0代表ID是64~319(第二个byte + 64);1代表chunk stream ID为64~65599((第三个byte)* 256 + 第二个byte + 64)(小端表示);2代表该消息为低层的协议(在RTMP协议中控制信令的chunk stream ID都是2)。
3~63的chunk stream ID就是该byte的值。
没有附加的字段来标识chunk stream streamID。
在这里要指出的是虽然RTMP 的chunk stream ID理论是可以达到65599,但是目前使用的chunk stream ID 很少,2~7都是约定的,8是用来传输publish play等命令,其他的chunk stream ID目前好像没有使用,所以目前chunk basic head的长度一般为1个字节),由chunk type和chunk channel ID组成。
Chunk type占据前两个bit,决定message header的大小,即type0,type1,type2,type3,分别为11,7,3,0bytes,它可以用掩码0xC0进行与运算。
Chunk channel id占据后面6个bits,Stream ID和Channel ID对应关系为:StreamID=(ChannelID-4)/5-1其可以为以下内容:02 ping和ByteRead通道03 invoke通道,我们的connect() publish()和自字写的NetConnection.Call() 数据都是在这个通道的04 audio和vedio通道05、06、07 服务器保留,经观察FMS2用这些channel也用来传送音频或视频在rtmp包中经常看见的0xC2,就表示type为type3,channel Id为2。
Message header:(11,7,3,0bytes)Timestamp:3bytesLength:3bytes,数据实际长度,可超过最大长度128bytes,如果超过128bytes,那么由多个后续RTMP封包组合,每个后续的RTMP封包头只占1bytes,一般以0xC?开头。
Type ID:1bytesStream ID:4bytes,little-endian,是音视频流的ID,如果TypeID!=0x08或!=0x09,那么streamID为0。
streamID与ChannelID之间计算公式为:streamID=(channelID-4)/5+1;前面说包头有几种长度,第一个长度是12bytes,包含了全部的头信息,第一个数据流也就是流的开始必须是这个长度。
第二种8bytes的包,没有了streamID,发这种包,对方就默认此streamID和上次相同,一个视频数据在第一个流之后都可以使这种格式,比如一个1M的视频,第一次发128bytes用12bytes的包,之后每次发的数据都应该用8bytes的包。
当然如果每次都用12bytes也没有问题。
第三种为4bytes,只有chunk_type和时间戳,缺少的对方认为与之前的一样,实际应用中很难出现。
第四中就只有chunk_type一个byte。
如果一次数据超过了长度(默认是128bytes),就要分块,第一个块是12bytes或者8bytes的,之后的块就是1byte。
因为分的N 块,每一块的信息都是一样的,所以只需要告诉对方此次包的长度就行了。
RTMP message format有两部分:a header and payload(message data)Message header:Message type:1bytes,1-6用于protocol control messageLength:3bytes,payload的大小,大端Timestamp:4bytes,大端Message stream ID:3bytes,大端Payload:message dataProtocol control messageMessage stream ID 必须为0,chunk stream ID必须为2。
Message type ID为1、2、3、5、6。