RTP
含义
RTP 是一种专门为 实时数据传输 设计的网络协议。这里的 "实时数据" 主要指的是 音频 和 视频 这类对传输延迟非常敏感的数据。想象一下,你在进行视频通话或者观看在线直播,你希望画面和声音能够流畅地、几乎同步地到达,而不是卡顿或者延迟很久。RTP 就是为了实现这种目标而生的
RTP在网络传输结构中的位置
- 应用层协议: RTP 运行在 OSI 模型中的 应用层,通常建立在 用户数据报协议 (UDP) 之上
- 不是传输协议,而是传输框架: 需要注意的是,RTP 本身 不是一个完整的传输协议,它更像是一个 传输框架 或者 协议轮廓
- 因为RTP 只定义了数据包的格式、序列号、时间戳等基本信息,而具体的传输控制、可靠性保证、会话建立等功能,RTP 自身并不负责。这些通常需要借助 RTP 控制协议 (RTCP) 以及其他的信令协议 (如 RTSP, SIP--一般GB28181通过SIP) 来完成
数据结构
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X| CC |M| PT | sequence number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| synchronization source (SSRC) identifier |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| contributing source (CSRC) identifiers |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Version (V, 2 bits): RTP 协议版本号,当前版本通常为 2
- Padding (P, 1 bit): 填充标志位。如果设置为 1,表示 RTP 数据包末尾包含一个或多个填充字节,用于满足某些协议对数据包长度的要求 (例如加密算法)。填充字节的最后一个字节指示了填充字节的长度
- Extension (X, 1 bit): 扩展头标志位。如果设置为 1,表示在 RTP 头后面有一个扩展头 (RTP header extension)。扩展头可以用来添加额外的协议信息
- CSRC count (CC, 4 bits): CSRC 计数器,指示 CSRC 标识符列表的长度。取值范围为 0-15,表示最多可以有 15 个 CSRC 标识符
- Marker (M, 1 bit): 标记位。其含义由 Payload Type 决定
- 例如,对于视频,标记位可能用来指示帧的边界;对于音频,可能用来指示会话的开始或结束
- Payload type (PT, 7 bits): Payload 类型。指示 RTP 数据包中携带的媒体数据类型
- Sequence number (16 bits): 序列号。每个 RTP 数据包的序列号递增 1。初始值随机
- Timestamp (32 bits): 时间戳。记录了 RTP 数据包中第一个字节的采样时刻。采样时钟频率由 Payload Type 决定
- 例如,音频的采样频率可能是 8kHz, 44.1kHz 等,视频的帧率可能是 25fps, 30fps 等
- SSRC (Synchronization source identifier, 32 bits): 同步源标识符。
- 随机选择的 32 位数值,唯一标识 RTP 流的源头。在同一个 RTP 会话中,SSRC 值必须唯一
- CSRC list (Contributing source identifiers, 0-15 项, 每项 32 bits): 贡献源标识符列表。只有当 CC 字段不为 0 时才存在。每个 CSRC 标识符也是一个 32 位数值,用于标识参与混合或转换的贡献源
主要特性
目的即是满足实时性传输的要求
- 实时性优先: RTP 的设计目标是 尽可能快地传输数据,即使这意味着可能会有少量的数据包丢失。它牺牲了一定的可靠性来换取低延迟,这对于实时音视频应用至关重要
- Payload 类型标识 (Payload Type): RTP 数据包头中包含一个 Payload Type 字段,用来 指示当前 RTP 包中携带的是什么类型的媒体数据
- 例如,Payload Type 可以标识是 H.264 视频、H.265 视频、AAC 音频、MP3 音频等等
- 序列号 (Sequence Number): RTP 数据包头中包含 序列号
- 数据包排序: 由于 UDP 是无序的,网络传输过程中数据包可能会乱序到达。序列号可以帮助接收端 按照正确的顺序重组数据包
- 丢包检测: 序列号的连续性可以帮助接收端 检测数据包是否丢失。如果序列号不连续,就意味着有数据包在传输过程中丢失了
- 时间戳 (Timestamp): RTP 数据包头中包含 时间戳
- 同步播放: 时间戳记录了 数据包中第一个字节的采样时刻。接收端可以根据时间戳信息,将音频和视频流同步播放,避免音视频不同步的问题
- 抖动补偿 (Jitter Compensation): 网络传输延迟可能会有抖动 (延迟变化)。时间戳可以帮助接收端 计算数据包的延迟,并进行抖动补偿,平滑播放,减少卡顿感
- 同步源标识符 (Synchronization Source, SSRC): RTP 数据包头中包含 SSRC 字段,用于 唯一标识 RTP 流的源头。
- 即使在同一个 RTP 会话中,不同的发送端也会有不同的 SSRC 值。这在多方通信 (例如多人视频会议) 中非常重要,接收端可以通过 SSRC 区分来自不同发送端的数据流
- 贡献源标识符 (Contributing Source, CSRC)
- RTP 数据包头中可以包含 CSRC 列表。CSRC 用于 标识参与混合器 (mixer) 或转换器 (translator) 的贡献源。在一些复杂的网络拓扑中,例如音频会议桥接,多个音频流会被混合成一个流再发送给接收端
H265的RTP
RTP结构分析

