Skip to content

RTMP 协议

实时消息传输协议(RTMP)是一种基于 TCP 的协议,设计用于在服务器和客户端之间传输音频、视频和数据。本文档描述了 RTMP 在 Monibuca(m7s)流媒体服务器中的实现,重点关注协议的架构、握手过程、消息格式和媒体处理能力。

架构概述

Monibuca 中的 RTMP 实现被构建为一个插件,支持通过 RTMP 发布(推流)和播放(拉流)媒体流。该插件自动在 1935 端口注册标准 RTMP 支持,也可以处理安全的 RTMPS 连接。

核心组件

RTMP 插件由以下主要组件组成:

组件描述
RTMPPlugin主插件结构,包含配置和初始化逻辑
RTMPServer处理传入连接的服务器实现
RTMPClient处理主动发起向远端服务器请求(拉流或者推流)的实现
NetConnection管理 RTMP 连接状态和消息交换
NetStream媒体传输的逻辑通道

该插件使用 Monibuca 的插件系统注册,并实现了推流和拉流所需的必要接口。

RTMP 协议流程

连接建立

当客户端连接到 RTMP 服务器时,会发生以下序列:

  1. 建立 TCP 连接
  2. 执行 RTMP 握手
  3. 交换 Connect 命令
  4. 创建流
  5. 开始发布或播放操作

握手过程

RTMP 握手是一个三步过程,包括以下步骤:

  1. C0/S0:单字节版本交换(通常为 0x03)
  2. C1/S1:交换 1536 字节,包含时间、版本和随机数据
  3. C2/S2:交换另一个 1536 字节,回显对等方的时间戳

Monibuca 支持简单和复杂(加密)握手:

C0: 版本字节 (0x03)
C1: 时间 (4 字节) + 零 (4 字节) + 随机数据 (1528 字节)
S0: 版本字节 (0x03)
S1: 时间 (4 字节) + 零 (4 字节) + 随机数据 (1528 字节)
C2/S2: 时间 (4 字节) + Time2 (4 字节) + 随机数据 (1528 字节)

对于复杂握手,服务器计算并验证 HMAC-SHA256 摘要以验证客户端身份。

消息格式和分块处理

分块格式

RTMP 将消息作为分块传输,以实现多路复用和带宽控制。每个分块都有一个根据类型不同而变化的头部:

分块类型头部大小内容
类型 0 (完整)12 字节时间戳 (3) + 消息长度 (3) + 消息类型 ID (1) + 消息流 ID (4)
类型 18 字节时间戳增量 (3) + 消息长度 (3) + 消息类型 ID (1)
类型 24 字节时间戳增量 (3)
类型 31 字节无额外头部(继续)

分块头部以基本头部开始,包含分块流 ID 和分块类型。

分块处理

NetConnection 类通过以下主要函数处理分块:

  1. readChunk():从连接读取分块
  2. readChunkStreamID():从头部提取分块流 ID
  3. readChunkType():处理分块类型并组装消息
  4. sendChunk():将消息分割成分块进行传输

消息类型

RTMP 定义了多种消息类型,由实现处理:

消息类型 ID描述
1设置分块大小
2中止消息
3确认
4用户控制消息
5窗口确认大小
6设置对等带宽
8音频消息
9视频消息
20AMF0 命令

RecvMessage() 函数处理这些消息并根据类型将它们分派到适当的处理程序。

媒体数据处理

视频处理

RTMP 实现支持多种视频编解码器,包括:

  1. H.264 (AVC):标准视频编解码器
  2. H.265 (HEVC):高效视频编解码器
  3. AV1:下一代视频编解码器(实验性支持)

RTMP 中的视频数据格式化为带有指示帧类型和编解码器 ID 的头部字节,后跟合成时间和实际编码数据。

RTMPVideo 结构实现了 IAVFrame 接口,提供以下方法:

  1. Parse():从视频帧中提取编解码器信息
  2. Demux():将 RTMP 视频格式转换为原始 NAL 单元
  3. Mux():将原始 NAL 单元转换为 RTMP 视频格式
  4. ConvertCtx():从序列头创建编解码器上下文

对于 H.264/H.265,实现处理序列头(SPS/PPS/VPS)并可以过滤有问题的 NAL 单元。

音频处理

实现支持多种音频格式:

  1. AAC:高级音频编码
  2. PCMA:A-law PCM
  3. PCMU:μ-law PCM

RTMP 中的音频数据包括指示编解码器类型、采样率、采样大小和通道数的头部字节。

RTMPAudio 结构也实现了 IAVFrame 接口,具有与 RTMPVideo 类似的方法。

流管理

发布和播放

RTMP 区分两种主要操作:

  1. 发布:向服务器发送媒体数据
  2. 播放:从服务器接收媒体数据

实现通过命令消息处理这些操作。

实现创建 NetStream 对象来管理单个流,并将它们连接到 Monibuca 核心的 PublisherSubscriber 组件。

配置和初始化

RTMP 插件可以配置以下设置:

设置默认值描述
ChunkSize1024RTMP 分块大小
KeepAlivefalse启用连接保活
C2false验证 C2 握手包

初始化时,插件注册其功能和地址格式:

rtmp://{hostName}/{streamPath}       (端口 1935)
rtmp://{hostName}:{port}/{streamPath} (自定义端口)
rtmps://{hostName}/{streamPath}      (端口 443)
rtmps://{hostName}:{port}/{streamPath} (自定义端口)

与 Monibuca 核心集成

RTMP 插件通过多种机制与 Monibuca 核心系统集成:

  1. 通过 m7s.InstallPlugin 进行插件注册
  2. 用于连接处理的任务系统
  3. 用于媒体处理的 Publisher/Subscriber 接口
  4. 用于高效数据处理的内存分配系统

这种设计使 RTMP 功能能够无缝集成,同时保持整个系统的模块化。

总结

Monibuca 中的 RTMP 协议实现为流媒体应用程序提供了坚实的基础。它支持:

  1. 具有简单和复杂握手的完整 RTMP 协议
  2. 多种视频(H.264、H.265、AV1)和音频(AAC、PCMA、PCMU)编解码器
  3. 发布和播放操作
  4. 通过 RTMPS 的安全连接
  5. 媒体数据的内存高效处理

此实现使 Monibuca 能够与各种 RTMP 客户端交互,包括媒体编码器、播放器和其他流媒体服务器。

基于 AGPL 许可发布