A headless receiver has no window manager, so a windowed window is
meaningless there — the screencast should simply fill the screen. The
renderer now goes borderless fullscreen automatically when SDL runs
the KMSDRM backend, and --fullscreen forces the same behavior in
desktop sessions. The video keeps its aspect ratio via
SDL_SetRenderLogicalPresentation(LETTERBOX): a 4:3 desktop on a 16:9
TV renders with black bars instead of a stretched picture, the cursor
is hidden, and the clear-before-draw keeps the bars black.
Verified live on a 3440x1440 monitor: the --fullscreen receiver window
covered the entire display while a 4:3 synthetic feed rendered with
pure-black pillarbox bars (Y=0/SAT=0) and a saturated-red center
(V=254). meson test 5/5 in both build configurations.
Wire the first end-to-end pipeline: capture -> encode -> packetize ->
UDP -> depacketize -> decode -> render.
- UdpRtpTransport: raw POSIX UDP sockets (IPv4 via getaddrinfo), a
receive jthread woken by socket close on stop; port 0 skips binding
so the sender uses an OS-assigned source port. ASIO stays deferred
to the signaling phase per ARCHITECTURE.md.
- SdlRenderer: SDL3 window/renderer with RGBA texture upload; the
texture is recreated on resolution change. RendererFactory now
returns RendererResult so SDL init failures carry a message,
mirroring the codec/capture error patterns.
- screencast binary: parse_cli plus SenderPipeline/ReceiverPipeline
per the app scaffolds; the sender creates its encoder once capture
reports real dimensions, the receiver keeps a bounded 3-frame queue
to hold latency down and renders on its own thread until the window
closes. cli argv signature fixed to 'const char* const*' so main's
argv converts implicitly.
- Encoder: drop AV_CODEC_FLAG_GLOBAL_HEADER so libx264 repeats SPS/PPS
in-band at each keyframe -- the receiver decodes from the bitstream
alone, which also makes mid-stream joins and later PLI recovery
work without out-of-band parameter negotiation. The round-trip test
now exercises exactly that path.
- tests: new udp-loopback integration test pushes synthetic frames
through a real localhost socket and decodes 10/10 frames with the
right dimensions; valgrind clean (loopback + codec). meson test 4/4.
Manual validation on the desktop (receiver window shows the captured
desktop) is documented in docs/RUNBOOK.md.
Add a linkable CaptureFactory stub so the capture API can be consumed
without unresolved symbols. Change remaining config string_view fields to
std::string to prevent dangling references. Update handoff memory.