WebRTC中的几个Channel
一、我指的是谁?
以视频为例,常见的有:MediaChannel
、VideoMediaChannel
、WebRtcVideoChannel
、BaseChannel
、VideoChannel
,那么,为什么要这么多Channel,只写一个叫做SuperChannel行不行(很多程序猿同胞都这么干,大而全,吃一个就饱了)??肯定是可以实现功能了,不过没有架构设计思想,以后扩展会很麻烦,并且会有很多重复代码。接下来一探究竟:
二、分层思想:
首先,我们WebRTC供用户调用的封装特别厉害,就是应用层了,典型的就是PeerConnection那一层,下面操作硬件或者系统的引擎层差异就比较大,因此,首先得把这几个Channel分成两层:
引擎层的:
MediaChannel、VideoMediaChannel、WebRtcVideoChannel
应用层的:
BaseChannel、VideoChannel
三、引擎层:
1. MediaChannel
-
定位:媒体通道的顶级抽象接口,定义所有媒体类型(音频、视频)的通用行为。
-
核心职责:
- 媒体流的基本控制(如启动 / 停止发送)。
- 编解码参数协商(如设置发送 / 接收参数)。
- 统计信息收集(如带宽使用、丢包率)。
-
关键接口:
class MediaChannel { public:virtual bool SetSendParameters(const SendParameters& params) = 0;virtual bool SetRecvParameters(const RecvParameters& params) = 0;virtual bool GetStats(MediaStats* stats) = 0;// ... };
2. VideoMediaChannel
-
定位:视频通道的专用抽象接口,继承自
MediaChannel
,扩展视频特有的功能。 -
核心职责:
- 视频编解码配置(如分辨率、帧率、编码格式)。
- 视频渲染控制(如设置渲染器、调整显示参数)。
- 视频质量增强(如生成关键帧、配置 FEC)。
-
关键接口 :
class VideoMediaChannel : public MediaChannel { public:virtual bool SetVideoSend(uint32_t ssrc, VideoSource* source) = 0;virtual bool SetSink(uint32_t ssrc, VideoSinkInterface* sink) = 0;virtual void GenerateKeyFrame(uint32_t ssrc) = 0;// ... };
3. WebRtcVideoChannel
-
定位:基于 WebRTC 原生库的视频通道具体实现,继承自
VideoMediaChannel
。 -
核心职责 :
- 将抽象接口映射到 WebRTC 原生 API(如
webrtc::VideoTrack
、RtpSender
)。 - 管理 WebRTC 组件的生命周期(如编码器、网络传输)。
- 将抽象接口映射到 WebRTC 原生 API(如
-
关键实现 :
class WebRtcVideoChannel : public VideoMediaChannel { public:bool SetVideoSend(uint32_t ssrc, VideoSource* source) override {// 创建 WebRTC 视频轨道video_track_ = factory_->CreateVideoTrack(ssrc, source);// 配置编码器return ConfigureEncoder(params);}bool SetSink(uint32_t ssrc, VideoSinkInterface* sink) override {// 将渲染器绑定到 WebRTC 轨道video_track_->AddOrUpdateSink(sink, rtc::VideoSinkWants());return true;}// ... };
四、应用层(业务封装与公共逻辑)
1. BaseChannel
- 定位:音视频通道的公共基类,封装媒体通道的实现细节(非接口)。
- 核心职责 :
- 网络传输管理(如 UDP/TCP 套接字配置)。
- 带宽估计与码率控制的公共逻辑。
- 错误处理与状态管理。
- 关键实现 :
class BaseChannel { protected:rtc::scoped_refptr<webrtc::Transport> transport_;BitrateAllocator bitrate_allocator_;bool SendPacket(const uint8_t* data, size_t length) {// 底层网络发送逻辑return transport_->SendRtp(data, length, options);}void OnNetworkQualityChanged(NetworkQuality quality) {// 网络质量变化时的通用处理逻辑bitrate_allocator_.UpdateEstimate(quality);} };
2. VideoChannel
-
定位:面向应用开发者的视频通道实现,继承自
BaseChannel
,并可能实现VideoMediaChannel
接口。 -
核心职责 :
- 提供易用的视频控制 API(如 StartVideo ()、StopVideo ())。
- 整合视频特有的业务逻辑(如双流策略、渲染优化)。
-
关键实现 :
class VideoChannel : public BaseChannel, public VideoMediaChannel { public:bool StartVideo() {// 组合多个操作:创建轨道、配置编码器、启动发送if (!CreateVideoTrack()) return false;if (!ConfigureEncoder()) return false;return StartSending();}bool SetSink(uint32_t ssrc, VideoSinkInterface* sink) override {// 调用 BaseChannel 的网络传输能力if (!BaseChannel::IsReady()) return false;// 设置渲染器return video_track_->AddOrUpdateSink(sink, rtc::VideoSinkWants());} };
五、分层协作模式
1. 接口继承关系
MediaChannel (抽象接口)↑│
VideoMediaChannel (视频专用接口)↑│
WebRtcVideoChannel (WebRTC 实现)
2. 实现继承关系
BaseChannel (公共实现基类)↑│
VideoChannel (视频业务实现,可能实现 VideoMediaChannel 接口)
3.典型协作流程:
四、设计价值与应用场景
1. 引擎层的接口抽象
-
价值:
- 支持多实现:可同时存在 WebRTC 实现、模拟实现或自定义实现。
- 便于测试:通过 Mock
VideoMediaChannel
接口,可独立测试上层业务逻辑。
-
应用场景 :
- 跨平台开发(如 Web、Android、iOS 共用同一套接口)。
- 单元测试与集成测试。
2. 应用层的公共基类
-
价值:
- 代码复用:避免在
VideoChannel
和AudioChannel
中重复实现网络传输、带宽控制等逻辑。 - 统一管理:集中处理错误、状态和资源释放。
- 代码复用:避免在
-
应用场景 :
- 同时支持音频和视频的应用(如视频会议系统)。
- 需统一网络策略的场景(如弱网环境下的自适应调整)。
3. 组合使用的优势
- 灵活性:
应用层可选择继承BaseChannel
复用公共逻辑,同时实现VideoMediaChannel
接口适配引擎层。 - 扩展性:
未来若需添加新的媒体类型(如屏幕共享),可继承BaseChannel
并实现MediaChannel
接口。