目录
今天突然发现自己对 WebRTC 的屏幕分享的底层工作原理有一个误解,之前,我一直以为屏幕分享就是简单的采集桌面的画面,然后编码发送就行了。实时上并不是如此简单,本文就来为大家揭秘。
在正式开始前,我先问大家一个问题:在屏幕分享的时候,鼠标是不是桌面画面的一部分?答案是肯定的!但是,实际上采集的时候并不是我们认为的那样!采集屏幕的时候不会自动把鼠标也采集上!
WebRTC 在进行屏幕分享画面的采集时,屏幕画面和鼠标分别采集的。其中,屏幕画面可能是桌面窗口或者应用程序窗口,鼠标的话,还包括光标形状和光标位置信息。整体关系的示意图如下:
实际上在进行屏幕采集时是可以选择是否包含鼠标的,只是一般情况下都默认包含鼠标。 先来看一下具体执行类的构造函数,代码如下:
DesktopAndCursorComposer::DesktopAndCursorComposer(
std::unique_ptr<DesktopCapturer> desktop_capturer,
const DesktopCaptureOptions& options)
: DesktopAndCursorComposer(desktop_capturer.release(),
MouseCursorMonitor::Create(options).release()) {}
DesktopAndCursorComposer::DesktopAndCursorComposer(
DesktopCapturer* desktop_capturer,
MouseCursorMonitor* mouse_monitor)
: desktop_capturer_(desktop_capturer), mouse_monitor_(mouse_monitor) {
RTC_DCHECK(desktop_capturer_);
}
然后就是启动桌面采集时和执行桌面采集时的代码逻辑区分,如果设置了mouse_monitor,才进行鼠标的捕捉,代码如下:
void DesktopAndCursorComposer::Start(DesktopCapturer::Callback* callback) {
callback_ = callback;
if (mouse_monitor_)
mouse_monitor_->Init(this, MouseCursorMonitor::SHAPE_AND_POSITION);
desktop_capturer_->Start(this);
}
void DesktopAndCursorComposer::CaptureFrame() {
if (mouse_monitor_)
mouse_monitor_->Capture();
desktop_capturer_->CaptureFrame();
}
WebRTC 源码采集屏幕信息的过程如下图所示,其中包含了整个函数方法调用的全过程,涉及屏幕画面以及鼠标的相关内容(光标形状和位置)。
有一点需要格外注意,DesktopAndCursorComposer类在决定多久采集一帧屏幕画面时,是根据如下公式算出来的:
每帧屏幕画面的采集时间间隔 = 1000 / 帧率(fps)
举个例子,如果设置的屏幕共享的帧率是 25fps,那么,每隔40毫秒(ms)就采集一帧屏幕画面。
作者简介:😄大家好,我是 Data-Mining(liuzhen007),是一名典型的音视频技术爱好者,前后就职于传统广电巨头和音视频互联网公司,具有丰富的音视频直播和点播相关经验,对 WebRTC、FFmpeg 和 Electron 有非常深入的了解。同时也是 CSDN 博客专家(博客之星)、华为云享专家(共创编辑、十佳博主)、51CTO社区编辑、InfoQ 签约作者,欢迎关注我分享更多干货!😄