# Call 对象 · 一次通话的媒体中枢

> PeerConnection 管控制面，Call 管媒体面——它是所有发送流/接收流的中枢，也是拥塞控制的宿主。这一章读 call/call.h：Call 怎么创建和管理 AudioSendStream/VideoReceiveStream，以及它为什么活在 worker 线程。

- 作者：David（道雾轩）
- 专栏：音视频与 WebRTC 详解（https://daiw.org/manual/webrtc.md）
- 最后更新：2026-07-14
- 原文：https://daiw.org/manual/webrtc/call-object
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# Call 对象 · 一次通话的媒体中枢

前八部分，我们从[会话协商](https://daiw.org/manual/webrtc/offer-answer-handler)一路走到[音视频数据的收发](https://daiw.org/manual/webrtc/sctp-streams-dcep)。第 9 部分退后一步，看**统管媒体面的中枢**——**`Call`**（`call/call.cc`）。[早在第 1 部分](https://daiw.org/manual/webrtc/peer-connection-object)它就作为 `PeerConnection` 的 `call_` 成员出现过，现在细看它。

## Call：媒体流的中枢

[`PeerConnection` 管控制面](https://daiw.org/manual/webrtc/peer-connection-object)（[SDP 协商](https://daiw.org/manual/webrtc/offer-answer-handler)、[ICE/DTLS](https://daiw.org/manual/webrtc/jsep-transport-controller)），而 **`Call` 管媒体面**——一次通话里**所有的发送流和接收流**，都由它创建和管理。看它的接口（`call/call.h`）：

```cpp
// call/call.h(节选)
class Call {
  virtual AudioSendStream* CreateAudioSendStream(...);
  virtual VideoSendStream* CreateVideoSendStream(...);
  virtual VideoReceiveStreamInterface* CreateVideoReceiveStream(...);
  // 以及 AudioReceiveStream、FlexfecReceiveStream 等
};
```

<Callout type="info">
  **`Call` 是“一次通话”在媒体层面的化身——它是所有[音视频流](https://daiw.org/manual/webrtc/audio-pipeline-overview)的**工厂 + 容器 + 协调者**。** [协商](https://daiw.org/manual/webrtc/offer-answer-handler)出要发一路视频、收一路音频，`PeerConnection` 就让 `Call` 创建对应的 [`VideoSendStream`](https://daiw.org/manual/webrtc/video-source-encoder)、[`AudioReceiveStream`](https://daiw.org/manual/webrtc/audio-pipeline-overview)。这些流由 `Call` 拥有、生命周期随通话。为什么要一个中枢来管、而不是各流自治？因为这些流**共享资源、需要协调**：

  - **共享带宽** —— 所有发送流[共用一个总带宽预算](https://daiw.org/manual/webrtc/rate-control)，要[统一分配](https://daiw.org/manual/webrtc/bitrate-allocator)（音频优先）。
  - **共享拥塞控制** —— [一套 GoogCC](https://daiw.org/manual/webrtc/congestion-control-overview) 服务所有流（而非每流一个）。
  - **共享传输** —— [BUNDLE 下所有流走一条传输](https://daiw.org/manual/webrtc/jsep-transport-controller)。

  `Call` 就是这个“协调共享资源”的中枢——它持有[拥塞控制的总控 `RtpTransportControllerSend`](https://daiw.org/manual/webrtc/rtp-transport-controller-send) 和[码率分配器 `BitrateAllocator`](https://daiw.org/manual/webrtc/bitrate-allocator)，让所有流在统一的资源框架下协作。
</Callout>

## Call 活在 worker 线程

呼应[第 1 部分](https://daiw.org/manual/webrtc/peer-connection-object)：`call_` 成员带着 `RTC_GUARDED_BY(worker_thread())`——**`Call` 及其媒体流活在 [worker 线程](https://daiw.org/manual/webrtc/threading-model)**。这符合[三线程分工](https://daiw.org/manual/webrtc/threading-model)：worker 线程管“媒体处理”，而 `Call` 正是媒体处理的中枢。[编解码、码率分配、拥塞控制](https://daiw.org/manual/webrtc/rate-control)这些计算，都在 worker 线程上跑；而[实际的包收发](https://daiw.org/manual/webrtc/rtp-sender)会派发到 [network 线程](https://daiw.org/manual/webrtc/threading-model)。[`PeerConnection` 的控制面在 signaling 线程](https://daiw.org/manual/webrtc/peer-connection-object)、`Call` 的媒体面在 worker 线程——两者通过[跨线程派发](https://daiw.org/manual/webrtc/proxy-pattern)协作。

## Call 持有什么

`Call` 是个“大管家”，它持有一次通话媒体面的关键部件：

| Call 持有 | 干什么 | 本教程 |
| --- | --- | --- |
| 各 SendStream / ReceiveStream | [音视频收发管线](https://daiw.org/manual/webrtc/video-pipeline-overview) | 第 6/7 部分 |
| `RtpTransportControllerSend` | [发送侧传输控制](https://daiw.org/manual/webrtc/rtp-transport-controller-send)（含[拥塞控制](https://daiw.org/manual/webrtc/congestion-control-overview)、[pacer](https://daiw.org/manual/webrtc/pacing)） | [下一章](https://daiw.org/manual/webrtc/rtp-transport-controller-send) |
| `BitrateAllocator` | [总码率在各流间分配](https://daiw.org/manual/webrtc/bitrate-allocator) | 第 9 部分 |

于是数据流是这样：[协商](https://daiw.org/manual/webrtc/offer-answer-handler) → `Call` 建流 → 流用[编解码器](https://daiw.org/manual/webrtc/video-encoder-abstraction)（[由媒体引擎](https://daiw.org/manual/webrtc/media-engine)提供）编解码 → [`RtpTransportControllerSend` 的拥塞控制 + pacer](https://daiw.org/manual/webrtc/rtp-transport-controller-send)调度发送 → [network 线程](https://daiw.org/manual/webrtc/threading-model)发包。`Call` 站在这一切的中心。

## 谁调用 Call

`Call` 不直接面对应用，而是被上层驱动：[`PeerConnection` 的各组件](https://daiw.org/manual/webrtc/peer-connection-object)（[channel](https://daiw.org/manual/webrtc/media-channels)、[transceiver](https://daiw.org/manual/webrtc/transceivers)）根据[协商结果](https://daiw.org/manual/webrtc/offer-answer-handler)，调 `Call` 建流、配流。可以说 `Call` 是[会话协商](https://daiw.org/manual/webrtc/offer-answer-handler)（“发什么、怎么发”）和[实际媒体管线](https://daiw.org/manual/webrtc/video-pipeline-overview)（“真的发”）之间的**执行层**——控制面谈定的东西，在 `Call` 这里变成真正跑起来的媒体流。

## 小结与下一章

**`Call`**（`call/call.cc`）是一次通话的**媒体中枢**——所有[音视频发送 / 接收流](https://daiw.org/manual/webrtc/audio-pipeline-overview)的**工厂 + 容器 + 协调者**（`CreateAudioSendStream` 等）。它统管的原因是这些流**共享带宽 / 拥塞控制 / 传输**，需要中枢协调——它持有[`RtpTransportControllerSend`](https://daiw.org/manual/webrtc/rtp-transport-controller-send)（拥塞控制 + [pacer](https://daiw.org/manual/webrtc/pacing)）和 [`BitrateAllocator`](https://daiw.org/manual/webrtc/bitrate-allocator)。`Call` 活在 [worker 线程](https://daiw.org/manual/webrtc/threading-model)（媒体处理），与 [signaling 线程的控制面](https://daiw.org/manual/webrtc/peer-connection-object)协作。它是[会话协商](https://daiw.org/manual/webrtc/offer-answer-handler)到[媒体管线](https://daiw.org/manual/webrtc/video-pipeline-overview)之间的执行层。

`Call` 持有的[拥塞控制总控 `RtpTransportControllerSend`](https://daiw.org/manual/webrtc/rtp-transport-controller-send) 是发送侧的神经中枢。下一章看它。👉 [RtpTransportControllerSend](https://daiw.org/manual/webrtc/rtp-transport-controller-send)。

## 参考资料

- [1] libwebrtc 源码.`call/call.h` / `call.cc`（`Call`、`CreateAudioSendStream` 等）。
- [2] libwebrtc 源码.`call/call_factory.cc`、`api/call/`。
- [3] 关联[PeerConnection 的 call_ 成员](https://daiw.org/manual/webrtc/peer-connection-object)、[线程模型](https://daiw.org/manual/webrtc/threading-model)。
