Scaffold C++20 screencast project with Meson, agent workflow, and phase plan

This commit is contained in:
2026-08-28 21:54:32 +02:00
commit 742611b841
25 changed files with 1322 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
# Architecture
`screen_cast` is a native Linux screencast application that sends and receives
desktop video over the LAN. It is intentionally split into small, replaceable
modules so that capture, codec, network, and rendering concerns can evolve
independently.
## Goals
- Works on modern Linux desktops (Wayland and X11).
- Low-latency peer-to-peer streaming.
- CLI-first; optional GUI later.
- Software and hardware-accelerated encoding paths.
- Minimal, auditable network protocol.
## Module overview
```
┌─────────────┐ ┌────────────┐ ┌─────────────┐ ┌──────────┐
│ Capture │────▶│ Encoder │────▶│ Packetize │────▶│ RTP/UDP │ Sender
│ (PipeWire) │ │ (FFmpeg) │ │ (RTP) │ │ Transport│
└─────────────┘ └────────────┘ └─────────────┘ └──────────┘
┌──────────┐ ┌─────────────┐ ┌────────────┐ ┌─────────────┐
│ RTP/UDP │────▶│ Depacketize │────▶│ Decoder │────▶│ Renderer │ Receiver
│Transport │ │ (RTP) │ │ (FFmpeg) │ │ (SDL/GL) │
└──────────┘ └─────────────┘ └────────────┘ └─────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ Control / Signaling / Discovery │
│ WebSocket/JSON control + mDNS/Avahi discovery │
└──────────────────────────────────────────────────────────────────┘
```
## Module responsibilities
| Module | Directory | Responsibility |
|---|---|---|
| Capture | `include/screencast/capture/` | Acquire raw frames from PipeWire/portal. |
| Codec | `include/screencast/codec/` | Encode to / decode from H.264 with FFmpeg. |
| Network | `include/screencast/network/` | RTP framing, UDP transport, signaling, discovery. |
| Render | `include/screencast/render/` | Display decoded frames. |
| App | `include/screencast/app/` | CLI parsing, sender/receiver pipelines. |
## Pipeline rules
- Each pipeline owns its modules and threads.
- Frames are transferred as owned buffers (`std::vector<std::byte>`).
- Timestamps start in the capture clock domain and are converted to RTP clock
domain once at packetization.
- On sender error the transport is drained and stopped.
- On receiver loss a PLI is sent over signaling; the sender inserts a keyframe.
## Namespace
All project code lives in `namespace sc`.
## Dependencies (planned)
| Library | pkg-config | Phase |
|---|---|---|
| FFmpeg | `libavcodec`, `libavutil`, `libswscale` | 2 |
| PipeWire | `libpipewire-0.3` | 3 |
| SDL2/3 | `sdl2` / `sdl3` | 5 |
| ASIO | bundled or standalone `asio` | 6 |
| Avahi | `avahi-client` | 7 |
| WebSocket | `websocketpp` or `uWebSockets` | 7 |
See `docs/PHASES.md` for the phased build plan.
+92
View File
@@ -0,0 +1,92 @@
# Development Phases
This file breaks the project into incremental milestones. Each phase produces a
working, testable slice of functionality. Do not start a phase until the
previous one is validated.
## Phase 1 — Project Skeleton
**Goal**: configure, compile, and run tests with no real dependencies.
- [x] Meson build files (`meson.build`, `meson_options.txt`).
- [x] Public module headers with `namespace sc`.
- [ ] Unit test that exercises a trivial utility function.
- [ ] `README.md` with build instructions.
**Validation**: `meson setup build && meson compile -C build && meson test -C build`.
## Phase 2 — Software H.264 Encode / Decode
**Goal**: encode raw pixel buffers to H.264 and decode them back, purely with
FFmpeg software paths.
- Add `libavcodec`, `libavutil`, `libswscale` dependencies.
- Implement `EncoderFactory::create()` and `Encoder::encode()`.
- Implement `DecoderFactory::create()` and `Decoder::decode()`.
- Round-trip test: synthetic RGB frames → H.264 → decoded RGB.
**Validation**: unit test produces visually/structurally correct round-trip
frames.
## Phase 3 — PipeWire Screen Capture
**Goal**: capture the desktop and feed frames into the encoder.
- Add `libpipewire-0.3` dependency.
- Implement `CaptureFactory::create()` using the xdg-desktop-portal.
- Wire `CaptureSession::next_frame()``Encoder::encode()` in a local smoke
test that just writes a few encoded frames to disk.
**Validation**: manual run on a real Linux desktop session produces a valid
H.264 bitstream.
## Phase 4 — RTP Framing
**Goal**: packetize NAL units into RTP and depacketize them.
- Implement `RtpHeader` and `RtpPacket` serialize/parse.
- Add H.264 NAL splitting and FU-A fragmentation.
- Unit test for serialization, fragmentation, and reassembly.
**Validation**: unit tests cover single-NAL and fragmented packet paths.
## Phase 5 — Local UDP Sender → Receiver Loopback
**Goal**: send RTP packets over UDP and render the result locally.
- Implement `RtpTransport` with ASIO or raw UDP sockets.
- Wire sender pipeline: capture → encode → RTP → localhost UDP.
- Wire receiver pipeline: localhost UDP → RTP → decode → renderer.
- Add SDL2/3 dependency and a minimal `Renderer`.
**Validation**: `screencast --send` and `screencast --receive` on the same
machine show the captured desktop in a window.
## Phase 6 — LAN Signaling and Discovery
**Goal**: two peers on the same LAN can find each other and negotiate a
session.
- Implement mDNS/DNS-SD discovery with Avahi.
- Implement JSON WebSocket signaling.
- Extend CLI with `--peer-address` or `--discover`.
**Validation**: two machines on the same LAN connect without hard-coded IP
addresses.
## Phase 7 — Resilience and Polish
**Goal**: loss recovery, hardware acceleration, and packaging.
- NACK / PLI feedback loop.
- Jitter buffer on the receiver.
- VAAPI/NVENC hardware encode probes and fallback.
- Optional GUI target behind `meson -Dgui=true`.
- `.desktop` file, icon, packaging notes.
**Validation**: sustained streaming under packet loss; hardware accel smoke
where available.
## Current phase
Phase 1 — skeleton and tooling.