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