webrtc源码走读(二)应用层如何使用WebRTC API实现功能

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. 通过系统接口层访问硬件设备
  2. 与核心引擎层交互,处理媒体流和网络连接
  3. 通过信令机制与其他端点交换连接信息

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层工作流程

  1. 应用层调用new RTCPeerConnection()
  2. API层调用PeerConnectionFactory::CreatePeerConnection()
  3. 工厂创建PeerConnection对象
  4. 初始化内部状态(包括ICE服务器配置)
  5. 返回封装的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层工作流程

  1. 应用层调用getUserMedia()
  2. API层调用MediaStreamInterface实现
  3. 调用底层C++ API获取媒体设备
  4. 返回媒体流对象

关键源码

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层工作流程

  1. 应用层调用createOffer()
  2. API层调用PeerConnection::CreateOffer()
  3. 内部调用CreateOfferInternal()生成SDP Offer
  4. 调用SetLocalDescriptionInternal()设置本地描述
  5. 通过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层工作流程

  1. 应用层监听onicecandidate事件
  2. API层在内部收集ICE候选
  3. 通过onicecandidate事件通知应用层
  4. 应用层将候选发送到信令服务器

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 候选者、房间控制指令等。

信令服务器用于交换以下关键信息:

  1. SDP (Session Description Protocol):会话描述信息,包含媒体格式、编解码器等
  2. ICE Candidates:网络地址信息,用于建立P2P连接 #### 3.3.2 信令服务器实现

信令机制的核心原理

WebRTC的信令机制是"桥梁",连接两个对等端。它不负责媒体传输,只负责交换建立连接所需的信息。信令机制包括以下关键步骤:

  1. 初始化:双方建立连接
  2. Offer/Answer:协商媒体能力
  3. ICE候选交换:确定网络路径
  4. 连接建立:P2P连接成功

信令模块的作用

  1. 会话协商:通过SDP交换,协商双方支持的媒体类型、编解码器、分辨率等参数
  2. 网络信息交换:交换ICE候选地址,用于NAT穿透和建立P2P连接
  3. 连接管理:管理连接状态,处理连接断开和重连
  4. 媒体流控制:控制媒体流的添加、删除和修改
  5. 错误处理:处理连接过程中的错误和异常情况

信令过程是建立RTCPeerConnection网络连接的关键部分,其主要目的是协调两个端点的通信参数并建立连接。

4.2. 关键源码文件及作用

信令模块的核心代码位于webrtc/pcwebrtc/api目录下,以下是关键文件及其作用:

4.2.1 peer_connection.hpeer_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.hsession_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.hice_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.hsignaling_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和answer
  • SendIceCandidate() 发送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信令模块将与边缘计算结合,实现更高效的信令处理:

  • 边缘信令服务器:在边缘节点部署信令服务器,减少延迟
  • 本地信令处理:在设备端进行部分信令处理,减少对中心服务器的依赖
  • 分布式信令网络:构建分布式信令网络,提高信令处理的可靠性和效率
相关推荐
草莓熊Lotso2 小时前
Qt 入门核心指南:从框架认知到环境搭建 + Qt Creator 实战
xml·开发语言·网络·c++·人工智能·qt·页面
weixin_425023002 小时前
Spring Boot 实现服务器全量信息监控(CPU/JVM/内存/磁盘)
服务器·jvm·spring boot
寂寞恋上夜2 小时前
边界条件检查清单:数据为空/超长/特殊字符/越界(附测试用例)
服务器·网络·测试用例·markdown转xmind·在线思维导图生成器
QT 小鲜肉2 小时前
【Linux命令大全】001.文件管理之rcp命令(实操篇)
linux·服务器·网络·chrome·笔记
老王熬夜敲代码2 小时前
模版元编程variant
c++·笔记
Psycho_MrZhang2 小时前
PythonGIL
服务器
Tipriest_2 小时前
Linux 下开发 C/C++ 程序为什么头文件引用路径这么多和复杂
linux·c语言·c++
翼龙云_cloud2 小时前
亚马逊云渠道商:AWS Lightsail 极速部署演示环境搭建指南
运维·服务器·云计算·aws
你好音视频2 小时前
FFmpeg HLS编码流程深度解析:从数据包到播放列表的完整实现
c++·ffmpeg·音视频