一、问题:
webrtc当中有几个比较相似的类,看着都是发送RTP数据包的,分别是:RtpPacketToSend
和RtpSenderVideo
还有RtpVideoSender
以及RTPSender
,这说明什么呢?首先,说明我会很多连词(🤬),元规正传(🤬),其次,说明他们都很像,容易给我们搞晕,最后,我们需要搞明白,这几个类各自扮演什么角色,设计意图是什么呢?如果是你设计,你怎么设计,整一个万能类不就行了,反正就是发送RTP数据?行不行,你说!
小的不才,有点感悟记录下来,行不行您自己看!
二、 RtpPacketToSend 的主要作用
主要代码
class RtpPacketToSend : public RtpPacket {
public:
// 省略不重要的牛马
private:
// 抓取时间,用于统计或同步
int64_t capture_time_ms_ = 0;
// 包类型(packet_type_):音频、视频、冗余等
absl::optional<RtpPacketMediaType> packet_type_;
// 是否允许重传
bool allow_retransmission_ = false;
absl::optional<uint16_t> retransmitted_sequence_number_;
std::vector<uint8_t> application_data_;
// 是否是视频帧第一个包/关键帧
bool is_first_packet_of_frame_ = false;
bool is_key_frame_ = false;
};
核心作用
RtpPacketToSend
是 WebRTC 代码中发送端专用的 RTP 包对象,承载了要发送的 RTP 包及其元数据。
它继承自 RtpPacket
,不光包含了基本的 RTP 头、负载、扩展字段,还附加了“只对发送过程有用的上下文元数据”,比如:
- 抓取时间(capture_time_ms_):用于统计或同步
- 包类型(packet_type_):音频、视频、冗余等
- 是否是重传包、原序列号
- 是否允许重传
- 是否是视频帧第一个包/关键帧
- 部分计时信息(如包化完成时间、发送出口时间等)
一句话总结:
RtpPacketToSend
= “封装着即将要发出的RTP包内容 + 发送相关的所有额外属性”
三、RTPSender
RTP 发送器基类,负责整个 RTP (不分媒体类型) 的发送流程。
核心职能:
- RTP 头生成、序列号分配
- 调用底层 socket 发送
- 调用上层接口获得要发什么
- 负责一些重传、FEC等通用功能
有音视频共用逻辑(针对 RTP 协议通用部分)
四、RtpSenderVideo
/ RtpVideoSender
这两个其实逻辑上是分开的,但在不同WebRTC代码阶段、分支和版本名可能不一样,核心意思都是“视频数据专用 RTP 发送器”。
它们在继承/组合结构上,最终都要依靠 RTPSender 来发送包,但是加上了:
- 对视频的特殊处理(比如分包、关键帧标识等)
- 输出帧状态报告
- 处理视频自己的 RTP 头扩展
通常代码里 RtpSenderVideo
是作为 RTPSender
的成员或持有者。调用“我要发一帧视频”→“如何打包分包”→“每一个分包作为RtpPacketToSend送给RTPSender”处理实际发送。
五、RtpPacketToSend
只负责代表“某一个要被发送出去的RTP包对象”,和 RTPSender
“怎么发、发给谁”是分开的。
六、大致的发包流程(类关系图)
RtpVideoSender
接到一帧视频数据- 封装成多个 RTP 包,每个包一份负载、RTP头,用
RtpPacketToSend
保存 RtpPacketToSend
包含所有要发的包的元信息(如capture时间、包类型、关键帧等)RTPSender
接收这些包,安排好序列号、头部、retransmit、NACK 等发送相关管理- 由
RTPSender
完成最终“投递到UDP”的行为
七、举个栗子:
比如:发送一帧视频流的发送链条
- 编码器输出了一帧 H264/VP8 数据
RtpVideoSender::SendVideo()
被调用- 将一帧切分成n个RTP包(因为包不能太大)
- 循环产生
RtpPacketToSend
对象- 填写每个包的payload
- 设置元数据(是否关键帧,是否第一包,时间戳等)
- 每个RtpPacketToSend喂给RTPSender::Send()
- 内部会进一步设置序列号、ssrc、加扩展头等
- 记录NACK/FEC/retransmission等重发需要的信息
- 通过socket等底层去发包到RTP peer
- 网络ISend接口:最终出去
八、总结联系与区别
类/模块 | 作用 | 关注点 |
---|---|---|
RtpPacketToSend | 表示“即将要发出去的一个RTP包”+元数据 | 单个包内容、附加定时/扩展/关键帧信息 |
RTPSender | RTP发送行为管理,包头生成+包投递(基础) | 通用RTP包发送,序列号分配、socket发包等 |
RtpSenderVideo/Video | 视频专用的RTP发送(多帧分包、关键帧判断等) | 视频帧处理,分包,关键帧加标,带有额外定时/统计 |
关系:
RtpPacketToSend
是包容器,RtpSenderVideo
/RtpVideoSender
生成它们,交由RTPSender
发送!RtpSenderVideo
/RtpVideoSender
是“分发器/工厂”,RTPSender
是“投递员”
九、一句话定性:
- RtpPacketToSend = 发包元信息封装器
- RtpSenderVideo(或RtpVideoSender)= 视频分包器,专门为视频准备、生成RtpPacketToSend,喂给RTPSender
- RTPSender = 真正的RTP通道发送器,管理和输出RTP包,连接到底层socket。
用一句话总结发送流程:
“视频帧被切割为多个RtpPacketToSend,经由RtpVideoSender预处理后交由RTPSender完成最终的网络发送。”