- 首行分析(第0和1个字节)
- V (Version - 2 bits, 位 0-1): 版本号。 通常 RTP 版本号为 2,所以这里 V=2
- P (Padding - 1 bit, 位 2): 填充标志。 如果 P=1,表示 RTP 包的末尾包含一个或多个填充字节。填充可能用于使 RTP 包符合某些块大小要求,或者用于加密等目的
- X (Extension - 1 bit, 位 3): 扩展头标志。 如果 X=1,表示在固定 RTP 包头之后,还存在一个扩展头。扩展头可以用于携带额外的协议特定信息
- CC (CSRC Count - 4 bits, 位 4-7): CSRC 计数。 指示紧随固定 RTP 包头之后 CSRC (Contributing Source) 标识符的数量。CSRC 标识符用于标识为混合器 (mixer) 贡献了媒体源的源。对于简单的点对点传输,通常 CC=0
- M (Marker - 1 bit, 位 7): 标记位。 M 位的含义由 负载类型 (PT) 决定。在视频编码中,M 位经常用于标记重要事件
- 帧的结束: 在 H.265 视频中,M=1 可能被用来指示当前 RTP 包是否包含一个视频帧的最后一个 NAL 单元 (Network Abstraction Layer Unit) 或 访问单元 (Access Unit) 的最后一个分片。这对于解码器识别帧边界非常重要
- PT (Payload Type - 7 bits, 位 0-6): 负载类型。 PT 字段指示 RTP 包中数据的 格式。 对于 H.265 视频,会分配特定的 负载类型值,注意这些值是通过会话协议(SDP)等方式协商出来的(通常是SDP)
- 第二行(第2和3字节)
- sequence number (序列号 - 16 bits): 序列号。 序列号 随着每个 RTP 数据包递增。接收端可以使用序列号来
- 检测丢包: 如果序列号不连续,则表明发生了丢包
- 重排序数据包: 在网络传输中,数据包可能会乱序到达。序列号允许接收端按照正确的顺序重组数据包
- sequence number (序列号 - 16 bits): 序列号。 序列号 随着每个 RTP 数据包递增。接收端可以使用序列号来
- 第三行(第4、5、6、7字节)
- timestamp (时间戳 - 32 bits): 时间戳。 时间戳 反映了 RTP 数据包中第一个数据字节的 采样时刻。 对于视频,时间戳 通常与视频帧的捕获或编码时间相关
- 同步播放: 与音频或其他媒体流同步视频播放
- 抖动补偿: 帮助接收端处理网络抖动,平滑播放
- 帧率控制: 解码器可以根据时间戳来调整帧率
- timestamp (时间戳 - 32 bits): 时间戳。 时间戳 反映了 RTP 数据包中第一个数据字节的 采样时刻。 对于视频,时间戳 通常与视频帧的捕获或编码时间相关
- 第四行 (字节 8, 9, 10, 和 11)
- synchronization source (SSRC) identifier (同步源标识符 - 32 bits): SSRC 标识符。 SSRC 标识符唯一地标识了 RTP 包的 同步源。 在一个 RTP 会话中,每个同步源应该有唯一的 SSRC 值
- 区分不同的发送源: 在多方会议或广播场景中,可以区分来自不同发送者的 RTP 流
- synchronization source (SSRC) identifier (同步源标识符 - 32 bits): SSRC 标识符。 SSRC 标识符唯一地标识了 RTP 包的 同步源。 在一个 RTP 会话中,每个同步源应该有唯一的 SSRC 值
- 第五行 (可变长度)
- contributing source (CSRC) identifiers (贡献源标识符 - 可变数量,每个 32 bits): CSRC 标识符。 只有当 CC > 0 时,才会有 CSRC 标识符 字段。
- 这些字段列出了为混合器贡献了媒体源的源的 SSRC 标识符。 在点对点传输中,通常没有 CSRC 标识符
- 补充(RTP负载)
- 包头后面就是数据载荷部分,对于 H.265 视频,这个 payload 部分会包含 H.265 编码的视频数据,通常是以 NAL 单元 (NALU) 的形式组织的。 RFC 7798 详细描述了 H.265 的 RTP 负载格式
- 单元类型: H.265 视频数据被组织成不同类型的 NAL 单元,例如视频参数集 (VPS)、序列参数集 (SPS)、图像参数集 (PPS)、视频编码层 (VCL) NAL 单元 (包含实际的视频编码数据) 等
- 封装方式(此处根据RFC 7798中描述实现)
- 单一NALU模式:一个RTP包中包含一个完整的NALU
- 聚合模式:一个RTP包中包含多个较小的NALU
- 分片模式:一个大的NALU被分割成多个RTP包进行传输
RTP负载封包方式
单一NALU

