RTMP传输基本流程
发送端
- Step 1: 把数据封装成消息(Message)。
- Step 2: 把消息分割成消息块(Chunk, 网络中实际传输的内容)。
- Step 3: 将分割后的消息块(Chunk)通过TCP协议发送出去。
接收端:
- Step 1: 在通过TCP协议收到数据后, 先将消息块重新组合成消息(Message)。
- Step 2: 通过对消息进行解封装处理就可以恢复出数据。
RTMP的突出优点是: 延时低,正常延时1~3秒,理想的话直播可控制在1秒之内。
它是怎么做到的?
有什么好的设计思想?
RTMP设计思想
大而化小 轻车简行
RTMP协议中基本的数据单元称为消息(Message)。
在互联网中传输数据时, 消息(Message)会被拆分成更小的单元, 称为消息块(Chunk).
大的Message被切割成利于在网络上传输的小Chunk,个人认为这是RTMP之所以延时低的核心原因。
切成小块, 还可防止大的数据块(如视频数据)阻塞小的数据块(如音频数据或控制信息)。
本是天涯同路人 你方唱罢我登场
RTMP基于TCP协议,包括控制信息、视频数据、音频数据都共用同一个TCP Connection。
也就是说路只有一条。而且同一时间只允许一辆车通过。
生成好的视频Chunk和音频Chunk,依次上路。
这就涉及到RTMP中一个非常重要的概念: 复用。
RTMP协议开篇是这么介绍的:
Abstract
This memo describes Adobe’s Real Time Messaging Protocol (RTMP), an
application-level protocol designed for multiplexing and packetizing
multimedia transport streams (such as audio, video, and interactive
content) over a suitable transport protocol (such as TCP).
其中multiplexing就是复用的意思,指的就是将独立的音视频数据整合到一个数据流,让音视频流可以同步传输的过程。
RTMP直播中,实时生成视频Chunk和音频Chunk,依次加入到数据流,通过网络发送到客户端。
复用在RTMP中是传输方式,也是音视频同步的关键。
事分轻重缓急 军令最重 粮草次之
在RTMP中,消息(Message)主要分为两大类: 控制消息和数据消息。
数据消息中由包括Video 消息和Audio 消息等。
这些消息都是怎么进行管理的呢?
有点像车辆的管理问题。
也就是说路,只有一条,到底谁先走呢,谁后走呢?
答案是: 分优先级,优先级高的先行。优先级低的不能阻塞优先级高的。
RTMP协议可从整体分为两个层次:
Message stream
属于应用层次消息,Chunk stream
属于更底层RTMP协议层次。
RTMP Chunk Stream does not provide any prioritization or similar forms of control, but can be used by higher-level protocols to provide such prioritization.
For example, a live video server might choose to drop video messages
for a slow client to ensure that audio messages are received in a
timely fashion, based on either the time to send or the time to
acknowledge each message.
RTMP Chunk Stream
层级没有优先级的划分,而是在高层次Message stream
提供优先级的划分。
也就是说: 不同类型的消息会被分配不同的优先级,当网络传输能力受限时,优先级用来控制消息在网络底层的排队顺序。
比如当客户端网络不佳时,流媒体服务器可能会选择丢弃视频消息,以保证音频消息可及时送达客户端。
Chunking allows large messages at the higher-level protocol to be
broken into smaller messages, for example to prevent large low priority
messages (such as video) from blocking smaller high-priority
messages (such as audio or control).
RTMP Chunk Stream
层级允许在Message stream
层次,将大消息切割成小消息,这样可以避免大的低优先级的消息(如视频消息)阻塞小的高优先级的消息(如音频消息或控制消息)。
Protocol Control Messages
RTMP Chunk Stream uses message type IDs 1, 2, 3, 5, and 6 for
protocol control messages.
These messages contain information needed by the RTMP Chunk Stream protocol.
These protocol control messages MUST have message stream ID 0 (known as the control stream) and be sent in chunk stream ID 2.
Protocol control messages take effect as soon as they are received;
their timestamps are ignored.
Protocol Control Messages
属于RTMP Chunk Stream
层级的控制消息,用于该协议的内部控制。
User Control Messages (4)
RTMP uses message type ID 4 for User Control messages.
These messages contain information used by the RTMP streaming layer.
Protocol messages with IDs 1, 2, 3, 5, and 6 are used by the RTMP
Chunk Stream protocol (Section 5.4).
**User Control messages SHOULD use message stream ID 0 (known as the control stream) ** and, when sent over RTMP Chunk Stream, be sent on
chunk stream ID 2. User Control messages are effective at the point
they are received in the stream; their timestamps are ignored.
User Control Messages (4)
是RTMP streaming layer
(即Message stream层次)的消息。
- 军令最重
协议控制消息(Protocol Control Messages)和用户控制消息(User Control Messages)应该包含消息流ID 0(控制流)和块流ID 2,并且有最高的发送优先级。 - 粮草次之
数据消息(音频信息、音频消息)比控制信息的优先级低。
另外,一般情况下,音频消息比视频数据优先级高。
凡事好商量
发送端,在将Message切割成Chunk的过程中,是以Chunk Size(默认值128字节)为基准进行切割的。
Larger chunk sizes reduce CPU usage, but also commit to larger writes that can delay other content on lower bandwidth connections. Smaller chunks are not good for high bit rate streaming.
Chunk Size越大,切割时CPU的负担越小;但在带宽不够宽裕的环境下,发送比较耗时,会阻塞其他消息的发送。
Chunk Size越小,利于网络发送,但服务器CPU负担大。不适用于高码率数据流的情况。
Chunk Size是可以实际情况进行改变的,即通过发送控制命令(Set Chunk Size
)的方式进行更新。
The chunk size is configurable. It can be set using a Set Chunk Size
control message (Section 5.4.1). Chunk size is maintained independently for each direction.
Protocol control message 1, Set Chunk Size, is used to notify the
peer of a new maximum chunk size.
The maximum chunk size defaults to 128 bytes.
The maximum chunk size SHOULD be at least 128 bytes, and MUST be at
least 1 byte.
充分考虑流媒体服务器、带宽、客户端的情况,通过Set Chunk Size
可动态的适应环境,从而达到最优效果。
能偷懒时就偷懒
RTMP Chunk Header
的长度不是固定的,分为: 12 Bytes、8 Bytes、4 Bytes、1 Byte
四种。
Chunking also allows small messages to be sent with less overhead, as
the chunk header contains a compressed representation of information
that would otherwise have to be included in the message itself.
一般情况下,msg stream id
是不会变的,所以针对视频或音频, 除了第一个RTMP Chunk Header是12Bytes的,后续即可采用8Bytes的。
如果消息的长度(
message length
)和类型(msg type id
, 如视频为9
或音频为8
)又相同,即可将这两部分也省去,RTMP Chunk Header
采用4Bytes类型的。如果当前
Chunk
与之前的Chunk相比, msg stream id
相同,msg type id相同,message length相同,而且都属于同一个消息(由同一个Message切割成),这类Chunk的时间戳(timestamp)也是相同的,故后续的也可以省去,RTMP Chunk Header
采用1 Byte类型的。
当
Chunk Size
足够大时(一般不这么干),此时所有的Message
都只能相应切割成一个Chunk
,该Chunk
仅msg stream id
相同。此时基本上除了第一个Chunk
的Header
是12Bytes
外,其它所有Chunk
的Header
都是8Bytes
。香港卫视的RTMP流:
rtmp://live.hkstv.hk.lxdns.com/live/hks
就是这种情况。
可见Chunk Size很大,为
2147483650
。
小结
RTMP设计的核心思想: 分块 复用 分等级
还有一些设计思想是: 可灵活设置Chunk Size和灵活的选择RTMP Chunk Header(实现压缩的效果)。
References:
rtmp_specification_1.0.pdf
Love ZY Forever