1mod ac3;
2mod amr;
3mod audio;
4mod av01;
5mod btrt;
6mod camm;
7mod ccst;
8mod chnl;
9mod colr;
10mod eac3;
11mod evte;
12mod fiel;
13mod flac;
14mod ftab;
15mod h264;
16mod hevc;
17mod jpeg;
18mod mebx;
19mod metadata;
20mod mett;
21mod metx;
22mod mp3;
23mod mp4a;
24mod opus;
25mod pasp;
26mod pcm;
27mod plaintext;
28mod spatial;
29mod st3d;
30mod sv3d;
31mod taic;
32mod tx3g;
33mod uncv;
34mod urim;
35mod vexu;
36mod visual;
37mod vp9;
38mod wvtt;
39
40pub use ac3::*;
41pub use amr::*;
42pub use audio::*;
43pub use av01::*;
44pub use btrt::*;
45pub use camm::*;
46pub use ccst::*;
47pub use chnl::*;
48pub use colr::*;
49pub use eac3::*;
50pub use evte::*;
51pub use fiel::*;
52pub use flac::*;
53pub use ftab::*;
54pub use h264::*;
55pub use hevc::*;
56pub use jpeg::*;
57pub use mebx::*;
58pub use metadata::*;
59pub use mett::*;
60pub use metx::*;
61pub use mp3::*;
62pub use mp4a::*;
63pub use opus::*;
64pub use pasp::*;
65pub use pcm::*;
66pub use plaintext::*;
67pub use spatial::*;
68pub use st3d::*;
69pub use sv3d::*;
70pub use taic::*;
71pub use tx3g::*;
72pub use uncv::*;
73pub use urim::*;
74pub use vexu::*;
75pub use visual::*;
76pub use vp9::*;
77pub use wvtt::*;
78
79use crate::*;
80use derive_more::From;
81
82#[derive(Debug, Clone, PartialEq, Eq, Default)]
83#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
84pub struct Stsd {
85 pub codecs: Vec<Codec>,
86}
87
88#[derive(Debug, Clone, PartialEq, Eq, From)]
90#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
91#[non_exhaustive]
92pub enum Codec {
93 Avc1(Avc1),
95
96 Avc3(Avc3),
98
99 Jpeg(Jpeg),
101
102 Hev1(Hev1),
104
105 Hvc1(Hvc1),
107
108 Vp08(Vp08),
110
111 Vp09(Vp09),
113
114 Av01(Av01),
116
117 Mp4a(Mp4a),
119
120 Mp3(Mp3),
122
123 Tx3g(Tx3g),
125
126 Opus(Opus),
128
129 Uncv(Uncv),
131
132 Flac(Flac),
134
135 Ac3(Ac3),
137
138 Eac3(Eac3),
140
141 Ipcm(Ipcm),
144 Fpcm(Fpcm),
145 Sowt(Sowt),
148 Twos(Twos),
149 Lpcm(Lpcm),
150 In24(In24),
151 In32(In32),
152 Fl32(Fl32),
153 Fl64(Fl64),
154 S16l(S16l),
155
156 Wvtt(Wvtt),
158
159 Samr(Samr),
161
162 Mett(Mett),
164
165 Metx(Metx),
167
168 Urim(Urim),
170
171 Camm(Camm),
173
174 Evte(Evte),
177
178 Mebx(Mebx),
180
181 Unknown(FourCC, Vec<u8>),
183}
184
185impl Codec {
186 pub fn visual(&self) -> Option<&Visual> {
189 Some(match self {
190 Self::Avc1(avc1) => &avc1.visual,
191 Self::Avc3(avc3) => &avc3.visual,
192 Self::Jpeg(jpeg) => &jpeg.visual,
193 Self::Hev1(hev1) => &hev1.visual,
194 Self::Hvc1(hvc1) => &hvc1.visual,
195 Self::Vp08(vp08) => &vp08.visual,
196 Self::Vp09(vp09) => &vp09.visual,
197 Self::Av01(av01) => &av01.visual,
198 Self::Uncv(uncv) => &uncv.visual,
199 _ => return None,
200 })
201 }
202
203 pub fn audio(&self) -> Option<&Audio> {
206 Some(match self {
207 Self::Mp4a(mp4a) => &mp4a.audio,
208 Self::Mp3(mp3) => &mp3.audio,
209 Self::Opus(opus) => &opus.audio,
210 Self::Flac(flac) => &flac.audio,
211 Self::Ac3(ac3) => &ac3.audio,
212 Self::Eac3(eac3) => &eac3.audio,
213 Self::Ipcm(pcm) => &pcm.audio,
214 Self::Fpcm(pcm) => &pcm.audio,
215 Self::Sowt(pcm) => &pcm.audio,
216 Self::Twos(pcm) => &pcm.audio,
217 Self::Lpcm(pcm) => &pcm.audio,
218 Self::In24(pcm) => &pcm.audio,
219 Self::In32(pcm) => &pcm.audio,
220 Self::Fl32(pcm) => &pcm.audio,
221 Self::Fl64(pcm) => &pcm.audio,
222 Self::S16l(pcm) => &pcm.audio,
223 _ => return None,
224 })
225 }
226
227 pub fn metadata(&self) -> Option<&MetaData> {
230 Some(match self {
231 Self::Mett(mett) => &mett.metadata,
232 Self::Metx(metx) => &metx.metadata,
233 Self::Urim(urim) => &urim.metadata,
234 Self::Camm(camm) => &camm.metadata,
235 Self::Evte(evte) => &evte.metadata,
236 Self::Mebx(mebx) => &mebx.metadata,
237 _ => return None,
238 })
239 }
240}
241
242impl Decode for Codec {
243 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
244 let atom = Any::decode(buf)?;
245 Ok(match atom {
246 Any::Avc1(atom) => atom.into(),
247 Any::Avc3(atom) => atom.into(),
248 Any::Jpeg(atom) => atom.into(),
249 Any::Hev1(atom) => atom.into(),
250 Any::Hvc1(atom) => atom.into(),
251 Any::Vp08(atom) => atom.into(),
252 Any::Vp09(atom) => atom.into(),
253 Any::Mp4a(atom) => atom.into(),
254 Any::Mp3(atom) => atom.into(),
255 Any::Tx3g(atom) => atom.into(),
256 Any::Av01(atom) => atom.into(),
257 Any::Opus(atom) => atom.into(),
258 Any::Uncv(atom) => atom.into(),
259 Any::Flac(atom) => atom.into(),
260 Any::Ac3(atom) => atom.into(),
261 Any::Eac3(atom) => atom.into(),
262 Any::Ipcm(atom) => atom.into(),
263 Any::Fpcm(atom) => atom.into(),
264 Any::Sowt(atom) => atom.into(),
265 Any::Twos(atom) => atom.into(),
266 Any::Lpcm(atom) => atom.into(),
267 Any::In24(atom) => atom.into(),
268 Any::In32(atom) => atom.into(),
269 Any::Fl32(atom) => atom.into(),
270 Any::Fl64(atom) => atom.into(),
271 Any::S16l(atom) => atom.into(),
272 Any::Wvtt(atom) => atom.into(),
273 Any::Samr(atom) => atom.into(),
274 Any::Mett(atom) => atom.into(),
275 Any::Metx(atom) => atom.into(),
276 Any::Urim(atom) => atom.into(),
277 Any::Camm(atom) => atom.into(),
278 Any::Evte(atom) => atom.into(),
279 Any::Mebx(atom) => atom.into(),
280 Any::Unknown(four_cc, body) => Self::Unknown(four_cc, body),
281 unknown => {
282 crate::decode_unknown(&unknown, Stsd::KIND)?;
283
284 let kind = unknown.kind();
287 let mut encoded = Vec::new();
288 unknown.encode(&mut encoded)?;
289 Self::Unknown(kind, encoded.split_off(8))
290 }
291 })
292 }
293}
294
295impl Encode for Codec {
296 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
297 match self {
298 Self::Unknown(..) => Err(Error::UnknownCodec),
299 Self::Avc1(atom) => atom.encode(buf),
300 Self::Avc3(atom) => atom.encode(buf),
301 Self::Jpeg(atom) => atom.encode(buf),
302 Self::Hev1(atom) => atom.encode(buf),
303 Self::Hvc1(atom) => atom.encode(buf),
304 Self::Vp08(atom) => atom.encode(buf),
305 Self::Vp09(atom) => atom.encode(buf),
306 Self::Mp4a(atom) => atom.encode(buf),
307 Self::Mp3(atom) => atom.encode(buf),
308 Self::Tx3g(atom) => atom.encode(buf),
309 Self::Av01(atom) => atom.encode(buf),
310 Self::Opus(atom) => atom.encode(buf),
311 Self::Uncv(atom) => atom.encode(buf),
312 Self::Flac(atom) => atom.encode(buf),
313 Self::Ac3(atom) => atom.encode(buf),
314 Self::Eac3(atom) => atom.encode(buf),
315 Self::Ipcm(atom) => atom.encode(buf),
316 Self::Fpcm(atom) => atom.encode(buf),
317 Self::Sowt(atom) => atom.encode(buf),
318 Self::Twos(atom) => atom.encode(buf),
319 Self::Lpcm(atom) => atom.encode(buf),
320 Self::In24(atom) => atom.encode(buf),
321 Self::In32(atom) => atom.encode(buf),
322 Self::Fl32(atom) => atom.encode(buf),
323 Self::Fl64(atom) => atom.encode(buf),
324 Self::S16l(atom) => atom.encode(buf),
325 Self::Wvtt(atom) => atom.encode(buf),
326 Self::Samr(atom) => atom.encode(buf),
327 Self::Mett(atom) => atom.encode(buf),
328 Self::Metx(atom) => atom.encode(buf),
329 Self::Urim(atom) => atom.encode(buf),
330 Self::Camm(atom) => atom.encode(buf),
331 Self::Evte(atom) => atom.encode(buf),
332 Self::Mebx(atom) => atom.encode(buf),
333 }
334 }
335}
336
337impl AtomExt for Stsd {
338 type Ext = ();
339
340 const KIND_EXT: FourCC = FourCC::new(b"stsd");
341
342 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: ()) -> Result<Self> {
343 let codec_count = u32::decode(buf)?;
344 let mut codecs = Vec::new();
345
346 for _ in 0..codec_count {
347 let codec = Codec::decode(buf)?;
348 codecs.push(codec);
349 }
350
351 Ok(Stsd { codecs })
352 }
353
354 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<()> {
355 (self.codecs.len() as u32).encode(buf)?;
356 for codec in &self.codecs {
357 codec.encode(buf)?;
358 }
359
360 Ok(())
361 }
362}
363
364#[cfg(test)]
365mod tests {
366 use super::*;
367
368 #[test]
369 fn test_codec_visual() {
370 let visual = Visual {
371 width: 640,
372 height: 480,
373 ..Default::default()
374 };
375 let codec = Codec::from(Jpeg {
376 visual: visual.clone(),
377 ..Default::default()
378 });
379 assert_eq!(codec.visual(), Some(&visual));
380 assert_eq!(codec.audio(), None);
381 assert_eq!(codec.metadata(), None);
382 }
383
384 #[test]
385 fn test_codec_audio() {
386 let audio = Audio {
387 data_reference_index: 1,
388 channel_count: 2,
389 sample_size: 16,
390 sample_rate: 44100.into(),
391 };
392 let codec = Codec::from(Mp3 {
393 audio: audio.clone(),
394 });
395 assert_eq!(codec.audio(), Some(&audio));
396 assert_eq!(codec.visual(), None);
397 }
398
399 #[test]
400 fn test_codec_metadata() {
401 let metadata = MetaData {
402 data_reference_index: 3,
403 };
404 let codec = Codec::from(Camm {
405 metadata: metadata.clone(),
406 });
407 assert_eq!(codec.metadata(), Some(&metadata));
408 assert_eq!(codec.visual(), None);
409 assert_eq!(codec.audio(), None);
410 }
411
412 #[test]
413 fn test_codec_neither() {
414 for codec in [
415 Codec::from(Tx3g::default()),
416 Codec::Unknown(FourCC::new(b"dvh9"), vec![]),
417 ] {
418 assert_eq!(codec.visual(), None);
419 assert_eq!(codec.audio(), None);
420 assert_eq!(codec.metadata(), None);
421 }
422 }
423
424 #[cfg(not(feature = "strict"))]
425 mod not_strict {
426 use super::*;
427
428 #[test]
429 fn unknown_codec_parses() {
430 let input = b"\0\0\0\x1cstsd\0\0\0\0\0\0\0\x01\0\0\0\x0cdvh9\x01\x02\x03\x04";
431 let mut buf = input.as_slice();
432
433 let stsd = Stsd::decode(&mut buf).unwrap();
434 assert_eq!(
435 stsd.codecs,
436 vec![Codec::Unknown(FourCC::new(b"dvh9"), vec![1, 2, 3, 4])]
437 );
438 }
439
440 #[test]
441 fn unknown_codec_not_emitted() {
442 let stsd = Stsd {
443 codecs: vec![Codec::Unknown(FourCC::new(b"dvh9"), vec![1, 2, 3, 4])],
444 };
445 assert_eq!(
446 stsd.codecs,
447 vec![Codec::Unknown(FourCC::new(b"dvh9"), vec![1, 2, 3, 4])]
448 );
449 let mut output = Vec::new();
450 assert!(matches!(
451 stsd.encode(&mut output),
452 Err(crate::Error::UnknownCodec)
453 ));
454 }
455 }
456}