专栏文章 Scrcpy 工具码流格式化

opentest-oper@360.cn · 2019年06月06日 · 最后由 阿飞 回复于 2021年09月18日 · 9735 次阅读

背景

目前,云真机平台实时投屏主要有两种工具: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 格式。

效果展示

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 12 条回复 时间 点赞

为啥我采用 scrcpy+broadway,前端解码的图片会很模糊。我这边是把后端接受 scrcpy 发来的数据直接推送给了前端,还是后端需要对 scrcpy 做处理吗?

prime89 回复

通过 socket 采集到的数据需要根据 h264 的帧格式,切分一下,然后发送给前端帧数据。理论上清晰度比 minicap 要高。

prime89 回复

大哥,你知道怎么从后端获取到 scrcpy 发来到数据吗。或者应该如何链接 apk 里面到 sokcet,我没找到链接端口和地址。请指教下可以吗。目前我大概理解为,apk 通过发送 socket 到电脑的端口上,然后电脑获取 apk 发来的信息。但是我不知道怎么连他的 socket

按照帧格式切分有相关说明吗?

可以找您定做个方案吗

air秋天 回复

定做什么?需要根据内容评估。

把 scrcpy 的控制功能,单独 剥离出来的。。。可以吗

基于 scrcpy-server 哪个版本修改的呢

直接使用 broadway 解码.h264 播放,我这边会花屏,请问你们有遇到过这个问题吗?

您好,我刚开始学习 scrcpy(学生),请问您是使用什么编译 scrcpy 的,然后又是怎么运行的呢??能不能教教我呀。拜托了,非常感谢!

大佬想问下,安卓 10 以上的 minitouch 已经不支持了,有什么解决思路么,我不想用 stf 的那个 apk 转发,我单纯想用 minitouch

易轻狂 回复

minitouch 不用想了,安卓 10 以上启动 stfservice.apk,效果等同 minitouch,因为命令是一样的
adb push STFService.apk /data/local/tmp
adb shell CLASSPATH=STFService.apk exec app_process /system/bin jp.co.cyberagent.stf.MinitouchAgent
adb forward tcp:30000 localabstract:minitouchagent

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册