Skip to main content

mp4_atom/moov/trak/mdia/minf/stbl/stsd/
mod.rs

1mod ac3;
2mod amr;
3mod audio;
4mod av01;
5mod btrt;
6mod camm;
7mod ccst;
8mod chnl;
9mod colr;
10mod eac3;
11mod fiel;
12mod flac;
13mod ftab;
14mod h264;
15mod hevc;
16mod jpeg;
17mod mebx;
18mod metadata;
19mod mett;
20mod metx;
21mod mp3;
22mod mp4a;
23mod opus;
24mod pasp;
25mod pcm;
26mod plaintext;
27mod taic;
28mod tx3g;
29mod uncv;
30mod urim;
31mod visual;
32mod vp9;
33mod wvtt;
34
35pub use ac3::*;
36pub use amr::*;
37pub use audio::*;
38pub use av01::*;
39pub use btrt::*;
40pub use camm::*;
41pub use ccst::*;
42pub use chnl::*;
43pub use colr::*;
44pub use eac3::*;
45pub use fiel::*;
46pub use flac::*;
47pub use ftab::*;
48pub use h264::*;
49pub use hevc::*;
50pub use jpeg::*;
51pub use mebx::*;
52pub use metadata::*;
53pub use mett::*;
54pub use metx::*;
55pub use mp3::*;
56pub use mp4a::*;
57pub use opus::*;
58pub use pasp::*;
59pub use pcm::*;
60pub use plaintext::*;
61pub use taic::*;
62pub use tx3g::*;
63pub use uncv::*;
64pub use urim::*;
65pub use visual::*;
66pub use vp9::*;
67pub use wvtt::*;
68
69use crate::*;
70use derive_more::From;
71
72#[derive(Debug, Clone, PartialEq, Eq, Default)]
73#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
74pub struct Stsd {
75    pub codecs: Vec<Codec>,
76}
77
78/// Called a "sample entry" in the ISOBMFF specification.
79#[derive(Debug, Clone, PartialEq, Eq, From)]
80#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
81#[non_exhaustive]
82pub enum Codec {
83    // H264
84    Avc1(Avc1),
85
86    // Photo - JPEG (QuickTime Motion JPEG)
87    Jpeg(Jpeg),
88
89    // HEVC: SPS/PPS/VPS is inline
90    Hev1(Hev1),
91
92    // HEVC: SPS/PPS/VPS is in a separate atom
93    Hvc1(Hvc1),
94
95    // VP8
96    Vp08(Vp08),
97
98    // VP9
99    Vp09(Vp09),
100
101    // AV1
102    Av01(Av01),
103
104    // AAC
105    Mp4a(Mp4a),
106
107    // MP3
108    Mp3(Mp3),
109
110    // Text
111    Tx3g(Tx3g),
112
113    // Opus
114    Opus(Opus),
115
116    // Uncompressed video
117    Uncv(Uncv),
118
119    // FLAC audio
120    Flac(Flac),
121
122    // AC-3 audio
123    Ac3(Ac3),
124
125    // EAC-3 audio
126    Eac3(Eac3),
127
128    // Uncompressed audio
129    // ipcm and fpcm are from 23003-5.
130    Ipcm(Ipcm),
131    Fpcm(Fpcm),
132    // sowt / twos and in24 / in32 / fl32 / fl64 / lpcm are Quicktime (QTFF-2001).
133    // s16l seems to be something that VLC produced at some point.
134    Sowt(Sowt),
135    Twos(Twos),
136    Lpcm(Lpcm),
137    In24(In24),
138    In32(In32),
139    Fl32(Fl32),
140    Fl64(Fl64),
141    S16l(S16l),
142
143    // WebVTT, ISO/IEC 14496-30
144    Wvtt(Wvtt),
145
146    // 3GPP Narrowband audio (3GPP TS 26.244 or ETSI TS 126 244)
147    Samr(Samr),
148
149    // Text-based timed metadata
150    Mett(Mett),
151
152    // XML-based timed metadata
153    Metx(Metx),
154
155    // URI-based timed metadata
156    Urim(Urim),
157
158    // Camera motion metadata (gyroscope/accelerometer), used by Google devices
159    Camm(Camm),
160
161    // Structured/"boxed" timed metadata, QuickTime "Metadata Media"
162    Mebx(Mebx),
163
164    // Unknown
165    Unknown(FourCC, Vec<u8>),
166}
167
168impl Decode for Codec {
169    fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
170        let atom = Any::decode(buf)?;
171        Ok(match atom {
172            Any::Avc1(atom) => atom.into(),
173            Any::Jpeg(atom) => atom.into(),
174            Any::Hev1(atom) => atom.into(),
175            Any::Hvc1(atom) => atom.into(),
176            Any::Vp08(atom) => atom.into(),
177            Any::Vp09(atom) => atom.into(),
178            Any::Mp4a(atom) => atom.into(),
179            Any::Mp3(atom) => atom.into(),
180            Any::Tx3g(atom) => atom.into(),
181            Any::Av01(atom) => atom.into(),
182            Any::Opus(atom) => atom.into(),
183            Any::Uncv(atom) => atom.into(),
184            Any::Flac(atom) => atom.into(),
185            Any::Ac3(atom) => atom.into(),
186            Any::Eac3(atom) => atom.into(),
187            Any::Ipcm(atom) => atom.into(),
188            Any::Fpcm(atom) => atom.into(),
189            Any::Sowt(atom) => atom.into(),
190            Any::Twos(atom) => atom.into(),
191            Any::Lpcm(atom) => atom.into(),
192            Any::In24(atom) => atom.into(),
193            Any::In32(atom) => atom.into(),
194            Any::Fl32(atom) => atom.into(),
195            Any::Fl64(atom) => atom.into(),
196            Any::S16l(atom) => atom.into(),
197            Any::Wvtt(atom) => atom.into(),
198            Any::Samr(atom) => atom.into(),
199            Any::Mett(atom) => atom.into(),
200            Any::Metx(atom) => atom.into(),
201            Any::Urim(atom) => atom.into(),
202            Any::Camm(atom) => atom.into(),
203            Any::Mebx(atom) => atom.into(),
204            Any::Unknown(four_cc, body) => Self::Unknown(four_cc, body),
205            unknown => {
206                crate::decode_unknown(&unknown, Stsd::KIND)?;
207
208                // The atom kind is known elsewhere in the hierarchy, but is not a supported
209                // sample entry. Re-encode its body so the unknown entry remains a valid box.
210                let kind = unknown.kind();
211                let mut encoded = Vec::new();
212                unknown.encode(&mut encoded)?;
213                Self::Unknown(kind, encoded.split_off(8))
214            }
215        })
216    }
217}
218
219impl Encode for Codec {
220    fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
221        match self {
222            Self::Unknown(..) => Err(Error::UnknownCodec),
223            Self::Avc1(atom) => atom.encode(buf),
224            Self::Jpeg(atom) => atom.encode(buf),
225            Self::Hev1(atom) => atom.encode(buf),
226            Self::Hvc1(atom) => atom.encode(buf),
227            Self::Vp08(atom) => atom.encode(buf),
228            Self::Vp09(atom) => atom.encode(buf),
229            Self::Mp4a(atom) => atom.encode(buf),
230            Self::Mp3(atom) => atom.encode(buf),
231            Self::Tx3g(atom) => atom.encode(buf),
232            Self::Av01(atom) => atom.encode(buf),
233            Self::Opus(atom) => atom.encode(buf),
234            Self::Uncv(atom) => atom.encode(buf),
235            Self::Flac(atom) => atom.encode(buf),
236            Self::Ac3(atom) => atom.encode(buf),
237            Self::Eac3(atom) => atom.encode(buf),
238            Self::Ipcm(atom) => atom.encode(buf),
239            Self::Fpcm(atom) => atom.encode(buf),
240            Self::Sowt(atom) => atom.encode(buf),
241            Self::Twos(atom) => atom.encode(buf),
242            Self::Lpcm(atom) => atom.encode(buf),
243            Self::In24(atom) => atom.encode(buf),
244            Self::In32(atom) => atom.encode(buf),
245            Self::Fl32(atom) => atom.encode(buf),
246            Self::Fl64(atom) => atom.encode(buf),
247            Self::S16l(atom) => atom.encode(buf),
248            Self::Wvtt(atom) => atom.encode(buf),
249            Self::Samr(atom) => atom.encode(buf),
250            Self::Mett(atom) => atom.encode(buf),
251            Self::Metx(atom) => atom.encode(buf),
252            Self::Urim(atom) => atom.encode(buf),
253            Self::Camm(atom) => atom.encode(buf),
254            Self::Mebx(atom) => atom.encode(buf),
255        }
256    }
257}
258
259impl AtomExt for Stsd {
260    type Ext = ();
261
262    const KIND_EXT: FourCC = FourCC::new(b"stsd");
263
264    fn decode_body_ext<B: Buf>(buf: &mut B, _ext: ()) -> Result<Self> {
265        let codec_count = u32::decode(buf)?;
266        let mut codecs = Vec::new();
267
268        for _ in 0..codec_count {
269            let codec = Codec::decode(buf)?;
270            codecs.push(codec);
271        }
272
273        Ok(Stsd { codecs })
274    }
275
276    fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<()> {
277        (self.codecs.len() as u32).encode(buf)?;
278        for codec in &self.codecs {
279            codec.encode(buf)?;
280        }
281
282        Ok(())
283    }
284}
285
286mod tests {
287    #![cfg(not(feature = "strict"))]
288
289    #[test]
290    fn unknown_codec_parses() {
291        use crate::{Codec, Decode, FourCC, Stsd};
292
293        let input = b"\0\0\0\x1cstsd\0\0\0\0\0\0\0\x01\0\0\0\x0cdvh9\x01\x02\x03\x04";
294        let mut buf = input.as_slice();
295
296        let stsd = Stsd::decode(&mut buf).unwrap();
297        assert_eq!(
298            stsd.codecs,
299            vec![Codec::Unknown(FourCC::new(b"dvh9"), vec![1, 2, 3, 4])]
300        );
301    }
302
303    #[test]
304
305    fn unknown_codec_not_emitted() {
306        use crate::{Codec, Encode, FourCC, Stsd};
307
308        let stsd = Stsd {
309            codecs: vec![Codec::Unknown(FourCC::new(b"dvh9"), vec![1, 2, 3, 4])],
310        };
311        assert_eq!(
312            stsd.codecs,
313            vec![Codec::Unknown(FourCC::new(b"dvh9"), vec![1, 2, 3, 4])]
314        );
315        let mut output = Vec::new();
316        assert!(matches!(
317            stsd.encode(&mut output),
318            Err(crate::Error::UnknownCodec)
319        ));
320    }
321}