第 10 部分导论 · 引擎底下的地基 rtc_base
前九部分讲的是 WebRTC 的引擎,但引擎底下有一层到处都在用、却很少被单独讲的地基——rtc_base。这一章讲清它是什么、为什么 WebRTC 要自造一套基础库,以及第 10 部分要拆开看的那些「零件」。
第 10 部分导论 · 引擎底下的地基 rtc_base
前九部分讲完了 WebRTC 的核心引擎。但你一定注意到:一路读下来,总有些“零件”反复出现——scoped_refptr、Thread、Timestamp、RTC_GUARDED_BY……它们不属于任何一个子系统,却被所有子系统依赖。这层地基,就是 rtc_base(源码里的 rtc_base/ 目录)。第 10 部分,我们把它拆开看。
WebRTC 为什么自造一套基础库
一个自然的疑问:C++ 有标准库,为什么 WebRTC 还要自己造 Thread、Buffer、Mutex?
rtc_base 是 WebRTC 的“标准库”——一套跨平台、贴合实时通信需求的基础设施。它存在的原因是历史与现实的叠加:
- 历史比 std 早 —— WebRTC 起于 2011 年,那时 C++11 刚出、
std::thread/std::mutex还不成熟,跨平台支持参差。WebRTC 需要在 Windows / Linux / macOS / Android / iOS 上行为一致的线程、锁、socket,只能自己造。 - 要跑在千奇百怪的平台上 —— WebRTC 要嵌进浏览器、手机 App、嵌入式设备。
rtc_base把平台差异(Win 的CRITICAL_SECTION、POSIX 的pthread_mutex)封在底下,上层代码写一套。 - 实时通信的特殊需求 —— 通用库没有的东西:类型安全的时间 / 码率单位、零拷贝缓冲、滑动窗口测速率、编译期线程安全检查——这些是音视频引擎天天要用的,
rtc_base为它们量身打造。
所以 rtc_base 不是“重复造轮子”,而是“造 std 没有、或当年 std 造不好的轮子”。理解它,你才真正看懂上面九部分那些代码为什么长那样。
地基决定上层的形状
一个重要观念:地基的设计,反过来塑造了整个引擎的样子。
比如 Thread 其实是一个任务队列(Thread : public TaskQueueBase)——正因如此,WebRTC 的三线程模型才能用“往线程 PostTask”这种统一方式跨线程协作。又如 scoped_refptr + 引用计数是 WebRTC 对象生命周期的基石——正因如此,PeerConnection 等对象才用 scoped_refptr 传递、异步回调时不怕对象被提前销毁。上层的架构选择,往往是地基能力的直接后果。 所以第 10 部分不是“附录”,而是补上“为什么上层能那样写”的答案。
这一部分拆开看的零件
第 10 部分挑 rtc_base 里最核心、最常出现的几样,逐一拆解:
| 章 | 零件 | 上面哪里用到 |
|---|---|---|
| 线程与任务队列 | Thread/TaskQueueBase | 三线程模型、代理模式 |
| 引用计数 | scoped_refptr | 几乎所有对象 |
| 类型安全单位 | Timestamp/DataRate | 拥塞控制、时间戳 |
| 零拷贝缓冲 | CopyOnWriteBuffer | RTP 包在系统里流动 |
| 同步与线程注解 | Mutex/RTC_GUARDED_BY | 满眼的线程断言 |
| 速率统计 | RateStatistics | pacer、BWE、stats |
小结与下一章
rtc_base 是 WebRTC 的“标准库”——一套跨平台、贴合实时通信的地基,因历史早于成熟的 std、要跑在千奇百怪的平台、且有通用库没有的实时需求而存在。它被所有子系统依赖,且地基的设计反过来塑造了上层架构(Thread 是任务队列 → 三线程协作方式;引用计数 → 对象生命周期管理)。本部分拆解它最核心的零件。
先从最“底”的一样开始——线程与任务队列,它撑起了整个 WebRTC 的并发模型。👉 线程与任务队列。
参考资料
- [1] libwebrtc 源码.
rtc_base/目录总览、api/下的公共抽象。 - [2] 关联第 0 部分线程模型、代理模式、读源码指南。
- [3] WebRTC 官方
g3doc/(架构与基础库说明)。