# Extension points — Genymobile/scrcpy

> Canonical page: https://codevetter.com/unpack/scrcpy/extension-points

# Extension points — Genymobile/scrcpy

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

Extension is deliberately table-driven. Client CLI: add an OPT_* enum + options[] row + case in the getopt switch + field in scrcpy_options. Server options: mirror the param as an ADD_PARAM in execute_server() and a case in Options.parse(). New control messages require a coordinated change in enum sc_control_msg_type, sc_control_msg_serialize/is_droppable/destroy/log, ControlMessage type constants, ControlMessageReader parsing and Controller.handleEvent dispatch. New media sinks plug into the packet_source/packet_sink and frame_source/frame_sink trait interfaces; new input modalities implement key/mouse/gamepad processor interfaces (SDK/UHID/AOA are the three existing backends). Server-side work units implement AsyncProcessor; captures implement SurfaceCapture; audio sources implement AudioCapture.
- Adding a CLI option = new OPT_* enum entry + a row in the static options[] table (shortopt/longopt/argdesc/optional_arg/text) + handling in parse_args_with_getopt's switch; undocumented options are supported by leaving .text NULL. — [app/src/cli.c#L22-149](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/cli.c#L22-L149) [app/src/cli.c#L1431](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/cli.c#L1431)
- Client->server option plumbing is a three-step mirror: sc_server_params field -> ADD_PARAM("key=value") in execute_server() -> case "key" in Options.parse() switch. — [app/src/scrcpy.c#L365-425](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/scrcpy.c#L365-L425) [app/src/server.c#L269-458](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/server.c#L269-L458) [server/src/main/java/com/genymobile/scrcpy/Options.java#L336-574](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/Options.java#L336-L574)
- New control message types must be added symmetrically: enum sc_control_msg_type + serialize/log/droppable/destroy cases client-side, and ControlMessage.TYPE_* + ControlMessageReader.read() case + Controller.handleEvent dispatch server-side. — [app/src/control_msg.h#L29-53](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/control_msg.h#L29-L53) [app/src/control_msg.c#L103-211](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/control_msg.c#L103-L211) [server/src/main/java/com/genymobile/scrcpy/control/ControlMessageReader.java#L25-70](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/control/ControlMessageReader.java#L25-L70) [server/src/main/java/com/genymobile/scrcpy/control/Controller.java#L333-441](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/control/Controller.java#L333-L441)
- The trait/ directory defines generic producer/consumer interfaces (packet_source/packet_sink for AVPackets, frame_source/frame_sink for AVFrames); recorder, decoders, screen, v4l2_sink and regulators all plug in via *_add_sink without knowing each other. — [app/src/trait/packet_source.h](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/trait/packet_source.h) [app/src/trait/frame_source.h](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/trait/frame_source.h) [app/src/scrcpy.c#L555-589](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/scrcpy.c#L555-L589)
- Input backends implement narrow processor interfaces (sc_key_processor, sc_mouse_processor, sc_gamepad_processor in trait/); scrcpy.c picks sdk/uhid/aoa implementations into union members and passes them to the screen as kp/mp/gp. — [app/src/trait/key_processor.h](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/trait/key_processor.h) [app/src/trait/mouse_processor.h](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/trait/mouse_processor.h) [app/src/trait/gamepad_processor.h](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/trait/gamepad_processor.h) [app/src/scrcpy.c#L706-766](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/scrcpy.c#L706-L766)
- Server capture sources implement SurfaceCapture — ScreenCapture, NewDisplayCapture, CameraCapture — selected by videoSource/newDisplay in Server.scrcpy() and attached to SurfaceEncoder. — [server/src/main/java/com/genymobile/scrcpy/Server.java#L139-155](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/Server.java#L139-L155) [server/src/main/java/com/genymobile/scrcpy/video/SurfaceCapture.java](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/video/SurfaceCapture.java)
- Audio capture is pluggable via AudioCapture implementations AudioDirectCapture and AudioPlaybackCapture chosen by AudioSource.isDirect(). — [server/src/main/java/com/genymobile/scrcpy/Server.java#L119-127](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/Server.java#L119-L127) [server/src/main/java/com/genymobile/scrcpy/audio/AudioCapture.java](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/audio/AudioCapture.java)
- Server-side background work implements the AsyncProcessor interface (start/stop/join + TerminationListener); Server keeps a List<AsyncProcessor> it starts and joins uniformly. — [server/src/main/java/com/genymobile/scrcpy/AsyncProcessor.java](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/AsyncProcessor.java) [server/src/main/java/com/genymobile/scrcpy/Server.java#L103-195](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/Server.java#L103-L195)
- Adding a codec means extending enum sc_codec, sc_server_get_codec_name, the demuxer SC_CODEC_ID_* mapping to AVCodecID, and the server-side VideoCodec/AudioCodec enums with matching wire ids. — [app/src/server.c#L105-130](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/server.c#L105-L130) [app/src/demuxer.c#L19-58](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/demuxer.c#L19-L58) [server/src/main/java/com/genymobile/scrcpy/video/VideoCodec.java](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/server/src/main/java/com/genymobile/scrcpy/video/VideoCodec.java)
- Custom SDL event types (SC_EVENT_*) in events.h + sc_push_event provide the extension mechanism for cross-thread signaling into the main event loop. — [app/src/events.h](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/events.h) [app/src/scrcpy.c#L116-153](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/scrcpy.c#L116-L153)
- Recording formats extend enum sc_record_format -> sc_recorder_get_format_name() mapping to FFmpeg muxer names (mp4/matroska/opus/flac/wav). — [app/src/recorder.c#L64-83](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/recorder.c#L64-L83)
- Feature flags compile out whole subsystems: HAVE_USB gates OTG/AOA code, HAVE_V4L2 gates the webcam sink, SERVER_DEBUGGER adds jdwp flags to the app_process command. — [app/meson.build#L104-119](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/meson.build#L104-L119) [app/src/server.c#L225-249](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/app/src/server.c#L225-L249) [meson_options.txt](https://github.com/Genymobile/scrcpy/blob/19c1261d2e2cbf2b5e6a71a8b64cc1dd3ede06ac/meson_options.txt)

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)
