RTMP(real time messaging protocol)协议
本文为Adobe rtmp规范1.0的中文介绍,其中内容大部分都是翻译自rtmp官方文档rtmp_specification_1.0.pdf
具体文章目录参见文章内侧边栏
介绍
Adobe的实时消息传输协议(RTMP
)通过可靠的流传输(如TCP [RFC0793]
)提供双向消息多路传输服务,用于在端到端之间传输带有时序信息的视频,音频和数据消息的并行流。 穿过多层流,RTMP
消息块流不提供任何控制的优先级别和相似形式,但是可以用于高层协议提供这样的优先级,例如:一段实时视频服务会选择丢弃给缓慢的客户的视频信息确保音频信息可以及时被接收。RTMP消息块流
包含它自己的入队协议控制消息,也提供一个高层协议机制用于嵌入用户的控制消息。
定义
有效负载:Payload
包含在包中的数据,就像音频样本或者压缩的视频数据。
包:Packet
一个数据包由固定的包头和有效负载数据组成,一些底层协议或许需要包的封装来被定义。
端口:Port
在TCP/IP
协议中定义的用正整数表示的端口号用于在传输中提取以区分目标主机的不同应用,用于OSI
传输层的传输选择(TSEL
)就是端口。
传输地址:Transport address
网络地址和端口的组合识别一个传输层终端端口,例如一个IP地址和TCP端口,数据包从一个源传输层地址传送到目标段的传输层地址。
消息流:Message stream
一个通信的逻辑通道,允许消息流通。
消息流ID:Message stream ID
每一个消息拥有一个分配的ID识别跟随的消息流。
消息块:Chunk
消息的片段,消息被分成小的部分,在他们在网络中发送之前交叉存储。消息块确保定制时间戳的端到端全消息传送,穿过多层流。
消息块流:Chunk stream
一个通信的逻辑通道,允许消息块在一个特定的方向上流通,消息块流可以从客户端传送到服务器,也可以相反。
消息块流ID:Chunk stream ID
每一个消息块有一个分配的ID用于识别更随的消息块流。
复合技术:Multiplexing
把分开的音视频数据组合成一条音视频流的过程,使同时传送许多音视频数据成为可能。
逆复合技术:DeMultiplexing
复合的反向过程,交叉存取组装的音频视频数据,使他们成为最初的音视频数据
远程过程调用:Remote Procedure Call (RPC)
允许客户端或服务器在对等端调用子例程或过程的请求。
Action Message Format (AMF)
一种紧凑的二进制格式,用于序列化ActionScript object graphs
。 可以透过 AMF overHTTP
的方式将flash
端资料编码后传回server,server端的remoting adaptor
接收到资料后则会译码回正确的native
对象,交给正确的程序处理。
字节顺序,对齐和时间格式
所有的整数字段都被引入到了字节顺序当中,字节0是第一个显示出来的,也是一个词和一个字段中最重要的。这种顺序就是通常所说的“大端”。如果没有特殊说明,在本文档中数字常量都是用十进制表示。
除另有规定外,RTMP
中的所有数据都是字节对齐的。例如,一个16位字段可能处于奇数字节偏移处。 在指定填充的地方,填充字节应该是0。
RTMP
中的时间戳相对于未指定的时期是以整数毫秒为单位给出的。 通常,每个流将以时间戳0开始,但这不是必需的,只要两个终端在时间点上达成一致。 请注意,这意味着跨多个流(尤其是来自不同主机)的任何同步都需要一些RTMP
外的其他机制。
时间戳必须始终在线性的增加,允许应用程序处理异步传输,带宽度量,检测,和流控制。
由于时间戳长度为32位,因此它们每隔49天,17小时,2分钟,47.296秒滚动一次。 由于流可以连续运行,可能持续数年,RTMP
应用程序应该在处理时间戳时使用序列号算法[RFC1982]
,并且应该能够处理回绕。 例如,假定所有相邻的时间戳都在2^31 - 1
毫秒之间,所以10000会在4000000000之后,而3000000000会在4000000000之前。
时间戳增量delta也被指定为相对于先前时间戳的无符号整数毫秒数。 时间戳增量delta可以是24位或32位。
RTMP块流
本节介绍实时消息传送协议块流(RTMP块流
)。 它为更高级别的多媒体流协议提供复用和打包服务。 虽然RTMP Chunk Stream
旨在与实时消息传送协议配合使用,但它可以处理发送消息流的任何协议。 每条消息都包含时间戳和有效负载类型标识。 RTMP Chunk Stream
和RTMP
一起适用于各种音频 - 视频应用,从一对一和一对多实时广播到视频点播服务,再到交互式会议应用。
当与可靠的传输协议(如TCP [RFC0793]
)一起使用时,RTMP块流
提供了保证所有消息在多个流中按时间排序的端到端传送。 RTMP块流
不提供任何优先级或类似的控制形式,但可以由更高级别的协议提供这种优先级。
消息格式
可以拆分成块以支持复用的消息格式取决于更高级别的协议。 但是,消息格式应该包含下列创建块所必需的字段。
时间戳:
消息的时间戳,这个字段可以传输4个字节。
长度:
消息的有效负载的长度,如果消息头不能被省略,它应该包含在长度中,这个字段在消息块包头中占有3个字节。
类型ID:
协议控制消息的类型字段的范围是被保留的,这些传播信息的消息由RTMP消息块
和高层协议处理,所有其他的类型ID可被高层协议使用,对RTMP消息块
来说当做不透明的值,实际上,RTMP Chunk Stream
中的任何内容都不需要将这些值用作类型; 所有(非协议)消息可以是相同类型的,或者应用程序可以使用类型id来区分同步踪迹而不是类型。 该字段占用块头中的1个字节。
消息流ID:
消息流ID可以是任意的值。 复合到相同块流上的不同消息流可以基于它们的消息流ID进行逆复合操作。 除此之外,就RTMP
块流而言,这是一个不透明的值。 该字段以小尾数格式占用块头中的4个字节。
握手
RTMP
连接始于握手。 rtmp
握手与其他协议的握手不同; 它由三个相同大小的块组成,而不是由可变大小的块组成。
客户端(连接已初始化的终端)和服务器都发送相同的三个块。 为了说明,由客户端发送的3个块分别为C0
, C1
, C2
,由服务端发送的3个块分别为S0
, S1
, S2
。
握手的顺序
握手以客户端发送C0
和C1
消息块位开始,客户端必须等到S1
到达在发送C2
。客户端必须等到S2
接收到才可以发送其他的数据;服务端必须等到C0
到达才发送S0
和S1
,在C1
之后也会等待。服务端必须等到C1
到达才发送S2
,服务端必须等到C2
到达后才发送其他数据。
C0和S0格式
C0
和S0
都是单个8位字节,可以看成一个8位整形字段。
8比特版本:在C0中,这个字段识别客户端需求的RTMP的版本,在S0中,这个字段识别服务器端选择的RTMP的版本,被定义的是版本3,0到2是早前的版本使用的,4到31保留用于未来使用,32到255还没有被允许。不能区分客户的请求的版本的服务应该以3返回,客户端可以选择降级到版本3,或放弃握手。
C1和S1格式
C1
和S1
包长度为1536个8位字节,包含以下字段:
time(4个字节):这个字段包含时间戳,被当做后续消息块从终端发送的时间点,也许是0,或者一些任意的值。为了同步多路消息块流,终端或许希望发送其他消息块流的时间戳的当前值。
zero(4各个字节):这个字段必须全0。
random data(1528个字节):这个字段可以包含任何任意的值,因为每个终端必须区分自己初始化的握手的返回数据和对方初始化