Files
screen_cast/docs/PHASES.md
T
fegger 7be8d59d07 feat(network): implement Phase 6 LAN discovery and session signaling
Add mDNS/DNS-SD discovery and JSON session negotiation so two peers on
a LAN connect without hard-coded addresses.

- Discovery (Avahi threaded-poll client): the receiver announces
  _screencast._tcp with its signaling port; senders browse and resolve
  peers. Strict lock ordering (poll lock before state mutex) keeps the
  callbacks deadlock-free; name collisions rename via
  avahi_alternative_service_name.
- Signaling: one JSON object per newline-terminated TCP line. The
  receiver hosts a server (port 5005) and answers session offers with
  its RTP port; senders connect, offer, and stream to the negotiated
  endpoint. WebSocket was deferred: no WS library is installed, the
  skill permits plain TCP, and the wire format is transport-agnostic.
- Dual-stack transports: this machine resolves its own services over
  IPv6, so getaddrinfo now runs AF_UNSPEC and listeners bind IPv6 with
  IPV6_V6ONLY=0 (IPv4 fallback), covering UDP and TCP alike. The
  signaling client shutdown now uses shutdown() so a reader blocked in
  recv() cannot hang the join (a plain close() does not wake it).
- CLI: --discover lists receivers (deduped to one entry per host);
  --send auto-disovers when exactly one receiver is found; --peer
  targets a receiver directly; --signaling-port overrides the default.

Validation: meson test 5/5 (new signaling round-trip test), valgrind
clean. End-to-end over loopback: --discover finds the announced
receiver, a probe negotiated a session and streamed 60 frames over
both IPv4 and IPv6, and the receiver reported stream started. mDNS
resolution was verified against avahi-browse as an independent
reference.
2026-09-07 12:16:34 +02:00

96 lines
3.4 KiB
Markdown

# 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`.
- [x] Unit test that exercises a trivial utility function.
- [x] `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.
- [x] Add `libavcodec`, `libavutil`, `libswscale` dependencies.
- [x] Implement `EncoderFactory::create()` and `Encoder::encode()`.
- [x] Implement `DecoderFactory::create()` and `Decoder::decode()`.
- [x] 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.
- [x] Add `libpipewire-0.3` dependency.
- [x] Implement `CaptureFactory::create()` using the xdg-desktop-portal.
- [x] 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.
- [x] Implement `RtpHeader` and `RtpPacket` serialize/parse.
- [x] Add H.264 NAL splitting and FU-A fragmentation.
- [x] 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.
- [x] Implement `RtpTransport` with ASIO or raw UDP sockets.
- [x] Wire sender pipeline: capture → encode → RTP → localhost UDP.
- [x] Wire receiver pipeline: localhost UDP → RTP → decode → renderer.
- [x] Add SDL2/SDL3 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.
- [x] Implement mDNS/DNS-SD discovery with Avahi.
- [x] Implement JSON signaling (newline-delimited JSON over TCP for now;
the WebSocket transport is deferred to Phase 7 with its dependency).
- [x] Extend CLI with `--peer` and `--discover`.
**Validation**: two peers connect without hard-coded IP addresses.
Validated end-to-end over loopback: discovery finds the announced receiver,
the sender negotiates a session over the signaling channel, and streams to
the negotiated endpoint over both IPv4 and IPv6.
## 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 7 — Resilience and Polish.