Skip to main content

mp4_atom/moov/trak/mdia/minf/stbl/
saiz.rs

1use crate::*;
2
3/// Auxiliary information type and parameter shared by `saiz` and `saio`,
4/// ISO/IEC 14496-12:2022 Sect 8.7.8 / 8.7.9.
5#[derive(Debug, Clone, PartialEq, Eq)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7pub struct AuxInfo {
8    pub aux_info_type: FourCC,
9    pub aux_info_type_parameter: u32,
10}
11
12ext! {
13    name: Saiz,
14    versions: [0],
15    flags: {
16        aux_info_type_present  = 0,
17    }
18}
19
20ext! {
21    name: Saio,
22    versions: [0, 1],
23    flags: {
24        aux_info_type_present  = 0,
25    }
26}
27
28/// Sample AuxiliaryInformationSizesBox, ISO/IEC 14496-12:2022 Sect 8.7.8
29#[derive(Debug, Clone, PartialEq, Eq, Default)]
30#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
31pub struct Saiz {
32    pub aux_info: Option<AuxInfo>,
33    pub default_sample_info_size: u8,
34    pub sample_count: u32,
35    pub sample_info_size: Vec<u8>,
36}
37
38impl AtomExt for Saiz {
39    type Ext = SaizExt;
40
41    const KIND_EXT: FourCC = FourCC::new(b"saiz");
42
43    fn decode_body_ext<B: Buf>(buf: &mut B, ext: SaizExt) -> Result<Self> {
44        let mut aux_info = None;
45        if ext.aux_info_type_present {
46            let aux_info_type = FourCC::decode(buf)?;
47            let aux_info_type_parameter = u32::decode(buf)?;
48            aux_info = Some(AuxInfo {
49                aux_info_type,
50                aux_info_type_parameter,
51            });
52        }
53        let default_sample_info_size = u8::decode(buf)?;
54        let sample_count = u32::decode(buf)?;
55        if default_sample_info_size == 0 {
56            // Each entry is a single byte; reject counts that cannot
57            // possibly fit in the remaining buffer before allocating.
58            if sample_count as usize > buf.remaining() {
59                return Err(Error::OutOfBounds);
60            }
61            let mut sample_info_size = Vec::with_capacity((sample_count as usize).min(4096));
62            for _ in 0..sample_count {
63                sample_info_size.push(u8::decode(buf)?);
64            }
65            Ok(Saiz {
66                aux_info,
67                default_sample_info_size,
68                sample_count,
69                sample_info_size,
70            })
71        } else {
72            Ok(Saiz {
73                aux_info,
74                default_sample_info_size,
75                sample_count,
76                sample_info_size: vec![],
77            })
78        }
79    }
80
81    fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<SaizExt> {
82        let ext = SaizExt {
83            version: SaizVersion::V0,
84            aux_info_type_present: self.aux_info.is_some(),
85        };
86        if let Some(aux_info) = &self.aux_info {
87            aux_info.aux_info_type.encode(buf)?;
88            aux_info.aux_info_type_parameter.encode(buf)?;
89        }
90        self.default_sample_info_size.encode(buf)?;
91        self.sample_count.encode(buf)?;
92        if self.default_sample_info_size == 0 {
93            for size in &self.sample_info_size {
94                size.encode(buf)?;
95            }
96        }
97        Ok(ext)
98    }
99}
100
101/// SampleAuxiliaryInformationOffsetsBox, ISO/IEC 14496-12:2022 Sect 8.7.9
102#[derive(Debug, Clone, PartialEq, Eq, Default)]
103#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
104pub struct Saio {
105    pub aux_info: Option<AuxInfo>,
106    pub offsets: Vec<u64>,
107}
108
109impl AtomExt for Saio {
110    type Ext = SaioExt;
111
112    const KIND_EXT: FourCC = FourCC::new(b"saio");
113
114    fn decode_body_ext<B: Buf>(buf: &mut B, ext: SaioExt) -> Result<Self> {
115        let mut aux_info = None;
116        if ext.aux_info_type_present {
117            let aux_info_type = FourCC::decode(buf)?;
118            let aux_info_type_parameter = u32::decode(buf)?;
119            aux_info = Some(AuxInfo {
120                aux_info_type,
121                aux_info_type_parameter,
122            });
123        }
124        let entry_count = u32::decode(buf)?;
125        // Entries are 4 bytes (v0) or 8 bytes (v1); reject counts that
126        // cannot possibly fit in the remaining buffer before allocating.
127        let per_entry = if ext.version == SaioVersion::V1 { 8 } else { 4 };
128        if entry_count as usize > buf.remaining() / per_entry {
129            return Err(Error::OutOfBounds);
130        }
131        let mut offsets = Vec::with_capacity((entry_count as usize).min(4096));
132        for _ in 0..entry_count {
133            if ext.version == SaioVersion::V0 {
134                let offset = u32::decode(buf)? as u64;
135                offsets.push(offset);
136            } else if ext.version == SaioVersion::V1 {
137                let offset = u64::decode(buf)?;
138                offsets.push(offset);
139            }
140        }
141        Ok(Saio { aux_info, offsets })
142    }
143
144    fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<SaioExt> {
145        let mut version: SaioVersion = SaioVersion::V0;
146        for offset in &self.offsets {
147            if *offset > (u32::MAX as u64) {
148                version = SaioVersion::V1;
149                break;
150            }
151        }
152
153        let ext = SaioExt {
154            version,
155            aux_info_type_present: self.aux_info.is_some(),
156        };
157        if let Some(aux_info) = &self.aux_info {
158            aux_info.aux_info_type.encode(buf)?;
159            aux_info.aux_info_type_parameter.encode(buf)?;
160        }
161        let entry_count: u32 = self.offsets.len() as u32;
162        entry_count.encode(buf)?;
163        if ext.version == SaioVersion::V0 {
164            for i in 0..self.offsets.len() {
165                let offset: u32 = self.offsets[i] as u32;
166                offset.encode(buf)?;
167            }
168        } else {
169            for offset in &self.offsets {
170                offset.encode(buf)?;
171            }
172        }
173        Ok(ext)
174    }
175}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180
181    const ENCODED_SAIZ: &[u8] = &[
182        0x00, 0x00, 0x00, 0x11, 0x73, 0x61, 0x69, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00,
183        0x00, 0x32,
184    ];
185
186    const ENCODED_SAIZ_CENC: &[u8] = &[
187        0x00, 0x00, 0x03, 0x07, 0x73, 0x61, 0x69, 0x7a, 0x00, 0x00, 0x00, 0x01, 0x63, 0x65, 0x6e,
188        0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xee, 0x1e, 0x18, 0x18, 0x18, 0x18,
189        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
190        0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
191        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24,
192        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
193        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18,
194        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
195        0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
196        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24,
197        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
198        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18,
199        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
200        0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
201        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24,
202        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
203        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18,
204        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
205        0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
206        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24,
207        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
208        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18,
209        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
210        0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
211        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24,
212        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
213        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18,
214        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
215        0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
216        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24,
217        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
218        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18,
219        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
220        0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
221        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24,
222        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
223        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18,
224        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
225        0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
226        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24,
227        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
228        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18,
229        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
230        0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
231        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24,
232        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
233        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18,
234        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
235        0x18, 0x18, 0x18, 0x18, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
236        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24,
237        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
238        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
239    ];
240
241    const ENCODED_SAIO: &[u8] = &[
242        0x00, 0x00, 0x00, 0x14, 0x73, 0x61, 0x69, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243        0x01, 0x00, 0x00, 0x04, 0xbc,
244    ];
245
246    const ENCODED_SAIO_CENC: &[u8] = &[
247        0x00, 0x00, 0x00, 0x1c, 0x73, 0x61, 0x69, 0x6f, 0x00, 0x00, 0x00, 0x01, 0x63, 0x65, 0x6e,
248        0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x8e,
249    ];
250
251    #[test]
252    fn test_saiz_decode() {
253        let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_SAIZ);
254
255        let saiz = Saiz::decode(buf).expect("failed to decode saiz");
256
257        assert_eq!(
258            saiz,
259            Saiz {
260                aux_info: None,
261                default_sample_info_size: 70,
262                sample_count: 50,
263                sample_info_size: vec![]
264            },
265        );
266    }
267
268    #[test]
269    fn test_saiz_encode() {
270        let saiz = Saiz {
271            aux_info: None,
272            default_sample_info_size: 70,
273            sample_count: 50,
274            sample_info_size: vec![],
275        };
276
277        let mut buf = Vec::new();
278        saiz.encode(&mut buf).unwrap();
279
280        assert_eq!(buf.as_slice(), ENCODED_SAIZ);
281    }
282
283    #[test]
284    fn test_saiz_encode_cenc() {
285        let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_SAIZ_CENC);
286
287        let saiz = Saiz::decode(buf).expect("failed to decode saiz");
288
289        assert_eq!(
290            saiz,
291            Saiz {
292                aux_info: Some(AuxInfo {
293                    aux_info_type: FourCC::new(b"cenc"),
294                    aux_info_type_parameter: 0,
295                }),
296                default_sample_info_size: 0,
297                sample_count: 750,
298                sample_info_size: vec![
299                    30, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
300                    24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
301                    24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
302                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24,
303                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36,
304                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
305                    24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
306                    24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
307                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24,
308                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36,
309                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
310                    24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
311                    24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
312                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24,
313                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36,
314                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
315                    24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
316                    24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
317                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24,
318                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36,
319                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
320                    24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
321                    24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
322                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24,
323                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36,
324                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
325                    24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
326                    24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
327                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24,
328                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36,
329                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
330                    24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
331                    24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
332                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24,
333                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36,
334                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
335                    24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
336                    24, 24, 24, 24, 24, 24, 24, 24, 24, 24
337                ]
338            },
339        );
340    }
341
342    #[test]
343    fn test_saiz_decode_cenc() {
344        let saiz = Saiz {
345            aux_info: Some(AuxInfo {
346                aux_info_type: FourCC::new(b"cenc"),
347                aux_info_type_parameter: 0,
348            }),
349            default_sample_info_size: 0,
350            sample_count: 750,
351            sample_info_size: vec![
352                30, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
353                24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
354                24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
355                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24,
356                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24,
357                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24,
358                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
359                24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
360                24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
361                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
362                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24,
363                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24,
364                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
365                24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
366                24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
367                24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
368                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24,
369                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24,
370                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
371                36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
372                24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
373                24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
374                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24,
375                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24,
376                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36,
377                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
378                24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
379                24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
380                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24,
381                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24,
382                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24,
383                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
384                24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
385                24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
386                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 36, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
387                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
388            ],
389        };
390
391        let mut buf = Vec::new();
392        saiz.encode(&mut buf).unwrap();
393
394        assert_eq!(buf.as_slice(), ENCODED_SAIZ_CENC);
395    }
396
397    #[test]
398    fn test_saio_decode() {
399        let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_SAIO);
400
401        let saio = Saio::decode(buf).expect("failed to decode saio");
402
403        assert_eq!(
404            saio,
405            Saio {
406                aux_info: None,
407                offsets: vec![1212],
408            }
409        );
410    }
411
412    #[test]
413    fn test_saio_encode() {
414        let saio = Saio {
415            aux_info: None,
416            offsets: vec![1212],
417        };
418
419        let mut buf = Vec::new();
420        saio.encode(&mut buf).unwrap();
421
422        assert_eq!(buf.as_slice(), ENCODED_SAIO);
423    }
424
425    #[test]
426    fn test_saio_decode_cenc() {
427        let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_SAIO_CENC);
428
429        let saio = Saio::decode(buf).expect("failed to decode saio");
430
431        assert_eq!(
432            saio,
433            Saio {
434                aux_info: Some(AuxInfo {
435                    aux_info_type: FourCC::new(b"cenc"),
436                    aux_info_type_parameter: 0
437                }),
438                offsets: vec![1166],
439            }
440        );
441    }
442
443    // Regression for issue #156: a u32::MAX sample_count must fail
444    // cleanly without attempting a ~4 GiB upfront allocation.
445    const ENCODED_SAIZ_HUGE_COUNT: &[u8] = &[
446        0x00, 0x00, 0x00, 0x11, 0x73, 0x61, 0x69, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
447        0xFF, 0xFF,
448    ];
449
450    #[test]
451    fn test_saiz_huge_count() {
452        let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_SAIZ_HUGE_COUNT);
453        assert!(matches!(Saiz::decode(buf), Err(Error::OverDecode(_))));
454    }
455
456    // Regression for issue #156: a u32::MAX entry_count must fail
457    // cleanly without attempting a multi-GiB upfront allocation.
458    const ENCODED_SAIO_HUGE_COUNT: &[u8] = &[
459        0x00, 0x00, 0x00, 0x10, 0x73, 0x61, 0x69, 0x6f, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
460        0xFF,
461    ];
462
463    #[test]
464    fn test_saio_huge_count() {
465        let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_SAIO_HUGE_COUNT);
466        assert!(matches!(Saio::decode(buf), Err(Error::OverDecode(_))));
467    }
468
469    #[test]
470    fn test_saio_encode_cenc() {
471        let saio = Saio {
472            aux_info: Some(AuxInfo {
473                aux_info_type: FourCC::new(b"cenc"),
474                aux_info_type_parameter: 0,
475            }),
476            offsets: vec![1166],
477        };
478
479        let mut buf = Vec::new();
480        saio.encode(&mut buf).unwrap();
481
482        assert_eq!(buf.as_slice(), ENCODED_SAIO_CENC);
483    }
484}