moq_transcode/config.rs
1//! Transcoder configuration: the rung ladder and catalog wiring.
2
3use moq_net::PathRelativeOwned;
4
5/// One candidate output rendition: a target resolution (by height) and bitrate.
6///
7/// The width is derived from the source aspect ratio at runtime, and a rung is
8/// only offered when it is strictly below the source (see [`Config::rungs`]).
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10#[non_exhaustive]
11pub struct Rung {
12 /// Output height in pixels. Rounded down to even (I420 chroma is 2x2).
13 pub height: u32,
14
15 /// Target bitrate in bits per second: the CBR target and the bitrate
16 /// advertised in the derivative catalog.
17 pub bitrate: u64,
18}
19
20impl Rung {
21 /// A rung at `height` pixels and `bitrate` bits per second.
22 pub fn new(height: u32, bitrate: u64) -> Self {
23 Self { height, bitrate }
24 }
25}
26
27/// Transcoder configuration for [`run`](crate::run).
28///
29/// `#[non_exhaustive]`: build via `Config::default()` and set fields, so future
30/// knobs don't break callers.
31#[derive(Clone, Debug)]
32#[non_exhaustive]
33pub struct Config {
34 /// Candidate output renditions. Only rungs strictly below the source
35 /// survive: a rung is dropped when its height exceeds the source, when its
36 /// bitrate is not below the source bitrate (when known), or when it matches
37 /// the source height without a known source bitrate to undercut. A 480p
38 /// source is never transcoded up to 720p.
39 pub rungs: Vec<Rung>,
40
41 /// Where the source broadcast lives relative to the output broadcast, e.g.
42 /// `".."` when the output is published at `<source>/transcode.hang`. When
43 /// set, the derivative catalog references the source renditions (all video
44 /// and audio) through this path so players fetch them from the source
45 /// directly; the transcoder never proxies or subscribes them. `None` omits
46 /// them from the derivative catalog.
47 pub source: Option<PathRelativeOwned>,
48
49 /// Which video encoder implementation encodes the rungs. The default
50 /// prefers hardware (NVENC on Linux, VideoToolbox on macOS, Media
51 /// Foundation on Windows) and falls back to openh264.
52 pub encoder: moq_video::encode::Kind,
53
54 /// Which video decoder implementation decodes the source. The default
55 /// prefers hardware and falls back to openh264 (H.264 only; H.265 sources
56 /// need a hardware decoder).
57 pub decoder: moq_video::decode::Kind,
58}
59
60impl Default for Config {
61 fn default() -> Self {
62 Self {
63 // The default ladder, top rung first, filtered against the source at
64 // runtime so only strictly-lower renditions are offered.
65 rungs: vec![
66 Rung::new(1080, 5_000_000),
67 Rung::new(720, 2_500_000),
68 Rung::new(480, 1_200_000),
69 Rung::new(360, 600_000),
70 Rung::new(240, 350_000),
71 ],
72 source: None,
73 encoder: moq_video::encode::Kind::default(),
74 decoder: moq_video::decode::Kind::default(),
75 }
76 }
77}