- PayloadHdr (Payload Header)
- 占据1个字节(注意该字段可能会被更改),官方文档中举例说明将CRA图片处理BLA图片的时候就会对其修改
- 这里复制的就是NALU的头部信息(例如SPS PPS VPS等)'
- DONL (Decoding Order Number Low) (conditional 16-bit field)
- 可选的2字节(存在一定条件才存在)
- 参考
- 存在条件: DONL 字段的出现与参数 sprop-max-don-diff 有关
- 如果 sprop-max-don-diff 大于 0 (对于任何 RTP 流),则 DONL 字段必须存在 (MUST be present)。 此时,NAL 单元的变量 DON 的值就等于 DONL 字段的值
- 如果 sprop-max-don-diff 等于 0 (对于所有 RTP 流),则 DONL 字段必须不存在 (MUST NOT be present)
- NAL unit payload data (NAL 单元负载数据)
- 这部分包含了 NAL 单元的实际负载数据
- 注意这里是不包含Nalu的类型,因为类型被放到了PayloadHdr字段
- OPTIONAL RTP padding (可选的 RTP 填充)
- 如图所示,在 NAL unit payload data 之后,可能有 可选的 RTP 填充字节
- 这部分是标准的 RTP 填充,用于满足 RTP 协议或应用层的一些对包长度的要求,例如为了对齐到特定的块大小,或者用于加密等目的。 RTP 填充的使用由 RTP 包头中的 P (Padding) 标志位 控制
代码实现

--- Simulated NALU ---
Simulated NALU: 27 64 00 0a ac b4 00 00 00 40 00 00 03 00 80 00 00 03 00 00 80 8a 00 00 00 28 00 00 07 84 00 00 1e 84 21 10
--- Packetization Parameters ---
Payload Type (PT): 96
Initial Sequence Number: 12345
Initial Timestamp: 0
SSRC: 0x12345678
--- RTP Header ---
RTP Header: 80 60 30 39 00 00 00 00 12 34 56 78
--- RTP Payload ---
PayloadHdr (NALU Header): 0x27
NALU Payload Data: 64 00 0a ac b4 00 00 00 40 00 00 03 00 80 00 00 03 00 00 80 8a 00 00 00 28 00 00 07 84 00 00 1e 84 21 10
--- Complete RTP Packet ---
Complete RTP Packet: 80 60 30 39 00 00 00 00 12 34 56 78 27 64 00 0a ac b4 00 00 00 40 00 00 03 00 80 00 00 03 00 00 80 8a 00 00 00 28 00 00 07 84 00 00 1e 84 21 10
--- After Packetization ---
Next Sequence Number: 12346
Next Timestamp: 3000
- 日志解释补充
- RTP Header: 显示了生成的 RTP 包头的字节内容
- 80 60: 第一个字节 80 (二进制 10000000) 表示 V=2 (bit 7-8), P=0 (bit 6), X=0 (bit 5), CC=0 (bit 1-4)。 第二个字节 60 (十六进制) = 96 (十进制),是负载类型 PT
- 30 39: 序列号 12345 的十六进制表示 (网络字节序)
- 00 00 00 00: 初始时间戳 0 的十六进制表示
- 12 34 56 78: SSRC 0x12345678 的十六进制表示
- RTP的负载就是Nalu
- RTP Header: 显示了生成的 RTP 包头的字节内容

最低0.47元/天 解锁文章
682

被折叠的 条评论
为什么被折叠?



