Skip to main content

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}