Files
pixelpass/src/host/capture.rs
T
molluskandClaude Opus 4.7 7483b9aae8 feat(quality): resolution/quality presets + Auto from pre-flight
Add a host-global quality knob (Discord-style) so the sharer can trade
resolution + bitrate for upload bandwidth. Quality is host-global by
design: one encode pipeline fans out to every viewer, so per-viewer
quality is out of scope (it would kill the broadcast fanout).

- New `--quality source|high|medium|low|auto` (ValueEnum) bundling a
  (max-height, bitrate, fps) tuple per preset; `auto` derives the preset
  from the saved bandwidth pre-flight (safe_mbps / viewer cap), falling
  back to `medium` when unmeasured. Default is auto; the interactive
  Host branch shows a picker when --quality is omitted (mirrors pick_app).
- `--max-height N` raw override; `--bitrate`/`--framerate` changed to
  Option so an explicit flag overrides just that field of the preset
  (precedence rule), leaving the rest of the preset intact.
- host/quality.rs: Preset table + resolve(); pure resolve_auto() split
  from the config read for testability. 5 unit tests lock preset
  pass-through, the Auto ladder, the unmeasured fallback, and override
  precedence.
- pipeline::build_args inserts `videoscale ! video/x-raw,height=N,
  pixel-aspect-ratio=1/1,width=[2,8192,2]` only for non-Source presets.
  PAR 1/1 forces a proportional downscale (without it videoscale keeps
  full width and squashes PAR — no bandwidth win); the even-stepped width
  range + even-rounded height satisfy H.264 4:2:0. EffectiveQuality is
  threaded capture -> wayland/x11 -> pipeline; max_viewers is now sized
  against the effective (post-preset) bitrate.
- Banner gains a quality line (preset label + ≤Np/kbps/fps + provenance).
- deps.rs checks `videoscale`; smoke-pipeline.sh adds a 1080->480
  downscale check asserting an even width below source.
- README: --quality preset table, Auto behavior, host-global note,
  --max-height/--bitrate/--framerate override precedence.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 15:03:14 -04:00

26 lines
914 B
Rust

//! Capture dispatcher. Picks the per-display-server source backend and returns
//! the shared [`pipeline::CaptureHandle`]. The handle itself, its teardown, and
//! the whole encode/serve tail are display-agnostic and live in
//! [`super::pipeline`]; the backends differ only in how they obtain a video
//! source element.
use anyhow::Result;
use crate::cli::HostOpts;
use crate::common::display::DisplayServer;
use crate::host::pipeline::CaptureHandle;
use crate::host::quality::EffectiveQuality;
use crate::host::{wayland, x11};
pub async fn spawn(
display: DisplayServer,
opts: &HostOpts,
quality: &EffectiveQuality,
) -> Result<CaptureHandle> {
match display {
DisplayServer::Wayland => wayland::start(opts, quality).await,
DisplayServer::X11 => x11::start(opts, quality).await,
DisplayServer::Unknown => unreachable!("caller guarantees display != Unknown"),
}
}