rtmp协议详解中文版RTMP协议分析rtmp 协议




rtmp协议详解中文版RTMP协议分析rtmp 协议

2022-07-20 19:31:27 网络知识 官方管理员

目前国内比较常见的三种直播协议RTMP、HLS、HTTP-FLV,其中rtmp是Adobe公司为Flash播放器和服务器之间提供音视频数据传输服务而设计的应用层私有协议,也是目前各大云厂商直线直播业务所公用的基本直播推拉流协议。本文主要是学习rtmp(实时消息传输协议,Real-TimeMessagingProtocol)的学习笔记,并结合livego的源码分析,和大家一起深入学习RTMP协议最核心的知识点。

  1. RTMP关键概念

1.1什么是Message和Chunk?

Message是RTMP协议中基本的数据单元,不同种类的消息包含不同的MessageTypeID,代表不同的功能。RTMP协议中一共规定了十多种消息类型,分别发挥着不同的作用。

在网络上传输数据时,消息需要被拆分成较小的数据块,才适合在相应的网络环境上传输。RTMP协议中规定,消息在网络上传输时被拆分成消息块(Chunk)。

简单来说就是在一个TCP连接上,将需要传递的Message分成一个或者多个Chunk,同一个Message的多个Chunk组成ChunkStream,在接收端,再把ChunkStream中一个个Chunk组合起来就可以还原成一个完整的Message

rtmp协议详解中文版(RTMP协议分析)(1)

Message被拆分成一个或多个Chunk,然后在网络上发送

拆分的时候,默认的ChunkSize是128字节,以Message大小为300字节举例,进行拆分。

rtmp协议详解中文版(RTMP协议分析)(2)

Message拆分成Chunk举例

1.2Message

消息主要分为三类:协议控制消息、数据消息、命令消息等。

  • 协议控制消息

MessageTypeID=12356和MessageTypeID=4两大类,主要用于协议内的控制,此部分后续详细分析。

  • 数据消息
MessageTypeID=8918

8:Audio音频数据

9:Video视频数据

18:Metadata包括音视频编码、视频宽高等信息。

  • 命令消息

CommandMessage(20,17)此类型消息主要有NetConnection和NetStream两个类,两个类分别有多个函数,该消息的调用,可理解为远程函数调用。

rtmp协议详解中文版(RTMP协议分析)(3)

常见消息格式

1.3Chunk

rtmp协议详解中文版(RTMP协议分析)(4)

Chunk格式

下面分别看看每个字段的含义

1.3.1BasicHeader

包含chunkstreamID(流通道id)和chunktype(即fmt),chunkstreamid一般被简写为CSID,用来唯一标识一个特定的流通道,chunktype决定了后面MessageHeader的格式。BasicHeader的长度可能是1,2,或3个字节,其中chunktype的长度是固定的(占2位,单位是bit),BasicHeader的长度取决于CSID的大小,在足够存储这两个字段的前提下最好用尽量少的字节从而减少由于引入Header增加的数据量。RTMP协议支持用户自定义[3,65599]之间的CSID,0,1,2由协议保留表示特殊信息。0代表BasicHeader总共要占用2个字节,CSID在[64,319]之间;1代表占用3个字节,CSID在[64,65599]之间;2代表该chunk是控制信息和一些命令信息。

  • BasicHeader:1byte
01234567--------|fmt|csid|--------
  • BasicHeader:2byte,csid==0

CSID占14bit,此时协议将于chunktype所在字节的其他bit都置为0,剩下的一个字节表示CSID-64,这样共有8个bit来存储CSID,8bit可以表示[0,255]个数,因此这种情况下CSID在[64,319],其中319=25564。

010123456789012345----------------|fmt|0|csid-64|----------------
  • BasicHeader:3bytes,csid==1

CSID占22bit,此时协议将第一个字节的[2,8]bit置1,余下的16个bit表示CSID-64,这样共有16个bit来存储CSID,16bit可以表示[0,65535]共65536个数,因此这种情况下CSID在[64,65599],其中65599=6553564,需要注意的是,BasicHeader是采用小端存储的方式,越往后的字节数量级越高,因此通过3个字节的每一个bit的值来计算CSID时,应该是:<第三个字节的值>*256<第二个字节的值>64。

012345678901234567890123------------------------|fmt|1|csid-64|------------------------

1.3.2MessageHeader

包含了要发送的实际信息(可能是完整的,也可能是一部分)的描述信息。MessageHeader的格式和长度取决于BasicHeader的chunktype(即fmt)共有四种不同的格式。其中第一种格式可以表示其他三种表示的所有数据,但由于其他三种格式是基于对之前chunk的差量化的表示,因此可以更简洁地表示相同的数据,实际使用的时候还是应该采用尽量少的字节表示相同意义的数据。下面按字节从多到少的顺序分别介绍这四种格式的MessageHeader。

  • ChunkType(fmt)=0:11bytes

rtmp协议详解中文版(RTMP协议分析)(5)

timestamp(时间戳):占用3个字节,因此它最多能表示到16777215=0xFFFFFF=2^24-1,当它的值超过这个最大值时,这三个字节都置为1,这样实际的timestamp会转存到ExtendedTimestamp字段中,接收端在判断timestamp字段24个位都为1时就会去ExtendedTimestamp中解析实际的时间戳。

messagelength(消息数据长度):占用3个字节,表示实际发送的消息的数据如音频帧、视频帧等数据的长度,单位是字节。注意这里是Message的长度,也就是chunk属于的Message的总长度,而不是chunk本身data的长度。

messagetypeid(消息的类型id):1个字节,表示实际发送的数据的类型,如8代表音频数据,9代表视频数据。

messagestreamid(消息的流id):4个字节,表示该chunk所在的流的ID,和BasicHeader的CSID一样,它采用小端存储方式。

  • ChunkType(fmt)=1:7bytes

rtmp协议详解中文版(RTMP协议分析)(6)

type为1时占用7个字节,省去了表示messagestreamid的4个字节,表示此chunk和上一次发的chunk所在的流相同,如果在发送端和对端有一个流链接的时候可以尽量采取这种格式。

timestampdelta:3bytes,这里和type=0时不同,存储的是和上一个chunk的时间差。类似上面提到的timestamp,当它的值超过3个字节所能表示的最大值时,三个字节都置为1,实际的时间戳差值就会转存到ExtendedTimestamp字段中,接收端在判断timestampdelta字段24个bit都为1时就会去ExtendedTimestamp中解析实际的与上次时间戳的差值。

其他字段与上面的解释相同.

  • ChunkType(fmt)=2:3bytes

rtmp协议详解中文版(RTMP协议分析)(7)

type为2时占用3个字节,相对于type=1格式又省去了表示消息长度的3个字节和表示消息类型的1个字节,表示此chunk和上一次发送的chunk所在的流、消息的长度和消息的类型都相同。余下的这三个字节表示timestampdelta,使用同type=1。

  • ChunkType(fmt)=3:0byte

type=3时,为0字节,表示这个chunk的MessageHeader和上一个是完全相同的。当它跟在type=0的chunk后面时,表示和前一个chunk的时间戳都是相同。什么时候连时间戳都是相同呢?就是一个Message拆分成多个chunk,这个chunk和上一个chunk同属于一个Message。而当它跟在type=1或type=2的chunk后面时的chunk后面时,表示和前一个chunk的时间戳的差是相同的。比如第一个chunk的type=0,timestamp=100,第二个chunk的type=2,timestampdelta=20,表示时间戳为10020=120,第三个chunk的type=3,表示timestampdelta=20,时间戳为12020=140。

发表评论:

最近发表
网站分类
标签列表