背景

目前,云真机平台实时投屏主要有两种工具:STF 的 minicap 和 GenyMotion 的 scrcpy。STF 的 minicap 工具是采用截图的方式实现实时投屏,但是 minicap 工具根据 google 发布的 Android 版本对应不同的工具文件,当新的 Android 发布时,minicap 的适配版本还未及时发布可能会影响用户体验。Scrcpy 通过获取视频数据实现实时投屏,但是只能支持 Android 5.0 以上。因此,目前这两种投屏方式都有各自的优缺点,我们开测平台采用两种方式结合的方式,用来实时适配 google 发布的 android 版本。最近,在新手机上线过程中,发现有些品牌(如 vivo,oppo)的 9.0 手机无法使用 Scrcpy 工具进行实时投屏,通过分析发现 H264 的码流是 High 档次,而前端 H264 数据播放插件 Broadway 只支持 baseline 档次的码流。

方案

以最新上市的小米 9 为例子,小米 9 是 Android 9.0 手机,虽然 STF 的 minicap 工具已经对 Android 9.0 进行了适配,但是采用 scrcpy 工具时出现获取的 H264 数据无法利用前端插件 Broadway 播放,这是因为 Broadway 插件不支持 H264 baseline 以外的码流。H264 格式数据的码流通过 profile_idc 字段标识,小米 9 获取到的 H264 格式数据如图所示:

其中 profile_idc 等于 100 表示码流是 High 档次,profile_idc 等于 66 表示码流是 baseline 档次。码流的取值是由手机硬件决定的。通过阅读 scrcpy 源码(https://github.com/Genymobile/scrcpy)发现 ScreenEncoder 文件中有个 createForma t 私有方法可以指定视频流数据的格式,因此我们修改该方法的代码,人为的将视频流数据格式化为 baseline,具体代码如图所示:

修改完源码之后实时投屏实现主要包括以下几个步骤:
1.将 scrcpy 源码重新编译成 jar 包,将 jar 包 push 到手机中。
2.在手机中执行命令 CLASSPATH=/data/local/tmp/scrcpy-server.jar app_process / --nice-name=scrcpy_servercom.genymobile.scrcpy.Server 0 8000000 true weight:height:0:0 false,其中 weight 和 height 是手机的宽度和高度。(需要注意的是每次执行命令后,之前 push 到手机中的 jar 包会被清除,所以每次启动命令都需要 pushjar 包)
3.执行 adb forward 命令确保 pc 可以通过 forward 端口和手机进行 socket 通信。获取视频流数据。
4.将获取的视频流数据解析成单条 H264 数据发送给 web 端,web 端通过 Broadway 插件播放视频流实现实时投屏。
修改后 scrcpy.jar 获取得到的视频流解析数据如图所示,可以看到 H264 格式的数据 profile_idc 变成了 66,码流变成 baseline 格式。

效果展示


↙↙↙阅读原文可查看相关链接,并与作者交流