diff --git a/src/avhw.rs b/src/avhw.rs index 722c087..7e6a35e 100644 --- a/src/avhw.rs +++ b/src/avhw.rs @@ -391,8 +391,6 @@ impl EncState { &frames_rgb, width, height, - enc_width, - enc_height, fps, transform, )?; @@ -2005,8 +2003,6 @@ fn build_filter_graph( frames_rgb: &AvHwFrameCtx, width: u32, height: u32, - _enc_width: u32, - _enc_height: u32, fps: u32, transform: Transform, ) -> Result { diff --git a/src/state.rs b/src/state.rs index eafcf53..fc00bf6 100644 --- a/src/state.rs +++ b/src/state.rs @@ -193,7 +193,10 @@ pub enum InFlightSurface { AllocQueued, CopyQueued { surface: ff::frame::Video, - drm_map: ff::ffi::AVDRMFrameDescriptor, + // Boxed: AVDRMFrameDescriptor is ~592 bytes (4 objects + 4 layers), + // which would balloon every InFlightSurface variant via enum alignment. + // The box shrinks the enum to ~32 bytes regardless of variant. + drm_map: Box, frame: S::Frame, buffer: WlBuffer, }, @@ -568,7 +571,7 @@ impl State { ); self.in_flight_surface = InFlightSurface::CopyQueued { surface, - drm_map: desc, + drm_map: Box::new(desc), frame, buffer: wl_buffer, }; diff --git a/src/state_portal.rs b/src/state_portal.rs index 2556cd1..a2678b5 100644 --- a/src/state_portal.rs +++ b/src/state_portal.rs @@ -42,6 +42,26 @@ struct WebrtcThread { sent_gap_rx: crossbeam_channel::Receiver<(f64, Option)>, } +/// Static configuration handed to the WebRTC sender thread. Immutable for the +/// thread's lifetime; a resolution tier change rebuilds the whole pipeline +/// (and spawns a new thread) rather than mutating this. +struct WebRtcThreadConfig { + fps: u32, + enc_width: u32, + enc_height: u32, + max_bitrate: u64, +} + +/// Channel endpoints owned exclusively by the WebRTC sender thread after spawn. +/// The reverse endpoints stay with StatePortal (or the encode thread) for +/// inbound/outbound traffic. +struct WebRtcThreadChannels { + webrtc_rx: crossbeam_channel::Receiver, + sent_gap_tx: crossbeam_channel::Sender<(f64, Option)>, + bitrate_tx: crossbeam_channel::Sender, + resolution_tx: crossbeam_channel::Sender, +} + /// 门户模式的主状态机 /// /// 负责管理从 PipeWire 采集屏幕帧、通过 VAAPI 硬件编码的完整生命周期。 @@ -288,15 +308,19 @@ impl StatePortal { .spawn(move || { webrtc_thread_loop( wrtc, - webrtc_rx, - fps, - enc_width, - enc_height, - max_bitrate, + WebRtcThreadConfig { + fps, + enc_width, + enc_height, + max_bitrate, + }, + WebRtcThreadChannels { + webrtc_rx, + sent_gap_tx, + bitrate_tx, + resolution_tx, + }, paused, - sent_gap_tx, - bitrate_tx, - resolution_tx, ) })?; self.webrtc_thread = Some(WebrtcThread { @@ -695,16 +719,22 @@ fn encode_thread_loop( fn webrtc_thread_loop( mut wrtc: WebRtcState, - webrtc_rx: crossbeam_channel::Receiver, - fps: u32, - enc_width: u32, - enc_height: u32, - max_bitrate: u64, + config: WebRtcThreadConfig, + channels: WebRtcThreadChannels, paused: Arc, - sent_gap_tx: crossbeam_channel::Sender<(f64, Option)>, - bitrate_tx: crossbeam_channel::Sender, - resolution_tx: crossbeam_channel::Sender, ) { + let WebRtcThreadConfig { + fps, + enc_width, + enc_height, + max_bitrate, + } = config; + let WebRtcThreadChannels { + webrtc_rx, + sent_gap_tx, + bitrate_tx, + resolution_tx, + } = channels; let mut frames_sent: u64 = 0; let mut last_send: Option = None; let mut last_sent_bitrate: Option = None;