python+minicap的使用

提及Minicap,不得不提到STF,STF (Smartphone Test Farm) 是一個開源的web架構應用,用戶可經過瀏覽器遠程操做Android設備、調試Android應用、在設備上進行測試,實現真正意義雲端使用、調試、測試、管理真機器。STF出現之後,國內幾個大互聯網公司也紛紛跟進效仿,出現了相似的真機調試、管理平臺,較爲知名的有騰訊Wetest、阿里MQC、百度MTCTestIn等。可見遠程真機調試在移動研發領域的做用仍是受到了比較高的重視,也能爲公司以及用戶帶來比較直接的收益。下面是STF官方的介紹動畫。html

 
STF

minicap簡介

minicap屬於STF框架的一個工具,由STF團隊自身開發,屬於較爲核心的一部分,minicap運行於android設備端,負責設備屏幕視頻的實時採集並經過socket接口發送,github下載地址:https://github.com/openstf/minicapmicicap。minicap採集屏幕的原理很簡單:經過ndk的截屏接口不停的截屏並經過socket接口實時發送,這樣客戶端即可以獲得一序列的圖片流,圖片流合成後就成爲視頻;python

構建minicap

micicap由Android ndk開發,包含一個可執行的二進制文件以及一個so文件,運行minicap前,須要經過adb命令將設備對應CPU架構以及設備對應SDK版本的minicap文件拷貝到設備後,再執行。因爲github上並無上傳編譯完成後的產物,所以咱們須要自行編譯。android

編譯依賴環境:git

1)、NDK;github

2)、make;web

3)、git;shell

環境依賴較爲簡單,若是沒有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進行界面的刷新:

 
 
 本文轉載地址自:https://www.jianshu.com/p/777af34b4f21
參考博客 https://www.cnblogs.com/xiand/p/6724399.html
相關文章
相關標籤/搜索