创新的背景:

  一直以来,只要有人用远程协助,就有人说:远程协助怎么用?这个牵涉到两个电脑熟练程度不同的人之间的协同功能,似乎一直都需要印一份远程协助使用手册发到每一个QQ用户,以及他们爸妈的手中。。。才能解决问题。有时候爸妈有一个非常芝麻绿豆的小问题,我们看起里非常简单的,无非是点几下鼠标,敲几下键盘的事情,对他们来说却非常困难。当求助我们的时候,短信电话里面怎么都讲都解释不清楚,这个时候我们就会想起神奇的QQ的远程协助。但是,杯具就发生了,要建立远程协助,需要由父母来发起请求。。。 也许是因为这个功能的按钮一直隐藏在QQ的会话窗口顶部众多按钮中,毫不起眼,平常用到的不多。看来,这是一个QQ必须要解决的问题,不然,爸妈就只能去求教小区里其他的人,或者冒着被乱收费的风险去电脑城找个人来修,也许那人只是点了一下对话框的确定按钮,就可以收费50元。

 

创新点:

  既然需要帮助的是父母,我们是帮忙解决问题的,那就让父母更轻松点。所以这里我们就把建立和发起远程连接的发起人变成解决问题的人。当需要建立远程控制的连接时,控制方可以直接发起控制请求,被控方只需要点击一下弹出提示中的接受就可以了。

1. QQ会话窗口中,点击请求控制对方电脑,然后对方会收到远程桌面请求的提示:

 

 

  对方点击接受后,连接成功就可以直接受控了。

  控制方的窗口默认独立于QQ会话窗口,这样可以增加更多的操作空间。

 

2。 双缓冲+多级流水线提高整体性能,实现了超越30帧的极速流畅体验和高画质效果,控制远端电脑更像控制一台真实电脑:

 

 

  在控制对方的过程中,如果带宽情况允许的话,你甚至可以流畅的欣赏远端电脑上的高清视频内容。这样,就算你和爸妈、女朋友无法相聚,也可以一起欣赏某台电脑上的同一部电影,并且画质和流畅度都很理想。

1.    技术上,使用chrome的异步化编程模型,实现了核心代码的多平台支持和异步化,为将来从移动端对PC端进行远程控制打好基础

2.    差异化的屏幕画面传输,实现更低的资源占用,在截屏阶段就只对变化的区域进行处理,减少后续的处理的数据量。

 

技术方案简述:

  远程桌面的技术实现原理其实很简单:一方面,对于被控方,我们先录制屏幕,然后当作电影一样,传送到主控方,播放出来。另一方面,与此同时,我们抓取主控方的鼠标键盘操作,传送到被控方,并模拟鼠标键盘的行为。稍详细的实现方式如图1所示。    

 

1 远程桌面实现原理图

  接下来稍详细的描述一下视频的实现方案。视频桌面主要包括如下几个操作:截屏、转码、编码、传输、解码、再转码和渲染。下面分别说明:

1)所谓截屏,就是将用户的屏幕截取下来,就像用PrintScreen键进行截屏操作一样,我们在实现的时候使用了GDIDX两种互相补充的实现方案。其他可选的方案包括Mirror Driver这种驱动方式,不过涉及到驱动就有小问题,比如对别有用心的人会说,一个聊天软件居然要装驱动,可能不能接受,另外安装驱动会导致QQ安装包体积变大。

2)一般截屏获得的是个位图,RGBRGBA)的图片,我们需要将其转换为YUV编码以便交给视频编码器,这就需要RGB2YUV的转码,这里我们使用了汇编优化以及GPU加速的实现方案以提升性能。一般来说对于PC,其CPU功能强大,使用汇编优化就足够了,对于手持设备,CPU是宝贵的资源,尽量减少CPU的使用,那么这个时候如果有可以利用GPU自然要利用起来。

3)接下来就是编码,对原始视频帧进行编码的最主要目的就是减少传输数据的大小,至于编码压缩的原理这个有点复杂,所以我们本着邓爷爷的拿来主义态度,找现有的编解码器就好了。比如GoogleVP8视频编解码器就是款很不错的开源视频编解码器,当然还可以使用其他的性能更好的编解码器比如H264,但有一定的版本成本。视频编解码器输入的YUV格式的帧,得到的是一个经过编码的视频帧序列。

4)网络模块负责将产生的视频帧序列传送到对端,既然我们的QQ能传文件、传视频,自然也能将这个视频帧传送给对端。当然实际使用过程中还是有些不同的,传文件我们可以忽快忽慢,只要最终能将所有的文件数据传送到对端即可,但视频不行,因为看网络视频的时候播放是忽快忽慢的,这样的话用户就要抓狂了,所以这里还涉及到网络延迟处理等问题,稍后会谈到。

5)对端接收到视频帧后将其交给视频解码器,当然,一方使用VP8编码,另一方就要使用VP8来解码。经过解码会得到一个个的YUV编码的数据帧图片序列。

