Skip to main content

moq_mux/
error.rs

1/// Errors from moq-mux operations.
2///
3/// Most variants are delegations to underlying layers: [`moq_net::Error`] for
4/// transport / pub-sub failures, [`hang::Error`] for catalog/codec parsing, the
5/// per-format Errors for container shape problems, and the per-codec Errors for
6/// bitstream parsing problems.
7#[derive(Debug, Clone, thiserror::Error)]
8#[non_exhaustive]
9pub enum Error {
10	/// Error from the underlying moq-net transport.
11	#[error("moq: {0}")]
12	Moq(#[from] moq_net::Error),
13
14	/// Error from the hang catalog/codec layer.
15	#[error("hang: {0}")]
16	Hang(#[from] hang::Error),
17
18	/// Error publishing or consuming JSON over a track.
19	#[error("json: {0}")]
20	Json(#[from] moq_json::Error),
21
22	/// Error parsing or building CMAF moof+mdat fragments.
23	#[error("cmaf: {0}")]
24	Cmaf(#[from] crate::container::fmp4::Error),
25
26	/// Error parsing or building MKV / WebM streams.
27	#[error("mkv: {0}")]
28	Mkv(#[from] crate::container::mkv::Error),
29
30	/// Error decoding the MSF catalog.
31	#[error("msf: {0}")]
32	Msf(#[from] crate::catalog::msf::Error),
33
34	/// Error parsing or building LOC frames.
35	#[error("loc: {0}")]
36	Loc(#[from] moq_loc::Error),
37
38	/// Error parsing an Annex B NAL stream.
39	#[error("annexb: {0}")]
40	Annexb(#[from] crate::codec::annexb::Error),
41
42	/// Error parsing AAC.
43	#[error("aac: {0}")]
44	Aac(#[from] crate::codec::aac::Error),
45
46	/// Error parsing Opus.
47	#[error("opus: {0}")]
48	Opus(#[from] crate::codec::opus::Error),
49
50	/// Error parsing FLAC.
51	#[error("flac: {0}")]
52	Flac(#[from] crate::codec::flac::Error),
53
54	/// Error parsing MP3.
55	#[error("mp3: {0}")]
56	Mp3(#[from] crate::codec::mp3::Error),
57
58	/// Error parsing H.264.
59	#[error("h264: {0}")]
60	H264(#[from] crate::codec::h264::Error),
61
62	/// Error parsing H.265.
63	#[error("h265: {0}")]
64	H265(#[from] crate::codec::h265::Error),
65
66	/// Error parsing AV1.
67	#[error("av1: {0}")]
68	Av1(#[from] crate::codec::av1::Error),
69
70	/// Error parsing VP8.
71	#[error("vp8: {0}")]
72	Vp8(#[from] crate::codec::vp8::Error),
73
74	/// Error parsing VP9.
75	#[error("vp9: {0}")]
76	Vp9(#[from] crate::codec::vp9::Error),
77
78	/// Error parsing legacy audio (MP2 / AC-3 / E-AC-3).
79	#[error("legacy: {0}")]
80	Legacy(#[from] crate::codec::legacy::Error),
81
82	/// Timestamp overflow when converting between timescales.
83	#[error("timestamp overflow")]
84	TimestampOverflow(#[from] moq_net::TimeOverflow),
85
86	/// Error decoding or encoding an mp4 atom.
87	#[error("mp4: {0}")]
88	Mp4(std::sync::Arc<mp4_atom::Error>),
89
90	/// I/O error.
91	#[error("io: {0}")]
92	Io(std::sync::Arc<std::io::Error>),
93
94	/// URL parse error.
95	#[error("url: {0}")]
96	Url(#[from] url::ParseError),
97
98	/// Unknown media format.
99	#[error("unknown format: {0}")]
100	UnknownFormat(String),
101
102	/// A non-keyframe frame was received before any keyframe opened a group.
103	/// A track joining mid-stream should skip frames until the first keyframe.
104	#[error("{0}")]
105	MissingKeyframe(#[from] crate::container::MissingKeyframe),
106
107	/// A FLV video frame resolved to a negative presentation timestamp.
108	#[error("negative FLV video presentation timestamp: dts={dts_ms}ms composition_time={composition_time_ms}ms")]
109	NegativeFlvPts {
110		/// The FLV tag decode timestamp in milliseconds.
111		dts_ms: u64,
112		/// The signed FLV composition-time offset in milliseconds.
113		composition_time_ms: i32,
114	},
115
116	/// Error from a muxer/demuxer that reports via `anyhow` (currently MPEG-TS).
117	/// Boxed in an `Arc` so the enum stays `Clone` (`anyhow::Error` is not).
118	#[error("{0}")]
119	Other(std::sync::Arc<anyhow::Error>),
120
121	/// A timeline catalog section declared a timescale that isn't a valid
122	/// [`moq_net::Timescale`] (zero, or too large).
123	#[error("invalid timeline timescale: {0}")]
124	InvalidTimescale(u32),
125
126	/// Tried to set an application catalog section whose name collides with a
127	/// reserved media section (`video`/`audio`).
128	#[error("reserved catalog section: {0}")]
129	ReservedSection(String),
130
131	/// A rendition declared a container `kind` this build does not recognize, so its
132	/// frames cannot be parsed. Such a rendition must be ignored, not guessed at.
133	#[error("unsupported container: {0}")]
134	UnsupportedContainer(String),
135}
136
137impl Error {
138	/// The error for a rendition whose container this build does not recognize.
139	pub(crate) fn unsupported_container(container: &hang::catalog::UnknownContainer) -> Self {
140		Self::UnsupportedContainer(container.kind().unwrap_or("<missing>").to_string())
141	}
142}
143
144impl From<anyhow::Error> for Error {
145	fn from(err: anyhow::Error) -> Self {
146		Error::Other(std::sync::Arc::new(err))
147	}
148}
149
150impl From<mp4_atom::Error> for Error {
151	fn from(err: mp4_atom::Error) -> Self {
152		Error::Mp4(std::sync::Arc::new(err))
153	}
154}
155
156impl From<std::io::Error> for Error {
157	fn from(err: std::io::Error) -> Self {
158		Error::Io(std::sync::Arc::new(err))
159	}
160}
161
162/// A Result type alias for moq-mux operations.
163pub type Result<T> = std::result::Result<T, Error>;