refactor: decompose oversized modules into directory form (avhw + state + cap_portal + state_portal + webrtc + bench bins) #26

Merged
dailz merged 16 commits from refactor/split-avhw into master 2026-07-14 11:44:56 +08:00
6 changed files with 14 additions and 26 deletions
Showing only changes of commit 633247201c - Show all commits
+1 -1
View File
@@ -173,7 +173,7 @@ impl SwEncEncode {
0, 0,
self.enc_height as i32, self.enc_height as i32,
(*self.yuv_frame).data.as_ptr() as *mut *mut u8, (*self.yuv_frame).data.as_ptr() as *mut *mut u8,
(*self.yuv_frame).linesize.as_ptr() as *const i32, (*self.yuv_frame).linesize.as_ptr(),
); );
if scaled < 0 { if scaled < 0 {
bail!("sws_scale failed for software encoder: {scaled}"); bail!("sws_scale failed for software encoder: {scaled}");
+4
View File
@@ -17,6 +17,10 @@ pub struct EncState {
enc_video: ff::codec::encoder::video::Video, enc_video: ff::codec::encoder::video::Video,
frames_rgb: AvHwFrameCtx, frames_rgb: AvHwFrameCtx,
video_filter: ff::filter::Graph, video_filter: ff::filter::Graph,
// Root AVHWDeviceContext, kept for ownership. Each consumer (encoder,
// filter graph, frames ctx) already holds its own ref_clone(); this
// field is never read after `new()` but must outlive those clones.
#[allow(dead_code)]
hw_device_ctx: AvHwDevCtx, hw_device_ctx: AvHwDevCtx,
octx: ff::format::context::Output, octx: ff::format::context::Output,
starting_timestamp: Option<i64>, starting_timestamp: Option<i64>,
+4 -4
View File
@@ -587,11 +587,11 @@ fn run_cpu_pipeline(
ffi::sws_scale( ffi::sws_scale(
sws_ctx.0, sws_ctx.0,
(*sw_frame).data.as_ptr() as *const *const u8, (*sw_frame).data.as_ptr() as *const *const u8,
(*sw_frame).linesize.as_ptr() as *const i32, (*sw_frame).linesize.as_ptr(),
0, 0,
(*sw_frame).height, (*sw_frame).height,
(*encoder.yuv_frame).data.as_ptr() as *mut *mut u8, (*encoder.yuv_frame).data.as_ptr() as *mut *mut u8,
(*encoder.yuv_frame).linesize.as_ptr() as *const i32, (*encoder.yuv_frame).linesize.as_ptr(),
); );
} }
let scale_us = t_scale.elapsed().as_micros() as u64; let scale_us = t_scale.elapsed().as_micros() as u64;
@@ -744,11 +744,11 @@ fn run_gpu_pipeline(
ffi::sws_scale( ffi::sws_scale(
format_ctx.0, format_ctx.0,
(*sw_nv12).data.as_ptr() as *const *const u8, (*sw_nv12).data.as_ptr() as *const *const u8,
(*sw_nv12).linesize.as_ptr() as *const i32, (*sw_nv12).linesize.as_ptr(),
0, 0,
(*sw_nv12).height, (*sw_nv12).height,
(*encoder.yuv_frame).data.as_ptr() as *mut *mut u8, (*encoder.yuv_frame).data.as_ptr() as *mut *mut u8,
(*encoder.yuv_frame).linesize.as_ptr() as *const i32, (*encoder.yuv_frame).linesize.as_ptr(),
); );
} }
let format_us = t_format.elapsed().as_micros() as u64; let format_us = t_format.elapsed().as_micros() as u64;
+4 -12
View File
@@ -139,6 +139,10 @@ pub struct CapPortal {
frame_rx: Receiver<PwDmaBufFrame>, frame_rx: Receiver<PwDmaBufFrame>,
event_rx: Receiver<PwCtrlEvent>, event_rx: Receiver<PwCtrlEvent>,
pw_thread: Option<JoinHandle<()>>, pw_thread: Option<JoinHandle<()>>,
// Kept alive for CapPortal's whole lifetime: ashpd caches a zbus::Connection
// in a process-global OnceCell and hangs if the owning runtime drops first
// (see AGENTS.md). Never read after `new()`; only its Drop ordering matters.
#[allow(dead_code)]
rt: Runtime, rt: Runtime,
pw_dropped: Arc<AtomicU64>, pw_dropped: Arc<AtomicU64>,
} }
@@ -154,7 +158,6 @@ struct PwThreadCtx {
shutdown_read: OwnedFd, shutdown_read: OwnedFd,
pw_fd: OwnedFd, pw_fd: OwnedFd,
node_id: u32, node_id: u32,
fps: u32,
} }
impl CapPortal { impl CapPortal {
@@ -209,7 +212,6 @@ impl CapPortal {
shutdown_read: unsafe { OwnedFd::from_raw_fd(efd) }, shutdown_read: unsafe { OwnedFd::from_raw_fd(efd) },
pw_fd, pw_fd,
node_id, node_id,
fps: args.fps,
}; };
let pw_thread = thread::Builder::new() let pw_thread = thread::Builder::new()
@@ -697,7 +699,6 @@ fn pipewire_thread(ctx: PwThreadCtx) {
shutdown_read, shutdown_read,
pw_fd, pw_fd,
node_id, node_id,
fps: _,
} = ctx; } = ctx;
let mainloop = match pw::main_loop::MainLoopBox::new(None) { let mainloop = match pw::main_loop::MainLoopBox::new(None) {
@@ -1070,15 +1071,6 @@ fn pipewire_thread(ctx: PwThreadCtx) {
// PipeWire global state is intentionally not deinitialized here — see pw::init() comment above. // PipeWire global state is intentionally not deinitialized here — see pw::init() comment above.
} }
/// 将四个 ASCII 字符编码为 32 位 FourCC (Four Character Code) 标识符
///
/// FourCC 是多媒体领域中广泛使用的像素格式标识方式。
/// 编码规则: 第一个字符在最低 8 位,依次向高位排列。
/// 例如: "BGRA" → 0x41524742 (小端序存储为 'B','G','R','A')
const fn fourcc(a: u8, b: u8, c: u8, d: u8) -> u32 {
(a as u32) | ((b as u32) << 8) | ((c as u32) << 16) | ((d as u32) << 24)
}
/// 将 PipeWire SPA 视频格式转换为 DRM FourCC 格式 /// 将 PipeWire SPA 视频格式转换为 DRM FourCC 格式
/// ///
/// PipeWire 使用自己的 VideoFormat 枚举,而 DRM/KMS 使用 FourCC 格式标识。 /// PipeWire 使用自己的 VideoFormat 枚举,而 DRM/KMS 使用 FourCC 格式标识。
-9
View File
@@ -77,8 +77,6 @@ pub trait CaptureSource: Sized + 'static {
pub struct OutputInfo { pub struct OutputInfo {
pub name: String, pub name: String,
pub transform: Transform, pub transform: Transform,
pub physical_size: (i32, i32),
pub logical_position: (i32, i32),
} }
#[derive(Default)] #[derive(Default)]
@@ -174,7 +172,6 @@ pub(crate) enum EncConstructionStage<S: CaptureSource> {
dmabuf: ZwpLinuxDmabufV1, dmabuf: ZwpLinuxDmabufV1,
}, },
Streaming { Streaming {
output_info: OutputInfo,
output: WlOutput, output: WlOutput,
enc: StreamingEncoder, enc: StreamingEncoder,
cap: S, cap: S,
@@ -209,7 +206,6 @@ pub enum InFlightSurface<S: CaptureSource> {
pub struct State<S: CaptureSource> { pub struct State<S: CaptureSource> {
pub(crate) stage: EncConstructionStage<S>, pub(crate) stage: EncConstructionStage<S>,
pub in_flight_surface: InFlightSurface<S>, pub in_flight_surface: InFlightSurface<S>,
pub starting_timestamp: Option<i64>,
pub stats_start_time: Option<Instant>, pub stats_start_time: Option<Instant>,
pub stats_last_time: Option<Instant>, pub stats_last_time: Option<Instant>,
pub stats_frames: u64, pub stats_frames: u64,
@@ -302,7 +298,6 @@ impl<S: CaptureSource> State<S> {
wlr_head_proxy_to_name: HashMap::new(), wlr_head_proxy_to_name: HashMap::new(),
}, },
in_flight_surface: InFlightSurface::None, in_flight_surface: InFlightSurface::None,
starting_timestamp: None,
stats_start_time: None, stats_start_time: None,
stats_last_time: None, stats_last_time: None,
stats_frames: 0, stats_frames: 0,
@@ -479,7 +474,6 @@ impl<S: CaptureSource> State<S> {
pub fn on_frame_allocd(&mut self, frame: S::Frame, format: u32, width: u32, height: u32) { pub fn on_frame_allocd(&mut self, frame: S::Frame, format: u32, width: u32, height: u32) {
let (frames_rgb_ctx, dmabuf, cap) = match &mut self.stage { let (frames_rgb_ctx, dmabuf, cap) = match &mut self.stage {
EncConstructionStage::Streaming { EncConstructionStage::Streaming {
output_info: _,
output: _, output: _,
enc, enc,
dmabuf, dmabuf,
@@ -829,7 +823,6 @@ impl<S: CaptureSource> State<S> {
bitrate bitrate
); );
self.stage = EncConstructionStage::Streaming { self.stage = EncConstructionStage::Streaming {
output_info,
output, output,
enc, enc,
cap, cap,
@@ -985,8 +978,6 @@ impl<S: CaptureSource> State<S> {
.or(info.wl_name.clone()) .or(info.wl_name.clone())
.unwrap_or_else(|| format!("output-{}", output_names[target_idx])), .unwrap_or_else(|| format!("output-{}", output_names[target_idx])),
transform: info.transform.unwrap(), transform: info.transform.unwrap(),
physical_size: info.physical_size.unwrap(),
logical_position: info.logical_position.unwrap_or((0, 0)),
}; };
let output = bound_outputs[target_idx].clone(); let output = bound_outputs[target_idx].clone();
+1
View File
@@ -2,6 +2,7 @@
// AsRawFd is required by frame.fd.as_raw_fd() in build_drm_descriptor below // AsRawFd is required by frame.fd.as_raw_fd() in build_drm_descriptor below
// but rustc emits a false "unused_imports" warning because OwnedFd also has // but rustc emits a false "unused_imports" warning because OwnedFd also has
// an inherent as_raw_fd — same quirk as avhw.rs. E0599 if removed → keep it. // an inherent as_raw_fd — same quirk as avhw.rs. E0599 if removed → keep it.
#[allow(unused_imports)]
use std::os::fd::AsRawFd; use std::os::fd::AsRawFd;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};