fix(capture): stop stranding a PipeWire buffer on a caught panic; invalidate the PyroWave CSC on ring recreate
Two medium findings from the round-1 sweep. - The `.process` callback dequeued a buffer INSIDE its `catch_unwind`, and every requeue site was inside too. `newest` is a raw pointer with no Drop, so any caught panic (update_cursor_meta / consume_frame) unwound past all three requeues and permanently stranded that buffer. Once the stream's fixed pool drained, `dequeue_raw_buffer` returned null every call and capture silently wedged while still reporting negotiated/active — defeating the very catch_unwind that was meant to keep a panic survivable. The drain loop now runs OUTSIDE the catch (dequeue/queue are non-panicking C FFI pointer ops) and `newest` is requeued exactly once after it, on every path: normal, corrupted-skip, or caught panic. - `recreate_ring` invalidated `video_conv` and `hdr_p010_conv` but not `pyro_conv`. That converter is mode-baked — BgraToYuvPlanes selects entirely different shaders and output formats for SDR (8-bit BT.709 → R8/R8G8) vs HDR (scRGB→PQ BT.2020 → R16/R16G16) — and `ensure_pyro_conv` only builds when None, so a display_hdr flip reused the stale SDR converter against a freshly HDR-formatted pyro ring, corrupting every frame. Reachable at the documented "Downgrade point D": a PyroWave session with client_10bit=true that opens on a box where HDR can't enable, then flips once the display comes up. Linux .21: pf-capture 1/0. Windows .173: `cargo check -p pf-capture` clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1341,6 +1341,12 @@ impl IddPushCapturer {
|
||||
self.out_ring.clear(); // the output format changed → rebuild lazily at the new format
|
||||
self.video_conv = None; // converters are sized + HDR-specific → rebuild at the new mode
|
||||
self.hdr_p010_conv = None;
|
||||
// The PyroWave CSC is mode-baked too (BgraToYuvPlanes picks different SDR vs HDR shaders
|
||||
// and R8/R8G8 vs R16/R16G16 outputs). Without this, a display_hdr flip (Downgrade point D:
|
||||
// client_10bit=true but HDR couldn't enable at open) reused the stale SDR converter against
|
||||
// the freshly HDR-formatted pyro ring — every frame corrupted. `ensure_pyro_conv` only
|
||||
// builds when None, so it must be reset here like its siblings.
|
||||
self.pyro_conv = None;
|
||||
self.pyro_ring.clear(); // PyroWave two-plane ring is sized → rebuild at the new mode
|
||||
self.pyro_last = None;
|
||||
self.out_idx = 0;
|
||||
|
||||
Reference in New Issue
Block a user