当前位置:
文档之家› RTMP协议分析:RTMP包头、AMF数据
RTMP协议分析:RTMP包头、AMF数据
CORE_String={StringLen(2 Byte) + StringValue(StringLen Byte)} CORE_DATE={value(10 Byte)} CORE_Array={ArrayLen(4 Byte) + Object} CORE_Map={MapNum(4 Byte) + CORE_Object} CORE_Object={CORE_String + Object}
RTMP协议分析 二、AMF数据
(原创) Rtmp包默认的最大长度为128字节,(或通过chunksize改变rtmp包最大长度), 当AMF数据超过128Byte的时候就可能有多个 rtmp包组成,如果需要解码的rtmp包太长则被TCP协议分割成多个TCP包.那么解码的时候需要先将包含rtmp包的tcp封包合 并, 再把合并的数据解码,解码后可得到amf格式的数据,将这些AMF数据取出来就可以对AMF数据解码了. RTMP封包包括包头和AMF数据2部分,AMF数据里面可以是命令也可以是音视频数据。组成服务器和Flash客户端之间的 所有数据都是用AMF格式的数据在传送,例如connect() publish()等命令. AMF数据由2部分组成: ObjType 加上 ObjValue。ObjType的大小为一个字节。ObjValue的大小不固定,和ObjType相关。 常用的ObjType类型和对应的 ObjValue大小整理如下,详细的ObjType的数据在本文的最下面列出:
四、AMFType - 数据类型 AMFType是RTMP包里面的数据的类型,占用1个字节。例如音频包的类型为8,视频包的类型为9。下面列出的是常用的 数据类型:
0×01
Chunk Size
changes the chunk size for packets
0×02
Unknown
0×03
Bytes Read
fms对于同一个流,发布(publish)的时间戳和播放(play)的时间戳是有区别的
publish时间戳,采用相对时间戳,时间戳值等于当前媒体包的绝对时间戳与上个媒体包的绝对时间戳之间的 差距,也就是说音视频时间戳在一个时间轴上面.单位毫秒。 play时间戳,也是相对时间戳,时间戳值等于当前媒体包的绝对时间戳与上个同类型媒体包的绝对时间戳 之间的差距, 注意这里跟上面不同的是强调“同类型的媒体包”。也就是说音视频时间戳分别采用单独的时间 轴,单位毫秒。 flv格式文件时间戳,绝对时间戳,时间戳长度3个字节。超过0xFFFFFF后时间戳值等于TimeStamp & 0xFFFFFF。 flv格式文件影片总时间长度保存在onMetaData的duration属性里面,长度为8个字节,是一个double类型。
六、封包分析
例如有一个RTMP封包的数据0300 00 00 00 01 02 1400 00 00 00 0200 07 63 6F 6E 6E 65 63 74 003F F0 00 00 00 00 00 00 08 ,,, 数据依次解析的含义 03表示12字节头,channelid=3 000000表示时间戳 Timer=0 000102表示AMFSize=18 14表示AMFType=Invoke 方法调用 00 00 00 00 表示StreamID = 0 //到此,12字节RTMP头结束下面的是AMF数据分析,具体的AMF0数据格式请参考 RTMP协议 二、AMF数据 02表示String 0007表示String长度7 63 6F 6E 6E 65 63 74 是String的Ascall值"connect" 00表示Double 3F F0 00 00 00 00 00 00 表示double的0.0 08表示Map数据开始 下面是我用c++实现的完整的rtmp客户端程序下载 RTMP协议分析 二、AMF数据:http://www.cnweblog.com/fly2700/archive/2008/04/09/281432.html 程序下载:http://www.cnweblog.com/fly2700/archive/2008/04/02/280641.html
0x08 0x01
4字节(开始嵌套) 1字节
ObjValue不一定是一个固定的大小,他可以包含另外一个AMF数据,这另外一个AMF数据里面又有ObjType 加上 ObjValue,也就是AMF数据的嵌套关系
AMF0数据的嵌套关系如下:
Object={ObjType + ObjValue} CORE_BOOLEAN={Value(1 Byte)} CORE_NUMBER={Value(8 Byte)}
RTMP协议分析 一、RTMP包头 原创
RTMP协议 封包 参考Red5
RTMP协议封包 由一个包头和一个包体组成,包头可以是4种长度的任意一种:12, 8, 4, 1 byte(s).完整的RTMP包头应该是 12bytes,包含了时间戳,Head_Type,AMFSize,AMFType,StreamID信息, 8字节的包头只纪录了时间 戳,Head_Type,AMFSize,AMFType, 4个字节的包头记录了时间戳,Head_Type。1个字节的包头只记录了Head_Type 。包 体最大长度默认为128字节,通过chunkSize可改变包体最大长度,通常当一段AFM数据超过128字节后,超过128的部分就放 到了其他的RTMP封包中,包头为一个字节. 完 整 的 RTM P包 头 有 12字 节 , 由 下 面 5个 部 分 组 成 :
用途 Head_Type TIMER AMFSize AMFType Stream ID
Baidu Nhomakorabea
大小(Byte) 1 3 3 1 4
含义 包头 时间戳 数据大小 数据类型 流ID
一、Head_Type - 包头类型 Head_Type占用RTMP包的第一个字节,这个字节里面记录了包的类型和包的ChannelID。Head_Type字节的前两个Bit决 定了包头的长度.它可以用掩码0xC0进行"与"计算: Head_Type的前两个Bit和长度对应关系:
Bits
Header Length
00
12 bytes
01
8 bytes
10
4 bytes
11
1 byte
Head_Type的后面6个Bit和StreamID决定了ChannelID。 StreamID和ChannelID对应关系:StreamID=(ChannelID4)/5+1 参考red5
ChannelID 02 03 04 05 06 07
二、TiMMER - 时间戳 时间戳占用RTMP包头的第2、3、4 三个字节。RTMP时间戳可分为绝对时间戳和相对时间戳,纪录的是音视频的时间信 息。相对时间戳指的是二个RTMP包之间的时间间隔,单位毫秒。而绝对时间戳指的是当前封包发送的时刻,单位也是毫 秒。对于音视频的播放,时间戳非常关键,因为音视频的播放同步是由时间戳来控制的,如果你的视频出现卡顿,音视频 不同步,延时越来越大,很可能就是你的时间戳不准导致的。
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
用途 Ping 和ByteRead通道 Invoke通道 我们的connect() publish()和自字写的NetConnection.Call() 数据都是在这个通道的 Audio和Vidio通道 服务器保留,经观察FMS2用这些Channel也用来发送音频或视频数据
例如在rtmp包的数据中里面,发现被插入了一个0xC2,这个就是一字节的包头,并且channelID=2.
0×14
Invoke
like remoting call, used for stream actions too.
0×16
Stream Data
这是FMS3出来后新增的数据类型,这种类型数据中包含AudioData和VideoData
五、StreamID - 流ID 占用RTMP包头的最后4个字节,是一个big-endian的int型数据。我们x86 计算机内存中数据存放都是小尾数模式:littleendian,而网络数据流一般都是大尾数模式:big-endian。 StreamID是音视频流的唯一ID, 一路流如果既有音频包又有视 频包,那么这路流音频包的StreamID和他视频包的StreamID相同,但ChannelID不同。 ChannelID 和StreamID之间的计算公式:StreamID=(ChannelID-4)/5+1 参考red5。如果这个封包既不是音频包,也不是 视频包,那么他的StreamID=0. 例如当音视频包ChannelID为2、3、4时StreamID都为1 当音视频包ChannelID为9的时候StreamID为2
三、AMFSize - 数据大小 AMFSize占三个字节,这个长度是AMF长度,可超过RTMP包的最大长度128字节。如果超过了128字节,那么由多个后续 RTMP封包组合,每个后续RTMP封包的头只占一个字节。一般就是以0xC?开头。1个字节的包头表示这个包的时间戳、 数据大小、数据类型、流ID都和上一个相同ChannelID的RTMP包完全一样。
s end 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
类型说明(ObjType) CORE_String CORE_Object NULL
数据 0x02 0x03 0x05
dataSize 2字节 (2字节的数据纪录了String的实际长度) 0字节(开始嵌套0x00000009表示嵌套结束) 0字节 空字节无意义
CORE_NUMBER
0x00
8字节
CORE_Map CORE_BOOLEAN
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
看起来有些复杂,所以我这里图文并茂来详解,例如完成握手后,Flash向FMS发送的第一个RTMP数据,内 容如下:
蓝色的表示包头,红色的表示ObjType,绿色的表示数据。上面一段数据由2个RTMP包组成,2个RTMP包头 分别用蓝色表示,第一个蓝色的是12字节的包头,后面一个蓝色的C3是一个字节的包头,绿色部分是数据,红色 的是AMF数据类型,整个RTMP解码过程如下 [2008-06-18 16:59:20] DecodeInvoke: [2008-06-18 16:59:20] InvokeName:String:connect [2008-06-18 16:59:20] InvokeID:Double:0 [2008-06-18 16:59:20] Map:MapNum:0 [2008-06-18 16:59:20] Params:{ [2008-06-18 16:59:20] Key:String:objectEncoding [2008-06-18 16:59:20] Value:Double:0 [2008-06-18 16:59:20] Key:String:app [2008-06-18 16:59:20] Value:String:mediaserver [2008-06-18 16:59:20] Key:String:fpda [2008-06-18 16:59:20] Value:Bool:0 [2008-06-18 16:59:20] Key:String:tcUrl [2008-06-18 16:59:20] Value:String:rtmp://127.0.0.1/mediaserver [2008-06-18 16:59:20] Key:String:audioCodecs [2008-06-18 16:59:20] Value:Double:615 [2008-06-18 16:59:20] Key:String:videoCodecs [2008-06-18 16:59:20] Value:Double:76 [2008-06-18 16:59:20] }End Params [2008-06-18 16:59:20] InvokeParams:String:PUBLISHER [2008-06-18 16:59:20] InvokeParams:String:streamRecode