# Architecture ## Pipeline ```text RecorderManager │ ├── CaptureSource (×N) one WGC session per window or monitor ├── FrameSynchronizer fixed-FPS tick, non-blocking poll ├── Scene canvas + source placements ├── SceneCompositor CPU BGRA compose (fast 1:1 path when possible) ├── cursor overlay once on the composed frame ├── taskbar overlay optional fake taskbar (window mode only) └── MfEncoder single H.264 MP4 output ``` Each stage has a narrow job. The encoder always sees one full canvas at fixed resolution; it never knows how many windows were captured. --- ## Components ### CaptureSource One Windows Graphics Capture session per target (`CaptureTarget` — window HWND or monitor HMONITOR), with `PrintWindow` fallback when a **window** is occluded. Frames arrive asynchronously; each source keeps a per-source CPU BGRA buffer with the latest frame. GPU textures are copied into a reused scratch buffer to avoid per-frame allocations. ### FrameSynchronizer Drives a fixed FPS clock. On each tick it polls every source and takes the newest frame. If a source has no new frame, the previous one is reused. The synchronizer never blocks waiting for capture. ### Scene Defines canvas size, background, and where each source is placed. Layout math (auto, grid, horizontal, vertical, custom) lives here and does not depend on Media Foundation. ### SceneCompositor Blits each source into the canvas with fit, fill, or stretch scaling. If a window closes mid-recording, that cell shows a **Window Closed** placeholder and recording continues. ### Cursor overlay `GetCursorInfo` plus alpha blend, applied **once** on the composed frame. Cursor position is mapped through source placements into scene coordinates. ### MfEncoder Receives only the final composed BGRA buffer. Source windows may resize during capture; content scales within its scene rect. The encoder is not recreated on source resize. --- ## End-to-end flow 1. **Resolve targets** — Windows: `EnumWindows` with filters; match by HWND, PID, or title substring. Monitors: `EnumDisplayMonitors`; match by HMONITOR from `wrec list --monitors`. Multiple targets become multiple `CaptureSource` instances. 2. **Capture** — WGC + D3D11 per source. Windows use `PrintWindow` when occluded (throttled). 3. **Synchronize** — Fixed FPS loop; poll hotkeys and stop requests between ticks. 4. **Compose** — CPU BGRA compositor writes one canvas-sized buffer per tick. Skips full compose when no source, cursor, or taskbar change since the last frame. 5. **Cursor** — Drawn on the composed buffer when enabled. 6. **Taskbar** — Optional fake Windows-style taskbar drawn after the cursor when enabled (window mode only). 7. **Encode** — Media Foundation H.264. Timestamps follow wall clock minus paused time, scaled by `--speed`. --- ## Performance Recording is CPU-bound (BGRA capture → compose → software H.264). The pipeline avoids unnecessary work: - **Compose skip** — When every source generation, cursor state, and taskbar overlay are unchanged, the previous composed frame is re-encoded (static scenes cost far less). - **Fast blit** — Full-canvas and tile 1:1 layouts use row `memcpy` instead of per-pixel scaling. - **Occlusion cache** — `isWindowOccluded` is polled on an interval, not every frame. - **Buffer reuse** — WGC GPU→CPU copies swap into a persistent buffer instead of allocating each frame. - **Verbose timing** — With `-v`, logs rolling averages every 300 frames (`poll`, `compose`, `cursor`, `encode`, `skip`, etc.). --- ## GUI vs CLI Both paths call the same `RecorderManager`. The CLI runs it on the main thread and polls hotkeys from a thread message queue. The GUI runs it on a worker thread; hotkeys register on the main window and actions forward through an atomic flag. Graceful shutdown (close window, Ctrl+C, console close) sets `stopRequested`; the manager enters a stopping state, finalizes the encoder if it was opened, then exits. --- ## Limitations - **No audio** — video only - **Minimized windows** — may produce zero-size frames and fail - **Unfocused apps** — some pause rendering when not visible (games, Page Visibility API) - **Software encode path** — CPU BGRA → Media Foundation (no GPU encode pipeline yet) - **Title matching** — each `-t` must match exactly one window - **Custom layout** — CLI only; requires `--canvas` - **Focus layout** — window mode only; switches when a selected window becomes foreground - **Taskbar overlay** — window mode only (disabled for monitor capture) - **Z-order** — source list order; last source wins for cursor hit-testing - **H.264** — canvas width and height are rounded down to even values - **Closed window** — placeholder in that rect; recording continues