90a46b4c45
On startup, the client has to: 1. listen on a port 2. push and start the server to the device 3. wait for the server to connect (accept) 4. read device name and size 5. initialize SDL 6. initialize the window and renderer 7. show the window From the execution of the app_process command to start the server on the device, to the execution of the java main method, it takes ~800ms. As a consequence, step 3 also takes ~800ms on the client. Once complete, the client initializes SDL, which takes ~500ms. These two expensive actions are executed sequentially: HOST DEVICE listen on port | | push/start the server |----------------->|| app_process loads the jar accept the connection . ^ || . | || . | WASTE || . | OF || . | TIME || . | || . | || . v X execution of our java main connection accepted |<-----------------| connect to the host init SDL || | || ,----------------| send frames || |,---------------| || ||,--------------| || |||,-------------| || ||||,------------| init window/renderer | |||||,-----------| display frames |<++++++-----------| (many frames skipped) The rationale for step 3 occuring before step 5 is that initializing SDL replaces the SIGTERM handler to receive the event in the event loop, so pressing Ctrl+C during step 5 would not work (since it blocks the event loop). But this is not so important; let's parallelize the SDL initialization with the app_process execution (we'll just add a timeout to the connection): HOST DEVICE listen on port | | push/start the server |----------------->||app_process loads the jar init SDL || || || || || || || || || || || || accept the connection . || . X execution of our java main connection accepted |<-----------------| connect to the host init window/renderer | | display frames |<-----------------| send frames |<-----------------| In addition, show the window only once the first frame is available to avoid flickering (opening a black window for 100~200ms). Note: the window and renderer are initialized after the connection is accepted because they use the device information received from the device. |
||
---|---|---|
app | ||
config | ||
gradle/wrapper | ||
server | ||
.gitignore | ||
build.gradle | ||
gradle.properties | ||
gradlew | ||
gradlew.bat | ||
Makefile | ||
README.md | ||
settings.gradle |
ScrCpy
This project displays screens of Android devices plugged on USB in live.
Run
Runtime requirements
This projects requires FFmpeg, LibSDL2 and LibSDL2-net.
Linux
Install the packages from your package manager. For example, on Debian:
sudo apt install ffmpeg libsdl2-2.0.0 libsdl2-net-2.0.0
Windows
From MSYS2:
pacman -S mingw-w64-x86_64-SDL2
pacman -S mingw-w64-x86_64-SDL2_net
pacman -S mingw-w64-x86_64-ffmpeg
MacOS
TODO
Build
The project is divided into two parts:
- the server, running on the device (in
server/
); - the client, running on the computer (in
app/
).
The server is a raw Java project requiring Android SDK. It not an Android
project: the target file is a .jar
, and a main()
method is executed with
shell rights.
The client is a C project using SDL and FFmpeg, built with Meson/Ninja.
The root directory contains a Makefile
to build both parts.
Build requirements
Install the Android SDK, the JDK 8 (openjdk-8-jdk
), and the packages
described below.
Linux
sudo apt install make gcc openjdk-8-jdk pkg-config meson zip \
libavcodec-dev libavformat-dev libavutil-dev \
libsdl2-dev libsdl2-net-dev
Windows
Install these packages:
pacman -S mingw-w64-x86_64-make
pacman -S mingw-w64-x86_64-gcc
pacman -S mingw-w64-x86_64-pkg-config
pacman -S mingw-w64-x86_64-meson
pacman -S zip
Java 8 is not available in MSYS2, so install it manually and make it available
from the PATH
:
export PATH="$JAVA_HOME/bin:$PATH"
Build
Make sure your ANDROID_HOME
variable is set to your Android SDK directory:
export ANDROID_HOME=~/android/sdk
From the project root directory, execute:
make build
To run the build:
make run
It is also pass arguments to scrcpy
via make
:
make run ARGS="-p 1234"
The purpose of this command is to execute scrcpy
during the development.
Test
To execute unit tests:
make test
The server-side tests require JUnit 4:
sudo apt install junit4
Generate a release
From the project root directory, execute:
make release
This will generate the application in dist/scrcpy/
.
Run
Plug a device, and from dist/scrcpy/
, execute:
./scrcpy
If several devices are listed in adb devices
, you must specify the serial:
./scrcpy 0123456789abcdef
To change the default port (useful to launch several scrcpy
simultaneously):
./scrcpy -p 1234
Other options are available, check scrcpy --help
.