Files
wl-webrtc/AGENTS.md
T
dailz fed8c2dcfd
CI / Build + Clippy + Test (pull_request) Failing after 30s
CI / Security audit (RUSTSEC) (pull_request) Failing after 30s
docs(avhw): fix misleading Send soundness reasoning
Oracle audit of all 5 `unsafe impl Send` in src/avhw/ found soundness
intact but reasoning wrong in 3 of 5:

- AvHwDevCtx: claimed '&mut self ensures exclusive access' — false,
  ref_clone() hands raw pointers to other threads / FFmpeg-internal
  codec workers. Real basis is AVBufferRef atomic_uint refcount +
  libva VADisplay thread safety.
- AvHwFrameCtx: claimed 'send/receive pattern is thread-safe' —
  misdirection. Real basis is AVBufferPool atomic get/put.
- EncState: claimed 'raw pointers not shared across threads' — false
  when FFmpeg frame/slice threading is enabled. Real basis is the
  hw device/frames contexts being designed for such sharing.

SwEncState and SwEncEncode comments were acceptable; improved for
clarity (note that contained FFmpeg handles are non-thread-safe but
Send-sound under exclusive access, and that crossbeam/Arc fields are
already Send by design).

Added module-level convention doc to src/avhw/mod.rs centralizing
the C-API-level justification rule and explicitly calling out the
'&mut self as Send basis' anti-pattern so future contributors don't
repeat the category error.

Fixed AGENTS.md:
- Stale claim that Cargo.toml 'only warns' on undocumented_unsafe_blocks
  (it's been 'deny' for a while)
- Stale path src/avhw.rs → src/avhw/ (split in d53e881)
- Stale 'avoid moving wrappers across threads' guidance — Send is sound,
  the audit just confirmed why

No code behavior change. Verified: cargo build --release,
cargo clippy --release --all-targets (0 warnings),
cargo test --release (79 unit + 3 integration, 1 ignored).
2026-07-09 15:20:16 +08:00

4.1 KiB

AGENTS.md

Sources of truth

  • Trust current Rust source, Cargo.toml, shell.nix, and tests over docs/superpowers/* or analysis.md; those docs contain historical/aspirational modules that are not in the tree.
  • Crate edition is 2021, not the default Rust 2024. The package exposes a library, three binaries (wl-webrtc, vaapi_import_bench, sw_encode_bench), and two examples (list_globals, test_portal).

Setup and build

  • Native prerequisites are FFmpeg 6+ dev libs with VAAPI, Wayland protocols/libs, libdrm, PipeWire, and libclang. shell.nix provides FFmpeg/Wayland/libdrm/Mesa/libva/clang and LIBCLANG_PATH, but does not currently list PipeWire.
  • Normal build: cargo build. Release binary required by README and integration tests: cargo build --release.
  • Cargo.toml sets clippy::undocumented_unsafe_blocks = "deny"; every unsafe block and unsafe impl must carry a // SAFETY: comment or the build fails. For unsafe impl Send on FFmpeg wrappers, see the convention in src/avhw/mod.rs — justification must be at the C-API level (atomic refcounts, libva VADisplay thread safety), not Rust borrow level.

Testing and verification

  • Unit/focused tests can run with filters, e.g. cargo test transform, cargo test fps_limit, cargo test backend_detect.
  • Full cargo test includes tests/integration_test.rs, which shells out to target/release/wl-webrtc; run cargo build --release first or those tests fail before reaching code behavior.
  • Hardware/live tests are marked ignored; run them only on a Wayland session with VAAPI-capable GPU and writable output: cargo test -- --ignored.
  • CLI smoke test surface: target/release/wl-webrtc --help and invalid-argument rejection. Real capture needs Wayland plus either wlr-screencopy or XDG Portal/PipeWire.
  • The README CLI table is stale for --backend and --no-persist; src/args.rs is authoritative for flags.

Runtime architecture

  • src/main.rs is the real entrypoint: parse Args, initialize tracing from RUST_LOG or -v, reject non-H.264, require --output or --port, detect backend, then run one of two loops.
  • Backend detection in src/backend_detect.rs: explicit --backend portal|screencopy wins; otherwise wlr-screencopy is preferred when the Wayland global zwlr_screencopy_manager_v1 exists, else Portal/PipeWire is used if D-Bus ScreenCast is available.
  • Do not use ashpd for backend availability checks; backend_detect.rs intentionally uses raw zbus because ashpd caches a zbus::Connection in a global and can hang after its owning Tokio runtime is dropped.
  • src/state.rs drives the wlroots path using a mio Wayland fd loop and State<CapWlrScreencopy>; src/state_portal.rs drives the Portal/PipeWire path through CapPortal frame channels.
  • src/webrtc.rs is a small embedded HTTP/WebRTC signaling server using str0m; --port 0 means file-output mode, --port > 0 enables WebRTC mode.

Unsafe and FFI work

  • FFmpeg/VAAPI/PipeWire code relies on raw FFI and many unsafe blocks. Preserve nearby // SAFETY: explanations and add one for any new unsafe block.
  • src/avhw/ (split from the former src/avhw.rs in commit d53e881) owns FFmpeg AVBufferRef / frame / codec contexts. Five types (AvHwDevCtx, AvHwFrameCtx, EncState, SwEncState, SwEncEncode) carry unsafe impl Send; soundness was Oracle-audited on 2026-07-09 against FFmpeg/libva threading semantics. Moving them across threads is sound because the C APIs use atomic refcounts, not because of any Rust-side exclusivity — see src/avhw/mod.rs for the full convention.
  • CapPortal stores the portal restore token under the user cache directory (wl-webrtc/portal-restore-token); use --no-persist when manually testing fresh authorization behavior.

Useful manual commands

  • List Wayland globals: cargo run --example list_globals.
  • Portal permission smoke test: cargo run --example test_portal.
  • Portal/VAAPI benchmarks require a screen-share dialog and hardware: cargo run --bin vaapi_import_bench -- --output /tmp/vaapi_bench.mp4 and cargo run --bin sw_encode_bench -- --output /tmp/bench_test.mp4.