RTMP协议之AMF数据

一、RTMP组成

1、RTMP包头

       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封包中,包头为一个字节。完整的RTMP包头有12字节,由下面5个部分组成:

2、Head_Type - 包头类型

       Head_Type占用RTMP包的第一个字节,这个字节里面记录了包的类型和包的ChannelID。Head_Type字节的前两个Bit决定了包头的长度.它可以用掩码0xC0进行"与"计算。Head_Type的前两个Bit和长度对应关系:

       Head_Type的后面6个Bit和StreamID决定了ChannelID。  StreamID和ChannelID对应关系:StreamID=(ChannelID-4)/5+1 参考red5

       例如在rtmp包的数据中里面,发现被插入了一个0xC2,这个就是一字节的包头,并且channelID=2。

3、TiMMER - 时间戳

       时间戳占用RTMP包头的第2、3、4 三个字节。RTMP时间戳可分为绝对时间戳和相对时间戳,纪录的是音视频的时间信息。相对时间戳指的是二个RTMP包之间的时间间隔,单位毫秒。而绝对时间戳指的是当前封包发送的时刻,单位也是毫秒。对于音视频的播放,时间戳非常关键,因为音视频的播放同步是由时间戳来控制的,如果你的视频出现卡顿,音视频不同步,延时越来越大,很可能就是你的时间戳不准导致的。

       fms对于同一个流,发布(publish)的时间戳和播放(play)的时间戳是有区别的

       publish时间戳,采用相对时间戳,时间戳值等于当前媒体包的绝对时间戳与上个媒体包的绝对时间戳之间的差距,也就是说音视频时间戳在一个时间轴上面.单位毫秒。

       play时间戳,也是相对时间戳,时间戳值等于当前媒体包的绝对时间戳与上个同类型媒体包的绝对时间戳之间的差距, 注意这里跟上面不同的是强调“同类型的媒体包”。也就是说音视频时间戳分别采用单独的时间轴,单位毫秒。

       flv格式文件时间戳,绝对时间戳,时间戳长度3个字节。超过0xFFFFFF后时间戳值等于TimeStamp & 0xFFFFFF。

       flv格式文件影片总时间长度保存在onMetaData的duration属性里面,长度为8个字节,是一个double类型。

4、AMFSize - 数据大小

       AMFSize占三个字节,这个长度是AMF长度,可超过RTMP包的最大长度128字节。如果超过了128字节,那么由多个后续RTMP封包组合,每个后续RTMP封包的头只占一个字节。一般就是以0xC?开头。1个字节的包头表示这个包的时间戳、数据大小、数据类型、流ID都和上一个相同ChannelID的RTMP包完全一样。

5、AMFType - 数据类型

       AMFType是RTMP包里面的数据的类型,占用1个字节。例如音频包的类型为8,视频包的类型为9。下面列出的是常用的数据类型:

6、StreamID - 流ID

       占用RTMP包头的最后4个字节,是一个big-endian的int型数据。我们x86 计算机内存中数据存放都是小尾数模式:little-endian,而网络数据流一般都是大尾数模式: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。

 

二、RTMP中的AMF数据

1、RTMP中的AMF数据

       Rtmp包默认的最大长度为128字节,(或通过chunksize改变rtmp包最大长度), 当AMF数据超过128Byte的时候就可能有多个rtmp包组成,如果需要解码的rtmp包太长则被TCP协议分割成多个TCP包.那么解码的时候需要先将包含rtmp包的tcp封包合并, 再把合并的数据解码,解码后可得到amf格式的数据,将这些AMF数据取出来就可以对AMF数据解码了。

2、AMF数据组成

       RTMP封包包括包头和AMF数据2部分,AMF数据里面可以是命令也可以是音视频数据。组成服务器和Flash客户端之间的所有数据都是用AMF格式的数据在传送,例如connect() publish()等命令.。AMF数据由2部分组成: ObjType 加上 ObjValueObjType的大小为一个字节。ObjValue的大小不固定,和ObjType相关。 常用的ObjType类型和对应的ObjValue大小如下:

       ObjValue不一定是一个固定的大小,他可以包含另外一个AMF数据,这另外一个AMF数据里面又有ObjType 加上 ObjValue,也就是AMF数据的嵌套关系。

       AMF0数据的嵌套关系如下:

  • Object={ObjType + ObjValue}
  • CORE_BOOLEAN={Value(1 Byte)}
  • CORE_NUMBER={Value(8 Byte)}
  • 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}

3、RTMP中的AMF数据实例分析

       从实例中可以知道AMF数据格式:“类型”+[长度]+“值”。

(1)String类型

       String类型中,1 个 byte 的 amf type,2 个 bytes 的字符长度,和 N 个 bytes 的数据。

此例中“02 00 07 5f 72 65 73 75 6c 74”,第 1 个 byte 是 amf 类型,其后 2 个 bytes 是长度,“5f 72 65 73 75 6c 74”是字符串“_result”。此处具体解析其中的一种,后续分析类型。

(a)类型:String

AMF0 type:String 类型,即 0x02。

(b)长度

String length:长度,即00 07。

(c)数据

String:具体数据,此处为字符串“_result”,即5f 72 65 73 75 6c 74。

(2)Number 类型

       Number 类型(其实就是 Double),即0x00,一个 byte 的 amf type,8 个 bytes 的值。

此例中第 1 个 byte 是 amf 类型,其后 8 个 bytes 是值:1。

(3)Object 类型

       Object 类型,即 0x03,第一个 byte 0x03 表示 object,其后跟 N 个 (key + value)。最后以 00 00 09表示 object 结束。

此例中03即表示amf的类型为object类型,其后表示key + value,例如其中的一个实例如下:

00 00 09表示结尾,如下所示:

 

猜你喜欢

转载自blog.csdn.net/King_weng/article/details/114698663