一、問題:
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
“怎么發、發給誰”是分開的。
六、大致的發包流程(類關系圖)
flowchart TDsubgraph 上層編碼器A[視頻幀] -->|EncodedImage| B(RtpVideoSender/RtpSenderVideo)endB -->|幀分包、添加RTP頭| C[RtpPacketToSend 1]B -->|幀分包、添加RTP頭| D[RtpPacketToSend 2]B -->|幀分包、添加RTP頭| E[RtpPacketToSend ...]C -->|SendPacket| F(RTPSender)D -->|SendPacket| FE -->|SendPacket| FF -->|網絡調度| G(PacingController)G -->|網絡發送| H[網絡socket]
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完成最終的網絡發送。”