RTMP 消息格式

114 阅读3分钟

整个RTMP消息由 header 和body 组成, 

header 又由三部分组成 : 基本头信息、消息头信息、扩展时间戳, 其中basic header是必须要有的, 而 message header 和 extended timetamp 是可有可无的, 需要根据basic header中的参数确定. 

Basic Header

basic header 是动态变化的, 第一个字节有两部分组成, 第一部分占两位是fmt, 后六位是chunk stream id ,范围是2的6次方(0~63), 其中 0 和1 有表示特殊意义.

如果fmt后面六位的值是[2, 63]之间的值, 那么这个值就直接代表了chunk stream id;

如果fmt后面六位是0, 则再往后一个字节才表示chunk stream id, 而且是从64开始 与2^8的和 这样一个范围;

如果fmt后面六位是1, 则用后面三个字节来表示chunk stream id, 范围就是 64 + 2^8 + 2^24 的和这样一个范围.

实际中 如果仅仅是自己推流的话, 第一种情况 一个字节就够用了, 但是如果是云服务平台的话, 会有很多的路被推送和拉取, 所以需要用到第三种情况, 目的是让数据量(字节数)尽量的小.

Message Header

message header 由 time Stamp (3byte)、MsgLength(3byte)、TypeId(1byte)、StreamId(4byte) 4部分组成.

这四个数据根据basic header中的fmt 确定是否存在, fmt占两位,表示4种状态:00、01、10、11.

00 : 四个数据都要包括

01 : 包括time Stamp (3byte)、MsgLength(3byte)、TypeId(1byte)

10 : 包括time Stamp (3byte)

11 : 整个message header都不要

如果同一个数据流需要拆分多个包传输的话,对于第一个包来说, messgea header 数据都是全的, 后面的包 因为是同一个数据流Streamid 是相同的, 所以Streamid 会被省略, 

如果是同一个流中的同一个数据 那么类型也是相同的, type ID也会被省略, 

如果传输的数据长度是固定的, 那么msgLength 也可以省略

如果同一个流的同一个包时间戳也相同的话, 那么时间戳也可以省略.

Extended Timestamp

当message header中的时间戳长度过大无法被表述的时候, 就会在message header后面扩展时间戳: extended timestamp.

当message header中的timestamp 的值为0xFFFFFF的时候,即所有位都为1的时候,就会启动后面的扩展时间戳.

RTMP 消息类型 (message header - type ID)

1 ~ 6 属于控制消息 SID(stream ID)一定是0, 占用的chunk Stream ID一定是2

1 : 设置chunk大小, 传输数据包的时候是以chunk为基础的, 可以设置拆包的大小,默认是128字节

2 : 当流结束的时候, 通知对方停止发送/接收

3 : 协商起始点并开始往后确认,不一定是从0开始的,一开始是一个随机值

5 : 设置发送窗口大小, 否则使用默认值

6 : 设置带宽

数据消息 : 8、9

命令消息

Data Message :  在音视频传输的时候,要传一个metadata, 其中包括采样率采样大小、通道数等信息, 这些信息就属于data message

AMF0 : flash数据编码的格式(类似于KLV, key length value), 0 是最基础的版本, 3是升级后的版本, 为了兼容性 一般使用0版本.

创建流、推流、拉流的时候 都是使用20(AMF0)命令消息.