6)再转码就是将YUV编码格式的帧转成我们一般的位图,我们就可以看到这个图片了,这里我们也同样需要汇编优化和GPU加速。

7)最后就是贴图了,将一个个位图贴到窗口上,学过windows窗口编程的同学一定知道怎么去刷位图的。

  上面说的是视频总体的流程,为了提高整体的流畅度和体验,我们做了如下几个事情:

1.使用chrome的异步化编程模型。chrome代码库是一套非常优秀的开源代码库,特别是核心代码是一套可跨平台的、多线程(多进程)、异步的编程框架。我们的远程桌面吸取了其中优秀的部分,为我们的多平台,异步化做了很好的支持。

2.多级流水线提高整体性能,图2很好的说明了双缓冲+多级流水的方式

  这里采用了双缓冲方式,一个缓冲区用于读,一个缓冲区用于写,其实就是对大家原来操作系统课上学过的生产者消费者模型的一种优化,原有模型中使用一个缓冲区,读写互斥操作,现在变成两个缓冲区,一个给读一个给写,当然锁还是需要的,不过读写过程不用互斥了,提高了性能,切换的时候要注意先释放锁再获得另外一个缓冲区的互斥锁,以避免死锁。

  流水线的方式,图2就很好的说明,其实也看到了双缓冲区的使用。   

2 多级流水线

3.负反馈模型。根据图1,我们可以看到在视频流是一个单向流动的数据,可以理解这个数据流会流过多个管道,包括截屏管道、编码管道,网络,解码管道和渲染管道,任何一个管道变窄都会影响整个视频流的流速,于此同时,我们要能及时发现这个窄管道,并动态调整当前的流速以适应管道的大小。这就是负反馈要做的事情。实现原理我们就需要倒过来看,对于接收方,如果其不能处理更多数据了,比如解码器太慢或者渲染器太慢,就要会最终将网络层的接受缓冲区充满,这是要通过网络层通知发送方不要在发送数据,对应的表现就是发送方的发送缓冲区变满,如果发送缓冲区编码就导致编码器产生的数据不能写入,从而卡住编码器的工作,在负反馈到截屏模块,发现可以写的缓冲区都满了,自然就需要停止截屏工作了,整个过程就是动态的负反馈过程,从而让系统达到一个动态的平衡。

4.音视频同步问题。这个问题可以比较负责任的说,我们几乎没有做音视频同步,简单说以音频为基准,当双方的时间差异比较大的时候强制做一次同步。这个使我们实现上比较薄弱的地方,后续我们要花精力在这里做优化。

5.视频(音频)延迟问题。这里涉及到两方面延迟:一个是机器本身的处理延迟,另一个是网络延迟。

  机器本身的延迟包括:截屏延迟、编码延迟,转码延迟,解码演示和渲染延迟。由于采用多级流水,虽然这些处理流程是串性的,但整体的延迟由其中每种延迟的最大一个决定。所以我们先针对每种操作简单描述一下提高性能的方式:

1)截屏,刚才提到了我们有几种截屏方案包括GDIDirectXMirrorDriver等方案,表1对比了集中方案:

1 几种截屏方案对比

  我们用了GDI作为保底方案,在可以使用DirectX的机器上使用DirectX以提升性能,MirrorDriver的方案就暂时未用,减少QQ安装包体积。与此同时,对屏幕做差异化分析,在截屏阶段就只对变化的区域进行处理,减少后续的处理的数据量。

2)视频编解码优化,这个不是我们的专长,包括编解码器的参数优化,所以这里要感谢即通音视频中心的同学的大力支持。广告一下他们还提供跨平台的音视频编解码解决方案。

3)转码优化。这个上面说了引入汇编优化和GPU加速,其实在GPU加速上我们还可以再优化,不过目前来说转码已经不是性能的关键点,优化后的整体效果提升不大。

4)渲染这个性能也不是瓶颈,所以没有专门的优化。  

  上面描述的是关于机器本身的延迟优化处理,还有另外一类延迟是网络延迟,处理方案就完全不同了,首先要做的就是:

1)延迟检测,校准双方的时间(这个本身就比较难,所以近似认为相同,以QQ登陆返回srv时间为基准换算当前时间),需要检测单方向延迟,网络中AB互发包,由于数据包在网络上的路由不保证是一致的,所以两个方向上的延迟也不固定。我们这里AB发包,B收到后打上时间戳立即发送回去,A收到后检测单向网络延迟。取多次平均后得到一个稳定基准值,后续启动视频后检测延迟的变化情况。

2)同步的基准,一般以音频为基准,因为视频跳帧大家可以接受,但音频跳跃就不可接受了。

3)同步原理:检测网络带宽占用和网络延迟,实时调整带宽占用和网络延迟,同样通过负反馈方式使得系统达到动态稳定。

4UDPTCP。使用TCP自带的流控策略我们的很多逻辑可以简化,但带来的问题就是灵活性变差,性能下降。使用UDP对于这种实时性要求比较高的场合是比较适用的,不过我们目前还没有使用UDP方案,这也是我们后续优化的方向。