Commit Graph

21 Commits

Author SHA1 Message Date
dailz
ffb36b7e0d fix(portal): convert PipeWire nanosecond PTS to encoder frame-number units
PipeWire spa_meta_header.pts is CLOCK_MONOTONIC in nanoseconds, but the
encoder expects frame-number units (time_base = 1/fps). The raw nanosecond
value was assigned directly to AVFrame.pts, causing the encoder/muxer to
interpret timestamps as billions of frames, producing corrupted duration
metadata and broken rate control.

Fix: record the first frame's PTS as a nanosecond base, compute elapsed
nanoseconds for each subsequent frame, then convert to frame numbers via
elapsed_ns * fps / 1_000_000_000. Using elapsed time avoids i64 overflow
on absolute timestamps (~10^18 ns).

Matches the WLR path pattern (state.rs:525-527) which converts microseconds
to frame numbers for the same encoder.
2026-05-22 13:05:53 +08:00
dailz
75a57e43ec docs: mark bug #2 as fixed in BUGS.md (a09a423) 2026-05-22 11:42:56 +08:00
dailz
a09a4235d3 fix(portal): replace blocking send with try_send in PW process callback
PipeWire .process callback called frame_tx.send() on a bounded(3)
channel. If the encoder stalled, this blocked the PipeWire data loop,
delaying buffer recycling and potentially causing XRUNs.

Replace with try_send + AtomicU64 drop counter. Frames are silently
dropped when the channel is full (preferred for screen capture: latest
frame wins). A warning is logged every 30 dropped frames.

Fixes #2 from BUGS.md.
2026-05-22 11:42:42 +08:00
dailz
1f286b2a5d docs(BUGS): mark #1 PipeWire mainloop UAF as fixed (e40ef9e) 2026-05-22 11:31:07 +08:00
dailz
e40ef9eba2 fix(cap_portal): eliminate PipeWire mainloop UAF by replacing detached helper thread with eventfd + loop-integrated add_io
The detached helper thread that called pw_main_loop_quit() through a raw
pointer cast to usize could outlive the mainloop if run() returned on its
own (event loop error, panic in callback, etc.), causing use-after-free.

Replace with an eventfd registered on the PipeWire loop via add_io(). The
shutdown callback runs on the loop thread during mainloop.run(), where the
mainloop is guaranteed alive. Drop order (reverse declaration) ensures the
IO source is unregistered before mainloop is destroyed.

Fixes: #1 (Critical UAF)
2026-05-22 11:30:12 +08:00
dailz
d7fbb5256c feat: add KWin/KDE Plasma screen capture via xdg-desktop-portal ScreenCast + PipeWire
Add a second capture backend for compositors without wlr-screencopy
(KWin, GNOME, etc.) using the xdg-desktop-portal ScreenCast interface
and PipeWire DMA-BUF streaming.

New files:
- src/backend_detect.rs: auto-detect wlr-screencopy vs portal backend
- src/cap_portal.rs: Portal session setup + PipeWire DMA-BUF thread
- src/state_portal.rs: StatePortal encoder pipeline (DMA-BUF → VAAPI)

Changes:
- Cargo.toml: add ashpd 0.13, tokio 1, pipewire 0.9, libspa 0.9,
  crossbeam-channel 0.5
- src/args.rs: add --backend CLI flag
- src/avhw.rs: extract create_encoder() from inline State code
- src/main.rs: route to portal or wlr-screencopy based on backend
- src/state.rs: fix params.destroy() on dup failure, cleanup
  in_flight_surface on copy fail, use create_encoder()
