RTP 包 · 实时媒体的载体

RTP 是音视频在网络上传输的基本载体。这一章读 modules/rtp_rtcp/source/rtp_packet.h,讲清 RTP 包的头部字段——SSRC、序号、时间戳、payload type、marker,它们各自解决什么问题,以及 RtpPacketToSend 与 RtpPacketReceived 两个方向的封装。

作者 David更新于 第 33 篇(共 112 篇)

RTP 包 · 实时媒体的载体

安全通道建好了,媒体终于要在上面流动。承载音视频的基本单位,是 RTP 包(RFC 3550)。第 4 部分进入 modules/rtp_rtcp/,而一切从这个包的结构讲起——它的每个头部字段,都是为「实时媒体过不可靠网络」量身设计的。

RTP 包 = 头 + 负载

一个 RTP 包很简单:一个头部加一段负载(payload)。负载是编码后的媒体数据(一段音频、一片视频);头部则是一组精心设计的字段。modules/rtp_rtcp/source/rtp_packet.h 里,RtpPacket 类把这些字段暴露成访问器:

// modules/rtp_rtcp/source/rtp_packet.h(节选)
class RtpPacket {
  bool Marker() const;              // 标记位(视频:帧结束)
  uint8_t PayloadType() const;      // 负载类型(哪种编解码器)
  uint16_t SequenceNumber() const;  // 序号(每包 +1)
  uint32_t Timestamp() const;       // 时间戳(采样时刻)
  uint32_t Ssrc() const;            // 同步源(哪条流)
};

五个关键字段,五个问题

这几个字段,每个都解决实时传输的一个具体问题:

RTP 头部的字段,是「在乱序、丢包的网络上重建媒体」所需信息的最小集合:

  • Ssrc(同步源) —— 一个 32 位随机数,标识这是哪一条流。一次通话有多条流(你的音频、你的视频、对方的……),全靠 SSRC 区分。BUNDLE把多条流挤一条传输后,接收端正是靠 SSRC 分流。
  • SequenceNumber(序号) —— 每发一个包 +1。它让接收端能发现丢包(序号跳了)和乱序(序号乱了)——UDP 不保证顺序和送达,序号是重建秩序的钥匙,也是 NACK 重传、FEC 的基础。
  • Timestamp(时间戳) —— 媒体的采样时刻(不是发送时刻)。它决定这段媒体该在什么时候播放,以及音视频怎么同步(音频、视频各有时间戳,按它对齐口型)。注意它按媒体采样率走(如音频 48kHz),不是墙上时钟。
  • PayloadType(负载类型) —— 一个数字,指明负载用哪种编解码器(如 111=Opus、96=VP8)。接收端据此选对解码器。这个数字怎么分配,下一章有讲究。
  • Marker(标记位) —— 一个比特,含义随媒体而定。视频里它常标记一帧的最后一个包(一帧可能拆成多个 RTP 包),接收端据此知道「这帧收全了,可以组装了」。

这五个字段合起来,就够接收端在混乱的网络之上,把媒体重新拼回有序、可播放、可同步的样子。 RTP 的精妙,在于用极简的头部,给出了对抗真实网络所需的全部元信息。

两个方向:ToSend 与 Received

RtpPacket 是基类,收发两侧各有一个子类(modules/rtp_rtcp/source/):

类方向特点
RtpPacketToSend发送除基础字段外,带发送侧元数据(如是否重传、分配信息、原始序号)
RtpPacketReceived接收带接收侧元数据(到达时间等,供抖动、反馈计算)

分开是因为收发两侧关心的元数据不同:发送侧要记「这个包发出去了没、是不是重传」,接收侧要记「这个包什么时候到的」。RtpPacketToSend 还有个细节:重传时它的传输序号可能和原始 SequenceNumber() 不同(RTX 用独立的序号空间)。

头部之外:头扩展

标准 RTP 头字段是固定的那几个,但实时通信常需要更多元数据——比如「这个包发送时的绝对时间」「音量大小」「视频旋转角度」。这些通过 RTP 头扩展(header extensions) 携带,是一套可扩展机制。它太重要(拥塞控制、音视频同步都靠它),值得下一章专讲。

小结与下一章

RTP 包 = 头 + 负载,是实时媒体的载体(RtpPacket,modules/rtp_rtcp/source/rtp_packet.h)。五个关键头字段各解决一个问题:Ssrc 标识哪条流、SequenceNumber 发现丢包 / 乱序、Timestamp 定播放时刻与音视频同步、PayloadType 指明编解码器、Marker 标记帧边界。收发两侧分别用 RtpPacketToSend / RtpPacketReceived,携带各自的元数据。

标准头之外,更多元数据靠头扩展携带——拥塞控制、音视频同步都离不开它。下一章专讲这套机制。👉 RTP 头扩展。

参考资料

  • [1] libwebrtc 源码.modules/rtp_rtcp/source/rtp_packet.h、rtp_packet_to_send.h、rtp_packet_received.h。
  • [2] libwebrtc 源码.g3doc/rtp.md(RTP 概览)。
  • [3] IETF RFC 3550「RTP」§ 5(包格式)。

本页目录