Architecture Overview
Scrcpy for Android uses a client-server architecture to enable Android-to-Android screen mirroring and control. The application is split into two distinct modules that communicate over TCP sockets.Two-Module Structure
The project consists of two independent modules:Client (App Module)
Located in
app/src/main/java/org/client/scrcpy/Runs on the controlling Android device and handles:- Video/audio decoding
- Display rendering
- Touch input capture
- Network communication
Server Module
Located in
server/src/main/java/org/server/scrcpy/Runs on the target Android device and handles:- Screen capture
- Video/audio encoding
- Input event injection
- ADB socket management
Client-Server Communication
The architecture follows a bidirectional communication pattern:Video Streaming Pipeline
The video streaming process involves multiple stages from capture to display:Server Side (Encoding)
-
Screen Capture (
ScreenCapture.java)- Uses Android’s
MediaCodecAPI withVirtualDisplay - Captures screen content as a
Surface - Supports rotation changes dynamically
- Uses Android’s
-
Video Encoding (
ScreenEncoder.java)- Encodes to H.264 (AVC) format
- Configuration:
bitRate,frameRate(default 60fps),iFrameInterval(default 10s) - Packets are tagged with flags:
CONFIG,KEY_FRAME,FRAME, orEND - Each packet includes a presentation timestamp
-
Packet Structure (
VideoPacket.java)
Client Side (Decoding)
-
Network Reception (
Scrcpy.java:342-470)- Reads packets from
DataInputStream - Packet size is transmitted first (4 bytes)
- Validates packet size (max 4MB per packet)
- Reads packets from
-
Video Decoding (
VideoDecoder.java)- Configures
MediaCodecwith SPS/PPS from CONFIG packets - Decodes H.264 stream to
Surface - Handles surface updates on rotation
- Configures
-
Rendering
- Direct rendering to
SurfaceViewviaMediaCodec - Aspect ratio preservation with padding calculation
- Direct rendering to
Audio Streaming Pipeline
Audio follows a parallel pipeline to video:Server Side
-
Audio Capture (
AudioCapture.java,AudioDirectCapture.java)- Captures system audio using
AudioRecord - Default bitrate: 128kbps
- Runs asynchronously in separate thread (
ScreenEncoder.java:113-129)
- Captures system audio using
-
Audio Encoding (
AudioEncoder.java)- Encodes to AAC format
- Packets tagged with
CONFIG,FRAME, orENDflags
Client Side
- Audio Decoding (
AudioDecoder.java)- Decodes AAC packets
- Configures from CONFIG packet data
- Synchronized with video using presentation timestamps
Touch Event Handling Flow
Touch events flow from the client device to inject input on the target:Touch Event Protocol
Each touch event is serialized as 20 bytes:Coordinate Transformation
The client performs coordinate scaling (Scrcpy.java:136-182):
- Calculate remote device aspect ratio
- Scale local coordinates to remote resolution
- Handle landscape/portrait orientation
- Support multi-touch (up to
MAX_POINTERS)
Server-Side Injection
The server receives events and injects them (EventController.java:66-121):
- Read 20-byte buffer from input stream
- Deserialize action, coordinates, and pointer ID
- Convert to physical screen coordinates
- Create
MotionEventwith proper tool type (TOOL_TYPE_FINGER) - Handle multi-pointer actions (
ACTION_POINTER_DOWN/UP) - Inject via
InputManager.injectInputEvent()
ADB Port Forwarding Mechanism
The connection setup relies on ADB’s port forwarding feature:Connection Establishment
-
ADB Connection (
SendCommands.java:92-114) -
Server Socket (
DroidConnection.java:27-36)- Server opens
ServerSocketon port 7007 - Waits for incoming connection
- Validates client IP address
- Server opens
-
Client Socket (
Scrcpy.java:227-290)- Client connects to
127.0.0.1:7008(forwarded port) - Connection timeout: 5000ms
- Retry mechanism: up to 50 attempts
- Client connects to
Initial Handshake
-
Server sends device resolution as first packet (16 bytes):
- Client reads resolution and configures decoders
- Bidirectional streaming begins
Key Components Reference
| Component | Location | Responsibility |
|---|---|---|
Server.java | server/src/main/java/org/server/scrcpy/ | Entry point, orchestrates server components |
Scrcpy.java | app/src/main/java/org/client/scrcpy/ | Client service, manages connection and decoding |
DroidConnection.java | server/src/main/java/org/server/scrcpy/ | Socket management on server |
ScreenEncoder.java | server/src/main/java/org/server/scrcpy/ | Video encoding and streaming |
AudioEncoder.java | server/src/main/java/org/server/scrcpy/ | Audio encoding and streaming |
EventController.java | server/src/main/java/org/server/scrcpy/ | Input event handling and injection |
VideoDecoder.java | app/src/main/java/org/client/scrcpy/decoder/ | Video decoding on client |
AudioDecoder.java | app/src/main/java/org/client/scrcpy/decoder/ | Audio decoding on client |
Performance Considerations
Video Encoding
Video Encoding
- Default: 60fps, adjustable via
Options.java - Resolution must be multiple of 8 (H.264 requirement)
- Key frame interval: 10 seconds
- Bitrate configurable per connection
Network Buffering
Network Buffering
- Client polls input stream with
available()check - Events queued in
LinkedListfor async sending - Frame dropping based on presentation timestamp delay
Threading Model
Threading Model
- Server: Main thread for video encoding, separate thread for event controller
- Client: Decoder threads managed by
MediaCodec, main loop in service thread
The architecture is designed for low-latency local network operation. For public network use, additional latency management may be required.
