moq_transcode/config.rs
1//! Transcoder configuration: the rung ladder and catalog wiring.
2
3use moq_net::{AsPath, PathRelativeOwned};
4
5use crate::Ladder;
6
7#[doc(hidden)]
8#[deprecated(note = "use moq_net::Path::relative")]
9pub fn source_reference(source: impl AsPath, output: impl AsPath) -> Option<PathRelativeOwned> {
10 let source = source.as_path();
11 let output = output.as_path();
12 if output.strip_prefix(&source)?.is_empty() {
13 return None;
14 }
15
16 source.relative(&output)
17}
18
19/// Transcoder configuration for [`run`](crate::run).
20///
21/// `#[non_exhaustive]`: build via `Config::default()` and set fields, so future
22/// knobs don't break callers.
23#[derive(Clone, Debug, Default)]
24#[non_exhaustive]
25pub struct Config {
26 /// Candidate output renditions, lowest first. Only rungs strictly below the
27 /// source survive: a rung is dropped when its height exceeds the source, when
28 /// its bitrate is not below the source bitrate (when known), or when it
29 /// matches the source height without a known source bitrate to undercut. A
30 /// 480p source is never transcoded up to 720p.
31 ///
32 /// Filtering drops rungs but never reorders them, so the surviving ladder is
33 /// still ascending. Build it with [`Ladder::new`](crate::Ladder::new), which
34 /// takes the rungs in any order and refuses an ambiguous ladder.
35 pub ladder: Ladder,
36
37 /// Where the source broadcast lives relative to the output broadcast, e.g.
38 /// `"."` when the output is published at `<source>/transcode.hang`. When
39 /// set, the derivative catalog references the source renditions (all video
40 /// and audio) through this path so players fetch them from the source
41 /// directly; the transcoder never proxies or subscribes them. `None` omits
42 /// them from the derivative catalog.
43 pub source: Option<PathRelativeOwned>,
44
45 /// Which video encoder implementation encodes the rungs. The default
46 /// prefers hardware (NVENC on Linux, VideoToolbox on macOS, Media
47 /// Foundation on Windows) and falls back to openh264.
48 pub encoder: moq_video::encode::Kind,
49
50 /// Which video decoder implementation decodes the source. The default
51 /// prefers hardware and falls back to openh264 (H.264 only; H.265 sources
52 /// need a hardware decoder).
53 pub decoder: moq_video::decode::Kind,
54
55 /// Frame resize behavior. Automatic mode keeps GPU-backed frames on the GPU.
56 pub resize: moq_video::resize::Config,
57}
58
59#[cfg(test)]
60#[allow(deprecated)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn source_reference_normalizes_and_counts_output_depth() {
66 assert_eq!(source_reference("a/b", "a/b/transcode.hang").unwrap().as_str(), ".");
67 assert_eq!(source_reference("/a//b/", "a/b/dir/").unwrap().as_str(), ".");
68 assert_eq!(
69 source_reference("a/b", "a/b/dir/transcode.hang").unwrap().as_str(),
70 ".."
71 );
72 assert_eq!(
73 source_reference("a/b", "a/b/one/two/transcode.hang").unwrap().as_str(),
74 "../.."
75 );
76 assert!(source_reference("a/b", "other/transcode.hang").is_none());
77 assert!(source_reference("a/b", "a/b").is_none());
78 }
79}