1、WebRTC 层级定位与核心功能
WebRTC为应用层提供了四个核心API,这些API是构建实时通信应用的基础:
| API | 功能 | 关键作用 | 浏览器兼容性 |
|---|---|---|---|
getUserMedia |
获取本地音视频流 | 访问摄像头、麦克风等硬件设备 | Chrome, Firefox, Edge, Safari |
RTCPeerConnection |
建立点对点连接 | 管理连接、交换媒体数据、处理ICE候选 | Chrome, Firefox, Edge, Safari |
RTCDataChannel |
传输任意数据 | 实现文本、文件等非媒体数据传输 | Chrome, Firefox, Edge |
getDisplayMedia |
获取屏幕共享流 | 实现屏幕共享功能 | Chrome, Firefox |
1.1 WebRTC API的层级定位
WebRTC API位于API层,是应用层与核心引擎层之间的桥梁。应用层通过调用这些API,无需了解底层实现细节,即可实现复杂的实时通信功能。
1.2 WebRTC API的工作原理
WebRTC API本质上是JavaScript接口,它封装了底层WebRTC核心引擎的功能。当应用层调用这些API时,WebRTC引擎会执行以下操作:
- 通过系统接口层访问硬件设备
- 与核心引擎层交互,处理媒体流和网络连接
- 通过信令机制与其他端点交换连接信息
1.3. API层的核心功能与作用
核心功能定位
| 功能 | 说明 | 重要性 |
|---|---|---|
| 标准化接口 | 提供统一的WebRTC API,使开发者无需关心底层实现 | ⭐⭐⭐⭐⭐ |
| 复杂性封装 | 将ICE候选收集、SDP协商、媒体处理等复杂逻辑封装 | ⭐⭐⭐⭐ |
| 生命周期管理 | 管理RTCPeerConnection等对象的创建、使用和销毁 | ⭐⭐⭐⭐ |
| 跨平台支持 | 确保不同浏览器提供一致的API体验 | ⭐⭐⭐ |
| 错误处理 | 提供标准化的错误处理机制 | ⭐⭐⭐ |
2、API层关键源码应用层开发的基本流程
WebRTC应用开发的完整流程可以概括为"获取媒体→建立连接→交换信令→处理媒体→数据传输"五个核心步骤:
应用层
│
├── 1. 获取本地媒体流 (getUserMedia)
│
├── 2. 创建RTCPeerConnection实例 (RTCPeerConnection)
│
├── 3. 信令交换 (SDP与ICE候选)
│ ├── 3.1 创建Offer
│ ├── 3.2 发送Offer给对方
│ ├── 3.3 接收Answer
│ └── 3.4 交换ICE候选
│
├── 4. 处理媒体流 (ontrack事件)
│
└── 5. 数据传输 (RTCDataChannel)
2.1 源码结构与目录组织
WebRTC源码中API层主要位于api/目录下:
api/
├── peerconnectioninterface.h
├── peerconnectionfactoryinterface.h
├── mediastreaminterface.h
├── datachannelinterface.h
├── sdp.h
├── ...
pc/
├── peerconnectioninterface.cc
├── peerconnectionfactory.cc
├── ...
2.2 关键源码文件解析
2.2.1 peerconnectioninterface.h - 核心接口
cpp
// api/peerconnectioninterface.h
// RTCPeerConnection的核心接口定义
class RTCPeerConnectionInterface {
public:
// 创建offer
virtual void CreateOffer(
CreateSessionDescriptionObserver* observer,
const RTCOfferOptions* options) = 0;
// 创建answer
virtual void CreateAnswer(
CreateSessionDescriptionObserver* observer,
const RTCOfferOptions* options) = 0;
// 设置远程描述
virtual void SetRemoteDescription(
SetSessionDescriptionObserver* observer,
const SessionDescriptionInterface* desc) = 0;
// 设置本地描述
virtual void SetLocalDescription(
SetSessionDescriptionObserver* observer,
const SessionDescriptionInterface* desc) = 0;
// 添加媒体轨道
virtual void AddTrack(
const rtc::scoped_refptr<MediaStreamTrackInterface>& track,
const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) = 0;
// 添加ICE候选
virtual void AddIceCandidate(
const IceCandidateInterface* candidate) = 0;
// 监听事件
virtual void OnTrack(
const rtc::scoped_refptr<TrackEvent>& event) = 0;
// 获取连接状态
virtual std::string iceConnectionState() const = 0;
virtual std::string connectionState() const = 0;
// ... 其他方法
};
- 该接口定义了WebRTC的核心功能,是API层的"心脏"
- 使用纯虚函数定义,由实现类具体实现
CreateSessionDescriptionObserver等接口用于处理异步操作- 所有方法都设计为异步,避免阻塞UI线程
2.2.2 peerconnectionfactoryinterface.h - 工厂接口
cpp
// api/peerconnectionfactoryinterface.h
// PeerConnectionFactory的接口定义
class PeerConnectionFactoryInterface {
public:
// 创建PeerConnection对象
virtual rtc::scoped_refptr<RTCPeerConnectionInterface> CreatePeerConnection(
const PeerConnectionInterface::Options& options,
const PeerConnectionInterface::RTCConfiguration& config,
const std::vector<rtc::scoped_refptr<PeerConnectionInterface::IceServer>>& ice_servers) = 0;
// 创建DataChannel
virtual rtc::scoped_refptr<RTCDataChannelInterface> CreateDataChannel(
const std::string& label,
const DataChannelInterface::Init& config) = 0;
// 创建MediaStream
virtual rtc::scoped_refptr<MediaStreamInterface> CreateLocalMediaStream(
const std::string& label) = 0;
// 创建MediaStreamTrack
virtual rtc::scoped_refptr<MediaStreamTrackInterface> CreateVideoTrack(
const std::string& id,
VideoTrackSourceInterface* source) = 0;
// ... 其他方法
};
- 工厂接口负责创建WebRTC核心对象
CreatePeerConnection是创建RTCPeerConnection的入口- 使用
scoped_refptr管理对象生命周期,避免内存泄漏 RTCConfiguration用于配置ICE服务器等连接参数
2.2.3 mediastreaminterface.h - 媒体流接口
cpp
// api/mediastreaminterface.h
// MediaStream API的核心接口
class MediaStreamInterface {
public:
// 获取媒体流ID
virtual std::string id() const = 0;
// 获取媒体轨道列表
virtual const std::vector<rtc::scoped_refptr<MediaStreamTrackInterface>>& GetAudioTracks() const = 0;
virtual const std::vector<rtc::scoped_refptr<MediaStreamTrackInterface>>& GetVideoTracks() const = 0;
// 添加媒体轨道
virtual void AddTrack(
const rtc::scoped_refptr<MediaStreamTrackInterface>& track) = 0;
// 移除媒体轨道
virtual void RemoveTrack(
const rtc::scoped_refptr<MediaStreamTrackInterface>& track) = 0;
};
// MediaStreamTrack的核心接口
class MediaStreamTrackInterface {
public:
// 获取轨道ID
virtual std::string id() const = 0;
// 获取轨道类型
virtual std::string kind() const = 0;
// 获取轨道状态
virtual std::string state() const = 0;
// 获取轨道的媒体源
virtual MediaStreamSourceInterface* GetSource() const = 0;
};
- 提供了媒体流和媒体轨道的标准接口
getUserMedia()API最终会调用这些接口MediaStreamTrack是媒体流的基本单元,可以是音频或视频
2.2.4 sdp.h - SDP处理接口
cpp
// api/sdp.h
// SDP处理核心接口
class SessionDescriptionInterface {
public:
// 获取SDP类型
virtual SdpType type() const = 0;
// 获取SDP内容
virtual std::string ToString() const = 0;
// 获取SDP的媒体描述
virtual const std::vector<MediaDescriptionInterface*>& GetMediaDescriptions() const = 0;
};
// SDP解析器接口
class SdpParseError {
public:
// 错误类型
enum Type {
kNoError,
kInvalidFormat,
kInvalidMLine,
kInvalidAttribute,
// ... 其他错误类型
};
};
// SDP解析器
class SdpParse {
public:
// 解析SDP字符串
static rtc::scoped_refptr<SessionDescriptionInterface> ParseSdp(
const std::string& sdp,
SdpParseError* error);
// 生成SDP字符串
static std::string GenerateSdp(
const SessionDescriptionInterface* desc);
};
- SDP(Session Description Protocol)是WebRTC信令交换的核心
SdpParse类负责SDP的解析和生成SessionDescriptionInterface是SDP的抽象表示
2.2.5 peerconnectioninterface.cc - 实现层
cpp
// pc/peerconnectioninterface.cc
// RTCPeerConnection的实现
class PeerConnection : public RTCPeerConnectionInterface {
public:
PeerConnection(
const PeerConnectionInterface::Options& options,
const PeerConnectionInterface::RTCConfiguration& config,
const std::vector<rtc::scoped_refptr<IceServer>>& ice_servers) {
// 初始化内部状态
Initialize(options, config, ice_servers);
}
// 创建offer
void CreateOffer(
CreateSessionDescriptionObserver* observer,
const RTCOfferOptions* options) override {
// 1. 创建SDP Offer
SessionDescriptionInterface* offer = CreateOfferInternal(options);
// 2. 设置本地描述
if (offer) {
SetLocalDescriptionInternal(offer);
}
// 3. 通过Observer返回结果
if (observer) {
observer->OnSuccess(offer);
}
}
// 设置本地描述
void SetLocalDescription(
SetSessionDescriptionObserver* observer,
const SessionDescriptionInterface* desc) override {
// 1. 更新本地描述状态
local_desc_ = desc;
// 2. 生成ICE候选
GenerateIceCandidates();
// 3. 通知核心引擎
core_engine_->SetLocalDescription(desc);
// 4. 通过Observer通知应用层
if (observer) {
observer->OnSuccess();
}
}
// 添加ICE候选
void AddIceCandidate(const IceCandidateInterface* candidate) override {
// 1. 添加候选到内部列表
ice_candidates_.push_back(candidate);
// 2. 通知核心引擎
core_engine_->AddIceCandidate(candidate);
}
// ... 其他方法实现
private:
// 内部状态
SessionDescriptionInterface* local_desc_ = nullptr;
SessionDescriptionInterface* remote_desc_ = nullptr;
std::vector<rtc::scoped_refptr<IceCandidateInterface>> ice_candidates_;
// 核心引擎实例
std::unique_ptr<CoreEngine> core_engine_;
// 初始化内部状态
void Initialize(
const PeerConnectionInterface::Options& options,
const PeerConnectionInterface::RTCConfiguration& config,
const std::vector<rtc::scoped_refptr<IceServer>>& ice_servers) {
// 1. 创建核心引擎
core_engine_ = std::make_unique<CoreEngine>(config, ice_servers);
// 2. 设置内部状态
// ...
}
};
PeerConnection类实现了RTCPeerConnectionInterface接口- 所有API方法都调用内部
core_engine_进行实际操作 - 使用
scoped_refptr管理对象生命周期 - 通过
Observer模式处理异步操作
2.2.6 peerconnectionfactory.cc - 工厂实现
cpp
// pc/peerconnectionfactory.cc
// PeerConnectionFactory的实现
class PeerConnectionFactory : public PeerConnectionFactoryInterface {
public:
// 创建PeerConnection
rtc::scoped_refptr<RTCPeerConnectionInterface> CreatePeerConnection(
const PeerConnectionInterface::Options& options,
const PeerConnectionInterface::RTCConfiguration& config,
const std::vector<rtc::scoped_refptr<PeerConnectionInterface::IceServer>>& ice_servers) override {
// 1. 创建PeerConnection对象
PeerConnection* pc = new PeerConnection(options, config, ice_servers);
// 2. 初始化内部状态
pc->Initialize();
// 3. 返回封装对象
return rtc::scoped_refptr<RTCPeerConnectionInterface>(pc);
}
// 创建DataChannel
rtc::scoped_refptr<RTCDataChannelInterface> CreateDataChannel(
const std::string& label,
const DataChannelInterface::Init& config) override {
// 实现DataChannel创建逻辑
// ...
}
// ... 其他方法实现
};
- 工厂方法负责创建和初始化PeerConnection对象
- 使用
scoped_refptr确保对象生命周期安全 - 实现了
PeerConnectionFactoryInterface接口
3. API层工作流程详解
3.1 API层交互流程
核心引擎层 (C++) API层 (WebRTC API) 应用层 (JavaScript) 核心引擎层 (C++) API层 (WebRTC API) 应用层 (JavaScript) 1. new RTCPeerConnection() 2. 调用PeerConnectionFactory::CreatePeerConnection() 3. 创建PeerConnection对象 4. 返回PeerConnection实例 5. 返回RTCPeerConnection实例 6. getUserMedia() 7. 调用MediaStreamInterface实现 8. 获取媒体设备 9. 返回媒体流 10. 返回MediaStream对象 11. createOffer() 12. 调用PeerConnection::CreateOffer() 13. 生成SDP Offer 14. 返回SDP Offer 15. 返回Offer SDP 16. setLocalDescription() 17. 调用PeerConnection::SetLocalDescription() 18. 更新连接状态 19. 确认设置 20. 确认设置 21. addTrack() 22. 调用PeerConnection::AddTrack() 23. 添加媒体轨道 24. 确认添加 25. 确认添加 26. onicecandidate事件处理 27. 监听ICE候选 28. 收集ICE候选 29. 触发onicecandidate事件
3.2 详细工作流程
3.2.1 创建RTCPeerConnection
JavaScript应用层代码:
javascript
const pc = new RTCPeerConnection({
iceServers: [{urls: "stun:stun.l.google.com:19302"}]
});
API层工作流程:
- 应用层调用
new RTCPeerConnection() - API层调用
PeerConnectionFactory::CreatePeerConnection() - 工厂创建
PeerConnection对象 - 初始化内部状态(包括ICE服务器配置)
- 返回封装的
RTCPeerConnectionInterface对象
Core API Application Core API Application new RTCPeerConnection() 创建PeerConnectionFactory CreatePeerConnection() 初始化PeerConnection对象 返回PeerConnection对象 返回RTCPeerConnection实例
关键源码:
cpp
// pc/peerconnectionfactory.cc
rtc::scoped_refptr<RTCPeerConnectionInterface> PeerConnectionFactory::CreatePeerConnection(
const PeerConnectionInterface::Options& options,
const PeerConnectionInterface::RTCConfiguration& config,
const std::vector<rtc::scoped_refptr<PeerConnectionInterface::IceServer>>& ice_servers) {
// 创建PeerConnection对象
PeerConnection* pc = new PeerConnection(options, config, ice_servers);
// 初始化内部状态
pc->Initialize();
// 返回封装对象
return rtc::scoped_refptr<RTCPeerConnectionInterface>(pc);
}
3.2.2 获取媒体流
JavaScript应用层代码:
javascript
const stream = await navigator.mediaDevices.getUserMedia({video: true, audio: true});
API层工作流程:
- 应用层调用
getUserMedia() - API层调用
MediaStreamInterface实现 - 调用底层C++ API获取媒体设备
- 返回媒体流对象
关键源码:
cpp
// api/mediastreaminterface.h
class MediaStreamInterface {
public:
static rtc::scoped_refptr<MediaStreamInterface> CreateLocalMediaStream(
const std::string& label);
};
// 实现部分
rtc::scoped_refptr<MediaStreamInterface> MediaStreamInterface::CreateLocalMediaStream(
const std::string& label) {
// 调用底层API创建媒体流
return CreateLocalMediaStreamInternal(label);
}
3.2.3 SDP协商过程
JavaScript应用层代码:
javascript
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// 通过信令服务器发送offer
signalingServer.send({type: "offer", sdp: offer.sdp});
API层工作流程:
- 应用层调用
createOffer() - API层调用
PeerConnection::CreateOffer() - 内部调用
CreateOfferInternal()生成SDP Offer - 调用
SetLocalDescriptionInternal()设置本地描述 - 通过Observer返回结果
Core API Application Core API Application createOffer() CreateOffer() 生成SDP Offer 返回SDP Offer 返回Offer setLocalDescription() SetLocalDescription() 更新连接状态 确认设置 确认设置
关键源码:
cpp
// pc/peerconnectioninterface.cc
void PeerConnection::CreateOffer(
CreateSessionDescriptionObserver* observer,
const RTCOfferOptions* options) {
// 1. 创建SDP Offer
SessionDescriptionInterface* offer = CreateOfferInternal(options);
// 2. 设置本地描述
if (offer) {
SetLocalDescriptionInternal(offer);
}
// 3. 通过Observer返回结果
if (observer) {
observer->OnSuccess(offer);
}
}
SessionDescriptionInterface* PeerConnection::CreateOfferInternal(
const RTCOfferOptions* options) {
// 实际SDP生成逻辑
// 1. 获取当前媒体配置
// 2. 生成SDP Offer
// 3. 返回SessionDescriptionInterface
return new SessionDescription(offer_sdp);
}
void PeerConnection::SetLocalDescriptionInternal(
SessionDescriptionInterface* desc) {
// 1. 更新本地描述状态
local_desc_ = desc;
// 2. 生成ICE候选
GenerateIceCandidates();
// 3. 通知核心引擎
core_engine_->SetLocalDescription(desc);
}
3.2.4 ICE候选交换
JavaScript应用层代码:
javascript
pc.onicecandidate = event => {
if (event.candidate) {
signalingServer.send({type: "candidate", candidate: event.candidate});
}
};
API层工作流程:
- 应用层监听
onicecandidate事件 - API层在内部收集ICE候选
- 通过
onicecandidate事件通知应用层 - 应用层将候选发送到信令服务器
Core API Application Core API Application onicecandidate事件监听 监听ICE候选 收集ICE候选 触发onicecandidate事件 触发onicecandidate事件 发送ICE候选 通过信令服务器发送候选 接收ICE候选 AddIceCandidate() 添加候选
关键源码:
cpp
// pc/peerconnectioninterface.cc
void PeerConnection::GenerateIceCandidates() {
// 1. 通过核心引擎收集候选
std::vector<IceCandidateInterface*> candidates;
core_engine_->GetIceCandidates(&candidates);
// 2. 通知应用层
for (auto& candidate : candidates) {
OnIceCandidate(candidate);
}
}
void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) {
// 触发onicecandidate事件
if (ice_candidate_observer_) {
ice_candidate_observer_->OnIceCandidate(candidate);
}
}
4、信令机制
4.1、信令机制的核心作用与原理
信令模块是WebRTC核心引擎层的关键组成部分,负责处理WebRTC会话的建立、协商和管理。信令模块的主要作用是交换SDP(Session Description Protocol)描述和ICE候选地址,以建立P2P连接。
WebRTC本身不提供信令机制 ,需要开发者实现自己的信令服务器。 虽然WebRTC核心源码本身不包含完整的信令服务器实现,但这是设计层面的刻意选择,而非功能缺失:
-
核心原因 :WebRTC 标准只定义了「实时媒体传输」的核心逻辑(如 ICE/NAT 穿透、DTLS/SRTP 加密、媒体编解码),但信令协议是完全开放的(可以用 WebSocket/HTTP/GRPC 等任意协议),因此 Google 没有在核心库中固化某一种信令实现。
-
源码中的相关部分:
WebRTC 源码提供了信令交互所需的「数据结构和接口」(如 SDP 解析、ICE 候选者交换的结构体),但不会实现信令的收发、转发逻辑。 - 官方的示例代码(如
src/examples/下的peerconnection_server)包含一个极简的 C++ 信令服务器 demo(基于 HTTP+WebSocket),仅用于演示,并非生产级实现。
实际开发:信令服务器需要开发者自行实现(或使用开源方案如 Janus/Mediasoup/OpenVidu),核心职责是转发 SDP、ICE 候选者、房间控制指令等。
信令服务器用于交换以下关键信息:
- SDP (Session Description Protocol):会话描述信息,包含媒体格式、编解码器等
- ICE Candidates:网络地址信息,用于建立P2P连接 #### 3.3.2 信令服务器实现
信令机制的核心原理
WebRTC的信令机制是"桥梁",连接两个对等端。它不负责媒体传输,只负责交换建立连接所需的信息。信令机制包括以下关键步骤:
- 初始化:双方建立连接
- Offer/Answer:协商媒体能力
- ICE候选交换:确定网络路径
- 连接建立:P2P连接成功
信令模块的作用:
- 会话协商:通过SDP交换,协商双方支持的媒体类型、编解码器、分辨率等参数
- 网络信息交换:交换ICE候选地址,用于NAT穿透和建立P2P连接
- 连接管理:管理连接状态,处理连接断开和重连
- 媒体流控制:控制媒体流的添加、删除和修改
- 错误处理:处理连接过程中的错误和异常情况
信令过程是建立RTCPeerConnection网络连接的关键部分,其主要目的是协调两个端点的通信参数并建立连接。
4.2. 关键源码文件及作用
信令模块的核心代码位于webrtc/pc和webrtc/api目录下,以下是关键文件及其作用:
4.2.1 peer_connection.h 和 peer_connection_impl.h
cpp
// webrtc/pc/peer_connection.h
// RTCPeerConnection的接口类
class RTCPeerConnection {
public:
// 创建RTCPeerConnection实例
static std::unique_ptr<RTCPeerConnection> Create(
const PeerConnectionInterface::Options& options);
// 创建offer
virtual void CreateOffer(
CreateSessionDescriptionObserver* observer,
const RTCOfferAnswerOptions* options = nullptr) = 0;
// 创建answer
virtual void CreateAnswer(
CreateSessionDescriptionObserver* observer,
const RTCOfferAnswerOptions* options = nullptr) = 0;
// 设置本地描述
virtual void SetLocalDescription(
SetSessionDescriptionObserver* observer,
SessionDescriptionInterface* desc) = 0;
// 设置远程描述
virtual void SetRemoteDescription(
SetSessionDescriptionObserver* observer,
SessionDescriptionInterface* desc) = 0;
// 添加ICE候选
virtual void AddIceCandidate(
const IceCandidateInterface* candidate) = 0;
// 获取ICE候选
virtual void GetIceCandidates(
std::vector<IceCandidateInterface*>* candidates) = 0;
// 监听ICE连接状态变化
virtual void OnIceConnectionStateChange(
IceConnectionState state) = 0;
};
作用:定义RTCPeerConnection接口,实现信令交互的核心功能,包括创建offer/answer、设置本地/远程描述、添加ICE候选等。
4.2.2 session_description.h 和 session_description_impl.h
cpp
// webrtc/pc/session_description.h
// SDP会话描述的接口类
class SessionDescriptionInterface {
public:
// 获取会话描述类型
virtual SessionDescriptionType type() const = 0;
// 获取会话描述内容
virtual const std::string& ToString() const = 0;
// 获取会话描述的媒体信息
virtual const std::vector<MediaContentDescriptionInterface*>&
contents() const = 0;
};
作用:定义SDP会话描述的接口,用于表示offer和answer的媒体信息,包括编解码器、分辨率、带宽等参数。
4.2.3 ice_candidate.h 和 ice_candidate_impl.h
cpp
// webrtc/pc/ice_candidate.h
// ICE候选的接口类
class IceCandidateInterface {
public:
// 获取候选地址
virtual const std::string& candidate() const = 0;
// 获取候选的sdpMid
virtual const std::string& sdp_mid() const = 0;
// 获取候选的sdpMLineIndex
virtual int sdp_mline_index() const = 0;
};
作用:定义ICE候选的接口,用于表示NAT穿透过程中收集的候选地址,包括Host候选、Server Reflexive候选和Relay候选。
4.2.4 signaling_channel.h 和 signaling_channel_impl.h
cpp
// webrtc/pc/signaling_channel.h
// 信令通道的接口类
class SignalingChannel {
public:
virtual ~SignalingChannel() {}
// 发送SDP offer
virtual void SendOffer(const SessionDescriptionInterface* offer) = 0;
// 发送SDP answer
virtual void SendAnswer(const SessionDescriptionInterface* answer) = 0;
// 发送本地描述
virtual void SendLocalDescription(
const SessionDescriptionInterface* desc) = 0;
// 发送ICE候选
virtual void SendIceCandidate(const IceCandidateInterface* candidate) = 0;
// 设置信令消息处理回调
virtual void SetMessageHandler(
std::function<void(const SignalingMessage&)> handler) = 0;
};
作用:定义信令通道的接口,用于实现具体的信令传输方式(如WebSocket、MQTT等),将SDP和ICE候选通过信令服务器发送给对端。
4.3. 与其他模块的交互
4.3.1 与传输模块的交互
核心引擎层 传输模块 信令模块 核心引擎层 传输模块 信令模块 创建RTCPeerConnection 初始化传输模块 创建RTP/RTCP实例 初始化ICE 返回ICE候选 收集ICE候选 交换ICE候选 设置ICE候选 建立P2P连接 连接建立成功 返回连接状态
交互细节:
- 信令模块创建RTCPeerConnection实例
- 传输模块初始化RTP/RTCP和ICE
- 传输模块收集ICE候选并返回给信令模块
- 信令模块将ICE候选通过信令服务器交换给对方
- 信令模块设置对方的ICE候选给传输模块
- 传输模块建立P2P连接
4.3.2 与媒体引擎的交互
核心引擎层 媒体引擎 信令模块 核心引擎层 媒体引擎 信令模块 创建RTCPeerConnection 初始化媒体引擎 采集媒体流 返回媒体流 返回媒体流 生成SDP offer 通过信令服务器交换SDP 设置远程描述 通过远程描述配置媒体引擎 接收并处理媒体流
交互细节:
- 信令模块创建RTCPeerConnection实例
- 媒体引擎初始化并采集媒体流
- 信令模块生成SDP offer并交换
- 信令模块设置远程描述
- 媒体引擎根据远程描述配置媒体处理
4.4. 源码示例
4.4.1 RTCPeerConnection实现
cpp
// webrtc/pc/peer_connection_impl.cc
// RTCPeerConnection实现类
class RTCPeerConnectionImpl : public RTCPeerConnection {
public:
RTCPeerConnectionImpl(const PeerConnectionInterface::Options& options)
: options_(options),
signaling_thread_(nullptr),
transport_(nullptr),
media_engine_(nullptr) {
// 1. 初始化信令线程
signaling_thread_ = new rtc::Thread("SignalingThread");
signaling_thread_->Start();
// 2. 初始化传输模块
transport_ = new Transport();
transport_->Init();
// 3. 初始化媒体引擎
media_engine_ = new MediaEngine();
media_engine_->Init();
}
void CreateOffer(CreateSessionDescriptionObserver* observer,
const RTCOfferAnswerOptions* options) override {
// 1. 生成SDP offer
SessionDescriptionInterface* offer = media_engine_->CreateOffer(options);
// 2. 保存offer
local_description_ = offer;
// 3. 通过信令通道发送offer
if (signaling_channel_) {
signaling_channel_->SendOffer(offer);
}
// 4. 通知观察者
observer->OnSuccess(offer);
}
void CreateAnswer(CreateSessionDescriptionObserver* observer,
const RTCOfferAnswerOptions* options) override {
// 1. 生成SDP answer
SessionDescriptionInterface* answer = media_engine_->CreateAnswer(options);
// 2. 保存answer
local_description_ = answer;
// 3. 通过信令通道发送answer
if (signaling_channel_) {
signaling_channel_->SendAnswer(answer);
}
// 4. 通知观察者
observer->OnSuccess(answer);
}
void SetLocalDescription(SetSessionDescriptionObserver* observer,
SessionDescriptionInterface* desc) override {
// 1. 设置本地描述
local_description_ = desc;
// 2. 通过信令通道发送本地描述
if (signaling_channel_) {
signaling_channel_->SendLocalDescription(desc);
}
// 3. 通知观察者
observer->OnSuccess();
}
void SetRemoteDescription(SetSessionDescriptionObserver* observer,
SessionDescriptionInterface* desc) override {
// 1. 设置远程描述
remote_description_ = desc;
// 2. 通过媒体引擎配置媒体
media_engine_->SetRemoteDescription(desc);
// 3. 通过传输模块配置ICE
transport_->SetRemoteDescription(desc);
// 4. 通知观察者
observer->OnSuccess();
}
void AddIceCandidate(const IceCandidateInterface* candidate) override {
// 1. 添加ICE候选
ice_candidates_.push_back(candidate);
// 2. 通过信令通道发送ICE候选
if (signaling_channel_) {
signaling_channel_->SendIceCandidate(candidate);
}
}
void OnIceConnectionStateChange(IceConnectionState state) override {
// 1. 处理ICE连接状态变化
ice_connection_state_ = state;
// 2. 通知观察者
if (ice_connection_state_observer_) {
ice_connection_state_observer_->OnIceConnectionStateChange(state);
}
}
private:
PeerConnectionInterface::Options options_;
rtc::Thread* signaling_thread_;
Transport* transport_;
MediaEngine* media_engine_;
SessionDescriptionInterface* local_description_;
SessionDescriptionInterface* remote_description_;
std::vector<IceCandidateInterface*> ice_candidates_;
IceConnectionState ice_connection_state_;
IceConnectionStateObserver* ice_connection_state_observer_;
SignalingChannel* signaling_channel_;
};
RTCPeerConnectionImpl是RTCPeerConnection的实现类- 通过组合模式管理传输模块、媒体引擎和信令通道
CreateOffer()和CreateAnswer()生成SDP描述SetLocalDescription()和SetRemoteDescription()设置本地和远程描述AddIceCandidate()添加ICE候选OnIceConnectionStateChange()处理ICE连接状态变化
4.4.2 信令通道实现
cpp
// webrtc/pc/signaling_channel_impl.h
// WebSocket信令通道实现
class WebSocketSignalingChannel : public SignalingChannel {
public:
WebSocketSignalingChannel(const std::string& url)
: url_(url),
socket_(nullptr) {
// 初始化WebSocket连接
Connect();
}
void SendOffer(const SessionDescriptionInterface* offer) override {
// 1. 创建SDP offer消息
SignalingMessage message;
message.type = "sdp_offer";
message.data = offer->ToString();
// 2. 通过WebSocket发送消息
Send(message);
}
void SendAnswer(const SessionDescriptionInterface* answer) override {
// 1. 创建SDP answer消息
SignalingMessage message;
message.type = "sdp_answer";
message.data = answer->ToString();
// 2. 通过WebSocket发送消息
Send(message);
}
void SendLocalDescription(
const SessionDescriptionInterface* desc) override {
// 1. 创建本地描述消息
SignalingMessage message;
message.type = "sdp_local";
message.data = desc->ToString();
// 2. 通过WebSocket发送消息
Send(message);
}
void SendIceCandidate(const IceCandidateInterface* candidate) override {
// 1. 创建ICE候选消息
SignalingMessage message;
message.type = "ice_candidate";
message.data = candidate->candidate();
message.sdp_mid = candidate->sdp_mid();
message.sdp_mline_index = candidate->sdp_mline_index();
// 2. 通过WebSocket发送消息
Send(message);
}
void SetMessageHandler(
std::function<void(const SignalingMessage&)> handler) override {
message_handler_ = handler;
}
private:
void Connect() {
// 1. 创建WebSocket连接
socket_ = new WebSocket(url_);
// 2. 设置消息处理
socket_->SetMessageHandler(
[this](const std::string& message) {
SignalingMessage msg;
// 解析JSON消息
ParseMessage(message, &msg);
// 调用消息处理回调
if (message_handler_) {
message_handler_(msg);
}
});
}
void Send(const SignalingMessage& message) {
// 1. 序列化消息
std::string json = SerializeMessage(message);
// 2. 通过WebSocket发送消息
socket_->Send(json);
}
std::string url_;
WebSocket* socket_;
std::function<void(const SignalingMessage&)> message_handler_;
};
SignalingChannel是信令通道的接口类WebSocketSignalingChannel是WebSocket信令通道的实现类SendOffer()和SendAnswer()发送SDP offer和answerSendIceCandidate()发送ICE候选SetMessageHandler()设置消息处理回调- 信令通道负责将SDP和ICE候选通过WebSocket发送给对端
4.5. 信令模块工作时序
媒体引擎 传输模块 信令模块 信令服务器 参与者B 参与者A 媒体引擎 传输模块 信令模块 信令服务器 参与者B 参与者A 创建RTCPeerConnection 采集媒体流 CreateOffer 生成SDP offer 发送SDP offer 转发SDP offer 创建RTCPeerConnection 采集媒体流 CreateAnswer 生成SDP answer 发送SDP answer 转发SDP answer SetRemoteDescription 配置媒体引擎 AddIceCandidate 收集ICE候选 通过STUN获取公网IP 返回ICE候选 发送ICE候选 转发ICE候选 AddIceCandidate 设置ICE候选 尝试建立P2P连接 连接成功 通知连接状态 通知连接状态 接收媒体流 接收媒体流
4.6. 信令模块核心流程
参与者A
创建RTCPeerConnection
采集媒体流
生成SDP offer
通过信令服务器发送offer
参与者B接收offer
生成SDP answer
通过信令服务器发送answer
参与者A接收answer
设置远程描述
配置媒体引擎
收集ICE候选
通过STUN获取公网IP
发送ICE候选
参与者B接收ICE候选
设置ICE候选
尝试建立P2P连接
连接成功
传输媒体流
4.7. 信令模块的关键技术
4.7.1 SDP(Session Description Protocol)
SDP是WebRTC信令的核心,用于描述媒体会话的参数,包括:
- 会话名称
- 会话时间
- 媒体类型(音频、视频)
- 编解码器
- 分辨率
- 带宽
- ICE候选地址
SDP格式示例:
v=0
o=- 123456 1 IN IP4 127.0.0.1
s=-
t=0 0
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104
c=IN IP4 192.168.1.100
a=rtcp:9 IN IP4 192.168.1.100
a=rtpmap:111 opus/48000/2
a=fmtp:111 minptime=10;useinbandfec=1
a=sendrecv
4.7.2 ICE候选交换
ICE候选是NAT穿透的关键,包括:
- Host Candidate:本地网络地址
- Server Reflexive Candidate:NAT反射地址
- Relay Candidate:TURN中继地址
ICE候选格式示例:
candidate:1 1 udp 2130706431 192.168.1.100 54321 typ host
candidate:2 1 udp 1686052607 203.0.113.1 54321 typ srflx raddr 192.168.1.100 rport 54321
candidate:3 1 udp 1500000000 198.51.100.1 54321 typ relay raddr 192.168.1.100 rport 54321
4.7.3 信令协议
WebRTC没有定义具体的信令协议,开发者可以使用各种方式,如:
- WebSocket
- XMPP
- SIP
- HTTP
- MQTT
信令消息格式示例:
json
{
"type": "sdp_offer",
"data": "v=0\r\no=- 123456 1 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111 103 104\r\nc=IN IP4 192.168.1.100\r\na=rtcp:9 IN IP4 192.168.1.100\r\na=rtpmap:111 opus/48000/2\r\na=fmtp:111 minptime=10;useinbandfec=1\r\na=sendrecv\r\n"
}
4.8. 信令模块的异常处理
4.8.1 连接失败处理
cpp
// 信令模块异常处理示例
pc->oniceconnectionstatechange = [this]() {
if (pc->iceconnectionstate() == "disconnected") {
// 1. 重新发起ICE协商
restartIce();
}
};
void restartIce() {
// 2. 创建新的offer
auto offer = pc->createoffer();
pc->setlocaldescription(offer);
// 3. 通过信令服务器发送新offer
signaling_channel_->sendoffer(offer);
}
关键点:
- 监听ICE连接状态变化
- 当连接断开时,重新发起ICE协商
- 创建新的offer并发送给对端
4.8.2 媒体流中断处理
cpp
// 信令模块媒体流中断处理
pc->addeventlistener("negotiationneeded", [this]() {
// 1. 获取传输通道
auto transceiver = pc->gettransceivers()[0];
// 2. 优先使用VP9编解码器
transceiver->setcodecpreferences(filtercodecs("vp9"));
});
关键点:
- 监听negotiationneeded事件
- 当媒体流中断时,切换编解码器
- 优先使用高效的编解码器如VP9
4.9. 信令模块的未来发展方向
更高效的信令协议
WebRTC信令模块将采用更高效的信令协议:
- MQTT:轻量级消息传输协议,适合低带宽环境
- QUIC:基于UDP的多路复用传输协议,减少连接建立时间
- WebTransport:基于Web标准的传输协议,支持更丰富的信令功能
AI增强的信令处理
WebRTC信令模块将集成AI技术,实现更智能的信令处理:
- AI信令优化:使用AI算法优化信令消息的发送和处理
- AI连接预测:使用AI算法预测连接状态,提前进行优化
- AI异常检测:使用AI算法检测连接异常,自动进行处理
信令与边缘计算结合
WebRTC信令模块将与边缘计算结合,实现更高效的信令处理:
- 边缘信令服务器:在边缘节点部署信令服务器,减少延迟
- 本地信令处理:在设备端进行部分信令处理,减少对中心服务器的依赖
- 分布式信令网络:构建分布式信令网络,提高信令处理的可靠性和效率