Scaffold C++20 screencast project with Meson, agent workflow, and phase plan
This commit is contained in:
@@ -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.
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user