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
98 lines
2.9 KiB
Rust
98 lines
2.9 KiB
Rust
use std::process::Command;
|
|
|
|
/// Helper: get the binary path. Uses the release build if available.
|
|
fn bin_path() -> &'static str {
|
|
"target/release/wl-webrtc"
|
|
}
|
|
|
|
#[test]
|
|
fn test_help_flag() {
|
|
let output = Command::new(bin_path())
|
|
.arg("--help")
|
|
.output()
|
|
.expect("failed to execute wl-webrtc --help");
|
|
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(output.status.success(), "--help should exit 0");
|
|
assert!(
|
|
stdout.contains("output"),
|
|
"help output should mention 'output'"
|
|
);
|
|
assert!(stdout.contains("fps"), "help output should mention 'fps'");
|
|
assert!(
|
|
stdout.contains("codec"),
|
|
"help output should mention 'codec'"
|
|
);
|
|
assert!(
|
|
stdout.contains("bitrate"),
|
|
"help output should mention 'bitrate'"
|
|
);
|
|
assert!(
|
|
stdout.contains("gop-size"),
|
|
"help output should mention 'gop-size'"
|
|
);
|
|
assert!(
|
|
stdout.contains("drm-device"),
|
|
"help output should mention 'drm-device'"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_rejects_invalid_args() {
|
|
let output = Command::new(bin_path())
|
|
.arg("--nonexistent-flag-xyz")
|
|
.output()
|
|
.expect("failed to execute wl-webrtc with invalid args");
|
|
|
|
assert!(!output.status.success(), "should reject unrecognized flag");
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
assert!(
|
|
stderr.to_lowercase().contains("error")
|
|
|| stderr.to_lowercase().contains("unexpected")
|
|
|| stderr.to_lowercase().contains("unrecognized"),
|
|
"stderr should mention the error, got: {stderr}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_rejects_hevc_codec() {
|
|
let output = Command::new(bin_path())
|
|
.arg("--output")
|
|
.arg("/dev/null")
|
|
.arg("--codec")
|
|
.arg("hevc")
|
|
.output()
|
|
.expect("failed to execute wl-webrtc --codec hevc");
|
|
|
|
// MVP only supports h264; hevc should be rejected.
|
|
assert!(!output.status.success(), "should reject hevc codec in MVP");
|
|
}
|
|
|
|
/// Tests requiring a live Wayland compositor and VAAPI hardware.
|
|
/// Run with: cargo test -- --ignored
|
|
#[test]
|
|
#[ignore]
|
|
fn test_capture_starts_with_valid_output() {
|
|
// This test requires:
|
|
// - A running Wayland compositor
|
|
// - VAAPI-compatible GPU hardware
|
|
// - A writable output path
|
|
let output = Command::new(bin_path())
|
|
.arg("--output")
|
|
.arg("/tmp/wl-webrtc-test-capture.mp4")
|
|
.arg("--fps")
|
|
.arg("10")
|
|
.output()
|
|
.expect("failed to start wl-webrtc");
|
|
|
|
// If we get here, the process ran and exited.
|
|
// In a real test, we'd give it time to capture a few frames
|
|
// and then send SIGINT, but for now just check it didn't
|
|
// immediately fail with an argument error.
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
assert!(
|
|
!stderr.contains("error: unexpected") && !stderr.contains("error: invalid"),
|
|
"should not have argument parsing errors, got: {stderr}"
|
|
);
|
|
}
|