前言
WebRTC 作为一个实时音视频通信系统,包含了信令控制、音视频传输、音视频采集、音视频编码、音视频解码、音视频渲染等所有功能。由于其功能多样性,注定了系统结构的复杂性,再加上音视频需要做很多编码前后的处理,算法非常复杂,逻辑结构也复杂。为了在复杂网络环境下,保证音视频通信的流畅性,WebRTC 还做了很多流控、带宽预测、拥塞控制算法。
为此,为了降低系统的复杂性,提高系统的运行效率,WebRTC 设计了一套多线程框架,并且做了精心的设计。下来我们就分析一下 WebRTC 中的线程模型。
线程结构图
WebRTC 的线程模型相对复杂一些,哪些模块要在哪些线程下运行,都是有规定的。要想更好的理解 WebRTC 的实现,分析 WebRTC 的线程框架是必不可少的。线程框架结构图如下:
![WebRTC架构分析]WebRTC 的线程模型_第1张图片](http://img.e-com-net.com/image/info8/57497056b9af480ebd58a4ad29f2ec4d.jpg)
图中每一个矩形框都代表了一个线程,我们这里列出了 11 个线程,当然这些是最主要的线程。线程之间的通信要么是通过图中标出的 Packet 队列,要么是通过 WebRTC 的 MessageQueue 来实现的。图中蓝色的线和橘色的线分别标出了数据包输出和输入时,在各个线程流向情况。
图中标出的信令线程、工作线程、网络线程,WebRTC 是允许定制的。
下来,我们就详细说明一下每一个线程的功能,以及具体代码实现位置。
线程功能说明
- 信令线程(Signal Thread)
一般是工作在 PeerConnection 层,主要是完成控制平面的逻辑,用于和应用层交互。比如,CreateOffer,SetRemoteSession 等接口都是通过 Signal threa 完成的。默认是采用 PeerConnectionFactory 初始化线程作为信令线程。
- 工作线程(Worker Thread)
主要是工作在媒体引擎层(media engine),具体工作如下:
- 音频设备初始化
- 视频设备初始化
- 流对象的初始化
- 从网络线程接收数据,传给解码器线程
- 从编码器线程接收数据,传给网络线程
- 网络线程(Network thread )
主要是工作在传输(transport)层,具体工作如下:
- Transport 的初始化
- 从网络接收数据,发送给 Worker thread
- 从 Worker thread 接收数据,发送到网络
- 视频采集线程
主要工作是完成视频原始数据的采集。在 Windows 上,这个线程是由directshow 提供。视频数据接收函数是 CaptureInputPin::Receive,实现文件是 http://sink_filter_ds.cc。
- 视频编码线程
主要工作是对视频的原始数据进行编码,从 Capture 接收 VideoFrame,然后调用编码器执行编码逻辑,将编码后的视频数据发送到 PacerSender。视频编码线程是通过 TaskQueue 实现的,线程名称是 EncodeThread。具体实现位置是 VideoStreamEncoder::TaskQueue,文件名是 video/video_stream_encoder.h。
- 视频解码线程
主要工作就是视频解码,具体如下:
- 从工作线程接收数据,然后调用视频解码器执行解码逻辑。
- 将解码后的视频数据发送给渲染线程。
具体实现的线程函数是 VideoReceiveStream::DecodeThreadFunction ,实现文件是 video/http://video_receive_stream.cc。
- 视频渲染线程
主要工作是将解码后的视频图像发送给上层应用,进行渲染。具体实现类是
IncomingVideoStream::NewFrameTask,通过 rtc::QueuedTask 实现的。
- 音频采集线程
主要工作是音频输入采集,比如采集麦克风声音。在 Windows 平台的线程函数 是 AudioDeviceWindowsCore::WSAPICaptureThread。线程名称是“webrtc_core_audio_capture_thread”,实现文件是
http://audio_device_core_win.cc。
- 音频编码线程
主要工作是从音频采集线程接收数据,调用音频编码器进行编码,然后将编码后的数据发送给 PaceSender。实现类是 Channel,通 rtc::TaskQueue 实现的。线程名称是 call_worker_queue,实现文件是 audio/channel.h。
- 音频渲染线程
音频渲染线程也是音频解码线程。在 Windows 平台下,线程函数是 AudioDeviceWindowsCore::WSAPIRenderThread,线程名称是“webrtc_core_audio_render_thread”。
- 发送控制线程
主要工作是定时发送音频、视频 rtp 包,线程名称是 SendControllerThread。
总结
本文是专门讨论 WebRTC 的线程模型,文中列出了主要的线程。之所以要分析线程模型,因为 WebRTC 明确规定了哪些模块在哪些线程下执行,在 Debug 版本中增加了很多检测,如果哪个模块没有在自己的线程下执行,会产生 abort 异常,程序自动退出。