1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Default)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6pub struct Subs {
7 pub flags: [u8; 3], pub entries: Vec<SubsEntry>,
9}
10
11#[derive(Debug, Clone, PartialEq, Eq, Default)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct SubsEntry {
14 pub sample_delta: u32,
15 pub subsamples: Vec<SubsSubsample>,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Default)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20pub struct SubsSubsample {
21 pub size: SubsSubsampleSize,
22 pub priority: u8,
23 pub discardable: bool,
24 pub codec_specific_parameters: Vec<u8>,
25}
26
27#[derive(Debug, Clone, PartialEq, Eq)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29pub enum SubsSubsampleSize {
30 U16(u16),
31 U32(u32),
32}
33impl Default for SubsSubsampleSize {
34 fn default() -> Self {
35 Self::U16(0)
38 }
39}
40impl SubsSubsampleSize {
41 pub fn value(&self) -> u32 {
42 match self {
43 Self::U16(n) => u32::from(*n),
44 Self::U32(n) => *n,
45 }
46 }
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
58pub(crate) enum SubsVersion {
59 #[default]
60 V0 = 0,
61 V1 = 1,
62}
63
64impl TryFrom<u8> for SubsVersion {
65 type Error = Error;
66
67 fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
68 match value {
69 0 => Ok(Self::V0),
70 1 => Ok(Self::V1),
71 _ => Err(Error::UnknownVersion(value)),
72 }
73 }
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, Default)]
77pub(crate) struct SubsExt {
78 pub version: SubsVersion,
79 pub flags: [u8; 3],
80}
81
82impl Ext for SubsExt {
83 fn encode(&self) -> Result<u32> {
84 Ok((self.version as u32) << 24
85 | (self.flags[0] as u32) << 16
86 | (self.flags[1] as u32) << 8
87 | (self.flags[2] as u32))
88 }
89
90 fn decode(v: u32) -> Result<Self> {
91 let bytes = v.to_be_bytes();
92 let version = SubsVersion::try_from(bytes[0])?;
93 let flags = [bytes[1], bytes[2], bytes[3]];
94 Ok(Self { version, flags })
95 }
96}
97
98impl AtomExt for Subs {
99 type Ext = SubsExt;
100
101 const KIND_EXT: FourCC = FourCC::new(b"subs");
102
103 fn decode_body_ext<B: Buf>(buf: &mut B, ext: Self::Ext) -> Result<Self> {
104 let flags = ext.flags;
105 let entry_count = u32::decode(buf)?;
106 let mut entries = Vec::with_capacity((entry_count as usize).min(1024));
107 for _ in 0..entry_count {
108 let sample_delta = u32::decode(buf)?;
109 let subsample_count = u16::decode(buf)?;
110 let mut subsamples = Vec::with_capacity(usize::from(subsample_count).min(1024));
111 for _ in 0..subsample_count {
112 let size = if ext.version == SubsVersion::V1 {
113 SubsSubsampleSize::U32(u32::decode(buf)?)
114 } else {
115 SubsSubsampleSize::U16(u16::decode(buf)?)
116 };
117 let priority = u8::decode(buf)?;
118 let discardable = u8::decode(buf)? == 1;
119 let codec_specific_parameters = <[u8; 4]>::decode(buf)?.to_vec();
120 subsamples.push(SubsSubsample {
121 size,
122 priority,
123 discardable,
124 codec_specific_parameters,
125 });
126 }
127 entries.push(SubsEntry {
128 sample_delta,
129 subsamples,
130 });
131 }
132 Ok(Self { flags, entries })
133 }
134
135 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<Self::Ext> {
136 let ext = match &self
137 .entries
138 .first()
139 .and_then(|e| e.subsamples.first())
140 .map(|s| &s.size)
141 {
142 Some(SubsSubsampleSize::U16(_)) => SubsExt {
143 version: SubsVersion::V0,
144 flags: self.flags,
145 },
146 Some(SubsSubsampleSize::U32(_)) => SubsExt {
147 version: SubsVersion::V1,
148 flags: self.flags,
149 },
150 None => SubsExt {
153 version: SubsVersion::default(),
154 flags: self.flags,
155 },
156 };
157 (self.entries.len() as u32).encode(buf)?;
158 for entry in &self.entries {
159 entry.sample_delta.encode(buf)?;
160 (entry.subsamples.len() as u16).encode(buf)?;
161 for subsample in &entry.subsamples {
162 match subsample.size {
163 SubsSubsampleSize::U16(n) => n.encode(buf)?,
164 SubsSubsampleSize::U32(n) => n.encode(buf)?,
165 }
166 subsample.priority.encode(buf)?;
167 if subsample.discardable {
168 1u8.encode(buf)?;
169 } else {
170 0u8.encode(buf)?;
171 }
172 subsample.codec_specific_parameters.encode(buf)?;
173 }
174 }
175 Ok(ext)
176 }
177}
178
179#[cfg(test)]
180mod tests {
181 use super::*;
182 use std::io::Cursor;
183
184 const SUBS: &[u8] = &[
189 0x00, 0x00, 0x00, 0x16, 0x73, 0x75, 0x62, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
191 ];
192
193 #[test]
194 fn subs_decodes_from_bytes_correctly() {
195 let mut buf = Cursor::new(SUBS);
196 let subs = Subs::decode(&mut buf).expect("subs should decode successfully");
197 assert_eq!(
198 subs,
199 Subs {
200 flags: [0, 0, 0],
201 entries: vec![SubsEntry {
202 sample_delta: 1,
203 subsamples: vec![],
204 }],
205 }
206 )
207 }
208
209 #[test]
210 fn subs_truncated_codec_parameters_return_error() {
211 let body: &[u8] = &[
212 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, ];
220
221 assert!(matches!(
222 Subs::decode_body_ext(
223 &mut Cursor::new(body),
224 SubsExt {
225 version: SubsVersion::V0,
226 flags: [0; 3],
227 },
228 ),
229 Err(Error::OutOfBounds)
230 ));
231 }
232
233 const SUBS_COMPLEX: &[u8] = &[
242 0x00, 0x00, 0x00, 0x9C, 0x73, 0x75, 0x62, 0x73, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
243 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0F, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x05, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x0B, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA3, 0x00, 0x00, 0x00, 0x00,
246 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x4A, 0x00, 0x00, 0x00,
247 0x00, 0x00, 0x00, 0x05, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
248 0x00, 0x08, 0x00, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00,
249 0x00, 0x00, 0x00, 0x02, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xDE, 0x00, 0x00,
250 0x00, 0x00, 0x00, 0x00, 0x05, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x4A, 0x00,
251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF6,
252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253 ];
254
255 #[test]
256 fn subs_decodes_from_bytes_and_encodes_to_bytes_correctly_with_more_complex_example() {
257 let mut buf = Cursor::new(SUBS_COMPLEX);
258 let subs = Subs {
259 flags: [0, 0, 2],
260 entries: vec![
261 SubsEntry {
262 sample_delta: 0,
263 subsamples: vec![
264 SubsSubsample {
265 size: SubsSubsampleSize::U16(3991),
266 priority: 0,
267 discardable: false,
268 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
269 },
270 SubsSubsample {
271 size: SubsSubsampleSize::U16(1362),
272 priority: 0,
273 discardable: false,
274 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
275 },
276 SubsSubsample {
277 size: SubsSubsampleSize::U16(1443),
278 priority: 0,
279 discardable: false,
280 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
281 },
282 SubsSubsample {
283 size: SubsSubsampleSize::U16(2952),
284 priority: 0,
285 discardable: false,
286 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
287 },
288 SubsSubsample {
289 size: SubsSubsampleSize::U16(1955),
290 priority: 0,
291 discardable: false,
292 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
293 },
294 SubsSubsample {
295 size: SubsSubsampleSize::U16(1525),
296 priority: 0,
297 discardable: false,
298 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
299 },
300 SubsSubsample {
301 size: SubsSubsampleSize::U16(842),
302 priority: 0,
303 discardable: false,
304 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
305 },
306 SubsSubsample {
307 size: SubsSubsampleSize::U16(1386),
308 priority: 0,
309 discardable: false,
310 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
311 },
312 ],
313 },
314 SubsEntry {
315 sample_delta: 1,
316 subsamples: vec![
317 SubsSubsample {
318 size: SubsSubsampleSize::U16(194),
319 priority: 0,
320 discardable: false,
321 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
322 },
323 SubsSubsample {
324 size: SubsSubsampleSize::U16(171),
325 priority: 0,
326 discardable: false,
327 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
328 },
329 SubsSubsample {
330 size: SubsSubsampleSize::U16(736),
331 priority: 0,
332 discardable: false,
333 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
334 },
335 SubsSubsample {
336 size: SubsSubsampleSize::U16(734),
337 priority: 0,
338 discardable: false,
339 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
340 },
341 SubsSubsample {
342 size: SubsSubsampleSize::U16(1470),
343 priority: 0,
344 discardable: false,
345 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
346 },
347 SubsSubsample {
348 size: SubsSubsampleSize::U16(330),
349 priority: 0,
350 discardable: false,
351 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
352 },
353 SubsSubsample {
354 size: SubsSubsampleSize::U16(150),
355 priority: 0,
356 discardable: false,
357 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
358 },
359 SubsSubsample {
360 size: SubsSubsampleSize::U16(1014),
361 priority: 0,
362 discardable: false,
363 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
364 },
365 ],
366 },
367 ],
368 };
369 let decoded = Subs::decode(&mut buf).expect("subs should decode successfully");
370 assert_eq!(subs, decoded);
371 let mut encoded = Vec::new();
372 subs.encode(&mut encoded)
373 .expect("encode should be successful");
374 assert_eq!(SUBS_COMPLEX, &encoded);
375 }
376}