# System map — Genymobile/scrcpy

> Canonical page: https://codevetter.com/unpack/scrcpy/system-map

# System map — Genymobile/scrcpy

Scanned commit 19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac (2026-09-05). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

The repo contains two deployables: the 'scrcpy' client binary in C (app/src) built by Meson, and 'scrcpy-server', an Android Java program (server/) built by Gradle into a dexed jar pushed to /data/local/tmp and run via app_process. The client entrypoint is app/src/main.c -> scrcpy() in app/src/scrcpy.c, which owns a single static struct aggregating server connection, screen, audio player, demuxers, decoders, recorder, controller and optional USB/V4L2 subsystems. The server entrypoint is Server.main -> internalMain -> scrcpy() in Server.java, which wires AsyncProcessors (Controller, audio encoder/recorder, SurfaceEncoder) onto sockets opened through DesktopConnection. Communication is over adb-tunnelled TCP/local sockets (adb reverse by default, forward with --force-adb-forward). CI/release is driven by .github/workflows/release.yml calling scripts in release/.
- The system is split into a host client (C, app/src) and an on-device server (Java, server/src); the client pushes the server and starts it, then they communicate over 1-3 sockets for video, audio and control. — [doc/develop.md](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/doc/develop.md) [app/src/scrcpy.c](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/scrcpy.c) [server/src/main/java/com/genymobile/scrcpy/Server.java](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/Server.java)
- Client entrypoint: main() in app/src/main.c converts Windows UTF-16 argv to UTF-8, calls main_scrcpy() which runs scrcpy_parse_args() then either scrcpy() or scrcpy_otg() (when built with HAVE_USB and --otg is passed). — [app/src/main.c#L27-175](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/main.c#L27-L175) [app/src/usb/scrcpy_otg.c](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/usb/scrcpy_otg.c)
- scrcpy() in app/src/scrcpy.c is the client orchestrator: it fills a static 'struct scrcpy' containing sc_server, sc_screen, sc_audio_player, two sc_demuxer, two sc_decoder, sc_recorder, sc_video_regulator, sc_controller and sc_file_pusher, plus unions of SDK/UHID/AOA input backends. — [app/src/scrcpy.c#L51-95](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/scrcpy.c#L51-L95) [app/src/scrcpy.c#L320-425](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/scrcpy.c#L320-L425)
- The client pushes the server jar to /data/local/tmp/scrcpy-server.jar and executes 'adb -s <serial> shell CLASSPATH=<jar> app_process / com.genymobile.scrcpy.Server <version> key=value...' in execute_server(). — [app/src/server.c#L18-21](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/server.c#L18-L21) [app/src/server.c#L208-262](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/server.c#L208-L262)
- Server-side entry: Server.main -> internalMain drops root privileges to uid 2000 (shell), installs a main Looper via reflection on Looper.sMainLooper (quitAllowed), then Options.parse() validates the client version arg before scrcpy() opens DesktopConnection and starts AsyncProcessors. — [server/src/main/java/com/genymobile/scrcpy/Server.java#L197-291](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/Server.java#L197-L291) [server/src/main/java/com/genymobile/scrcpy/Options.java#L322-335](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/Options.java#L322-L335)
- The control protocol version is tied to the app version: the client passes SCRCPY_VERSION as argv[1] and Options.parse() throws IllegalArgumentException if it differs from BuildConfig.VERSION_NAME. — [app/src/server.c#L253](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/server.c#L253) [server/src/main/java/com/genymobile/scrcpy/Options.java#L328-332](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/Options.java#L328-L332)
- DesktopConnection.open() creates/connects LocalSocket(s) named 'scrcpy_%08x' (scid) — listening with LocalServerSocket in tunnel-forward mode, connecting otherwise — for video, audio and control channels, optionally writing a dummy byte so the client detects a dead tunnel. — [server/src/main/java/com/genymobile/scrcpy/device/DesktopConnection.java#L47-116](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/device/DesktopConnection.java#L47-L116) [app/src/server.c#L489-539](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/server.c#L489-L539)
- Client dependencies are FFmpeg (libavformat, libavcodec, libavutil, libswresample), SDL3 >= 3.2.0, optionally libavdevice (V4L2) and libusb-1.0 (USB/HID/OTG); on Windows it links mingw32 and ws2_32. — [app/meson.build#L125-144](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/meson.build#L125-L144)
- Build system: root meson.build declares project 'scrcpy' v4.1 (C11) with options compile_app/compile_server/prebuilt_server/portable/static/server_debugger/v4l2/usb; the server is produced by a Meson custom_target invoking server/scripts/build-wrapper.sh (Gradle) unless prebuilt_server is set. — [meson.build](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/meson.build) [meson_options.txt](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/meson_options.txt) [server/meson.build#L1-25](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/meson.build#L1-L25)
- scrcpy-server is an Android Gradle module (com.android.application plugin, compileSdk 36, minSdk 21, targetSdk 36) with JUnit testImplementation and a checkstyle config applied from config/android-checkstyle.gradle. — [server/build.gradle](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/build.gradle) [config/android-checkstyle.gradle](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/config/android-checkstyle.gradle)
- Threading model: one dedicated thread per socket direction — run_server (adb process + tunnel), run_demuxer per stream, run_controller + receiver for control, run_file_pusher — coordinated through SDL events posted to the main thread event_loop(). — [app/src/scrcpy.c#L116-153](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/scrcpy.c#L116-L153) [app/src/server.c#L964-1189](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/server.c#L964-L1189) [app/src/demuxer.c#L176-355](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/demuxer.c#L176-L355) [app/src/controller.c#L162-217](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/controller.c#L162-L217)
- Release pipeline: .github/workflows/release.yml (workflow_dispatch) tests server+client, builds server jar and client dists for linux-x86_64/win32/win64/macos aarch64+x86_64, then packages and checksums them via release/*.sh scripts. — [.github/workflows/release.yml](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/.github/workflows/release.yml) [release/test_client.sh](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/release/test_client.sh) [release/test_server.sh](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/release/test_server.sh)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