- tests/integration_test.rs: add --backend flag tests
2026-05-11 08:49:08 +08:00
dailz
2972216a02 fix(avhw): specify format=nv12 output for scale_vaapi filter
scale_vaapi defaults to the input sw_format (RGBZ) when no output format
is specified. h264_vaapi encoder only supports NV12/YUV formats.
Adding format=nv12 ensures the filter outputs the correct color format
for hardware encoding.
2026-04-15 15:01:06 +08:00
dailz
1065364261 fix(avhw): add missing mut on video_filter for buffersink access 2026-04-15 14:41:58 +08:00
dailz
833cbdfed3 chore(avhw): clean up debug tracing in VA-API pipeline 2026-04-15 14:01:22 +08:00
dailz
c77838235a fix(avhw): derive encoder hw_frames_ctx from filter graph buffersink 2026-04-15 13:57:34 +08:00
dailz
10ee190fd2 fix(state): do not destroy screencopy proxy on SHM buffer event 2026-04-15 07:15:46 +08:00
dailz
68514bd3f6 fix(state): do not set errored on SHM buffer event
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-15 07:12:33 +08:00
dailz
506e5ea30e fix(state,avhw): bind initial globals manually + fix filter graph crash on niri
- registry_queue_init consumes registry events during its internal
  roundtrip without forwarding them to Dispatch<WlRegistry>. Added
  bind_initial_globals() to manually iterate GlobalList and bind all
  initial globals (wl_output, xdg_output_manager, dmabuf, screencopy,
  wlr_output_manager) at State::new time.
- Fix av_freep segfault in build_filter_graph: av_buffersrc_parameters_alloc
  returns a plain pointer, use av_free instead of av_freep (which expects
  pointer-to-pointer).
- Fix filter graph format negotiation: remove software format filter that
  broke scale_vaapi hardware pipeline. Chain is now src -> scale -> sink.
- Downgrade repeat_pps error to warning (not available in FFmpeg 6.x).
2026-04-14 20:42:05 +08:00
dailz
b2e5f37cf6 feat(state): support compositors without xdg-output via wlr-output-management
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-14 17:52:59 +08:00
dailz
ecd78492ee feat(avhw): integrate transform into VA-API filter graph
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-14 17:02:54 +08:00
dailz
e89689634d fix(state): handle BufferParamsEvent::Failed to prevent silent hang
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-14 16:50:48 +08:00
dailz
6835f1f6cd fix(main): call fps_limit.flush() before encoder flush on shutdown
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-14 16:45:47 +08:00
dailz
3a954dae1a fix: resolve 4 audit bugs (PTS, WlOutput, first_frame, DRM minor) 2026-04-06 16:25:02 +08:00
dailz
27aa8d2c65 fix: convert PTS from from frame号单位转换 2026-04-06 16:23:59 +08:00
dailz
1e8d00126b fix(bsf): remove non-functional BSF pipeline, use encoder repeat_pps option 2026-04-06 09:35:37 +08:00
dailz
6d49222de8 feat: Phase 1 MVP with audit fixes — Wayland screen capture + VAAPI encoding
Phase 1 MVP implementation of wl-webrtc: Wayland screen capture tool
with hardware-accelerated VAAPI H.264 encoding and WebTransport output.

Includes all 9 runtime bug fixes from code audit (fix-audit-issues plan):

CRITICAL:
- C2: h264_metadata BSF with repeat_sps/repeat_pps in encode pipeline
- C4: FpsLimit wired as timing gate in on_copy_complete

HIGH:
- C3+A2: DRM device discovery via dmabuf feedback MainDevice event,
  unified resolve_drm_path() helper (CLI > compositor > auto > fallback)
- H2: Separate physical_size (mm) from mode_size (pixels) in wl_output
- H1+A3: Multi-output warning + named-output-not-found error

MEDIUM:
- M5: tv_sec u32->u64 to avoid Y2106 timestamp truncation
- M4: Guard against SHM Buffer event (DMA-BUF only)

Key components:
- src/avhw.rs: FFmpeg VAAPI encoder + filter graph + BSF pipeline
- src/state.rs: Wayland event loop + output negotiation + screencopy
- src/cap_wlr_screencopy.rs: wlr-screencopy capture source
- src/fps_limit.rs: Frame rate limiting with configurable target
- src/transform.rs: Frame format conversion utilities
2026-04-05 23:35:00 +08:00