Python实现minicap协议解析并通过PyQt渲染

说起Minicap,不得不提到STF,STF (Smartphone Test Farm) 是一个开源的web架构应用,用户可通过浏览器远程操作Android设备、调试Android应用、在设备上进行测试,实现真正意义云端使用、调试、测试、管理真机器。STF出现以后,国内几个大互联网公司也纷纷跟进效仿,出现了类似的真机调试、管理平台,较为知名的有腾讯Wetest、阿里MQC、百度MTCTestIn等。可见远程真机调试在移动研发领域的作用还是受到了比较高的重视,也能为公司以及用户带来比较直接的收益。下面是STF官方的介绍动画。

STF

minicap简介

minicap属于STF框架的一个工具,由STF团队自身开发,属于较为核心的一部分,minicap运行于android设备端,负责设备屏幕视频的实时采集并通过socket接口发送,github下载地址:https://github.com/openstf/minicapmicicap。minicap采集屏幕的原理很简单:通过ndk的截屏接口不停的截屏并通过socket接口实时发送,这样客户端便可以得到一序列的图片流,图片流合成后就成为视频;

构建minicap

micicap由Android ndk开发,包含一个可执行的二进制文件以及一个so文件,运行minicap前,需要通过adb命令将设备对应CPU架构以及设备对应SDK版本的minicap文件拷贝到设备后,再执行。由于github上并没有上传编译完成后的产物,因此我们需要自行编译。

编译依赖环境:

1)、NDK;

2)、make;

3)、git;

环境依赖较为简单,如果没有NDK以及make环境的,可自行百度安装;

构建过程:

1)、通过git下载minicamp源码:

git clone https://github.com/openstf/minicap.git

2)、micicap项目还依赖于libjpeg-turbo,首先我们需要在minicap引入libjpeg-turbo项目源码:

git submodule init

git submodule update

3)、执行ndk-build,构建完成后,minicap编译后的产物将会在libs目录下找到;

ndk-build

运行minicap

1)、获取设备CPU支持的ABI,minicap针对4种不同的ABI构建了不同的so文件和可执行文件,分别是:x86_64/x86/arm64-v8a/armeabi-v7a;

ABI=$(adb shell getprop ro.product.cpu.abi|tr -d'\r')

2)、拷贝对应ABI版本的文件到设备,这里使用的是adb push;

adb push libs/$ABI/minicap /data/local/tmp/

3)、获取设备对应的SDK版本;

SDK=$(adb shell getprop ro.build.version.sdk|tr -d'\r')

4)、只有可执行文件是不够的,我们还需要拷贝对应sdk版本的共享库到设备;

adb push jni/minicap-shared/aosp/libs/android-$SDK/$ABI/minicap.so /data/local/tmp/

5)、每次启动minicap,我们都需要设置LD_LIBRARY_PATH,不然会提示找不到公共库,-P后面的参数为:{RealWidth}x{RealHeight}@{VirtualWidth}x{VirtualHeight}/{Orientation},可以指定采集的实际大小、虚拟大小以及屏幕方向,实际大小一般设置成设备物理分辨率大小,虚拟大小是通过socket接口发送的大小,屏幕实际窗口大小我们可以通过adb命令获取;

adb shell dumpsys window | grep -Eo 'init=\d+x\d+' | head -1 | cut -d= -f 2

6)、启动minicap,下面我们假设获取到的实际屏幕大小是1080x1920,需要发送的虚拟窗口大小是540x960,采集的屏幕方向是纵向;

adb shell LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap -P 1080x1920@1080x1920/0

7)、端口转发,通过adb forward命令,可以把minicap端口映射到我们PC指定的端口,localabstract:minicap是UNIX域名的SOCKET名称,把minicap的socket端口映射到PC的1313端口,这样我们就可以在PC通过连接1313端口获取到设备的实时视频流;

adb forward tcp:1313 localabstract:minicap

minicap协议解析

minicap启动并用adb forward命令映射端口后,我们就可以通过socket与minicap建立连接。

1)、Global header

minicap协议是一种简单的二进制流推送流协议,一旦与minicap建立连接,minicap首先会推送长度为24字节的global header,global header只会推送一次,后续推送的数据不会再包括global header,而是不断的推送实时图片流数据,直到客户端关闭socket连接。

Global header binary format

Global header说包含了基本的一些信息,如minicap的版本信息、头长度、实际大小以及虚拟大小、设备方向等,这些信息我们可以保存起来,方便后面使用,这里我使用python解析了Global header,代码参考如下:

2)、Frame binary format

接下来,minicap会不断的推送一帧一帧的图片流,每一帧都包含两部分信息:0-3字节,表示这一帧图片的长度n,由4个字节的32位整型小端格式存储;4-(n+4)字节,是具体的图片数据,由JPG格式存储,这部分才是我们想要的最关键数据;

Frame binary format

至此,我们完成了minicap协议的解析,并获取到了minicap推送过来的每一帧图片。需要注意的是,由于minicap是实时推送流,因此流的数据可能会比较大,客户端获取的buffer需要尽可能的大,不然我们在渲染每一帧的时候,可能会出现卡顿的现象,具体多大合适,我们可以稍微推算一下,一张由minicap推送过来的1080x1920大小的png图片,大概是100-200KB,minicap宣称帧率可以达到20 FPS左右,因此我们的buffer可以设置为:200KB * 20 = 4096000字节,每隔一秒recv()一次;

PyQt实时渲染

获取到图片流数据后,我们可以使用PyQt中的paintEvent进行渲染,下面的refreshFrame()方法,关联了获取图片线程中的一个信号槽,一旦获取图片线程从minicap解析到一帧的图片,便会通知refreshFrame()中的self.update()方法,self.update()方法则会调用paintEvent进行界面的刷新:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容