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 = buf.slice(4).to_vec();
120 buf.advance(4);
121 subsamples.push(SubsSubsample {
122 size,
123 priority,
124 discardable,
125 codec_specific_parameters,
126 });
127 }
128 entries.push(SubsEntry {
129 sample_delta,
130 subsamples,
131 });
132 }
133 Ok(Self { flags, entries })
134 }
135
136 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<Self::Ext> {
137 let ext = match &self
138 .entries
139 .first()
140 .and_then(|e| e.subsamples.first())
141 .map(|s| &s.size)
142 {
143 Some(SubsSubsampleSize::U16(_)) => SubsExt {
144 version: SubsVersion::V0,
145 flags: self.flags,
146 },
147 Some(SubsSubsampleSize::U32(_)) => SubsExt {
148 version: SubsVersion::V1,
149 flags: self.flags,
150 },
151 None => SubsExt {
154 version: SubsVersion::default(),
155 flags: self.flags,
156 },
157 };
158 (self.entries.len() as u32).encode(buf)?;
159 for entry in &self.entries {
160 entry.sample_delta.encode(buf)?;
161 (entry.subsamples.len() as u16).encode(buf)?;
162 for subsample in &entry.subsamples {
163 match subsample.size {
164 SubsSubsampleSize::U16(n) => n.encode(buf)?,
165 SubsSubsampleSize::U32(n) => n.encode(buf)?,
166 }
167 subsample.priority.encode(buf)?;
168 if subsample.discardable {
169 1u8.encode(buf)?;
170 } else {
171 0u8.encode(buf)?;
172 }
173 subsample.codec_specific_parameters.encode(buf)?;
174 }
175 }
176 Ok(ext)
177 }
178}
179
180#[cfg(test)]
181mod tests {
182 use super::*;
183 use std::io::Cursor;
184
185 const SUBS: &[u8] = &[
190 0x00, 0x00, 0x00, 0x16, 0x73, 0x75, 0x62, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
192 ];
193
194 #[test]
195 fn subs_decodes_from_bytes_correctly() {
196 let mut buf = Cursor::new(SUBS);
197 let subs = Subs::decode(&mut buf).expect("subs should decode successfully");
198 assert_eq!(
199 subs,
200 Subs {
201 flags: [0, 0, 0],
202 entries: vec![SubsEntry {
203 sample_delta: 1,
204 subsamples: vec![],
205 }],
206 }
207 )
208 }
209
210 const SUBS_COMPLEX: &[u8] = &[
219 0x00, 0x00, 0x00, 0x9C, 0x73, 0x75, 0x62, 0x73, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
220 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0F, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221 0x05, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x00,
222 0x00, 0x0B, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xA3, 0x00, 0x00, 0x00, 0x00,
223 0x00, 0x00, 0x05, 0xF5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x4A, 0x00, 0x00, 0x00,
224 0x00, 0x00, 0x00, 0x05, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
225 0x00, 0x08, 0x00, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB, 0x00, 0x00, 0x00,
226 0x00, 0x00, 0x00, 0x02, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xDE, 0x00, 0x00,
227 0x00, 0x00, 0x00, 0x00, 0x05, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x4A, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF6,
229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 ];
231
232 #[test]
233 fn subs_decodes_from_bytes_and_encodes_to_bytes_correctly_with_more_complex_example() {
234 let mut buf = Cursor::new(SUBS_COMPLEX);
235 let subs = Subs {
236 flags: [0, 0, 2],
237 entries: vec![
238 SubsEntry {
239 sample_delta: 0,
240 subsamples: vec![
241 SubsSubsample {
242 size: SubsSubsampleSize::U16(3991),
243 priority: 0,
244 discardable: false,
245 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
246 },
247 SubsSubsample {
248 size: SubsSubsampleSize::U16(1362),
249 priority: 0,
250 discardable: false,
251 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
252 },
253 SubsSubsample {
254 size: SubsSubsampleSize::U16(1443),
255 priority: 0,
256 discardable: false,
257 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
258 },
259 SubsSubsample {
260 size: SubsSubsampleSize::U16(2952),
261 priority: 0,
262 discardable: false,
263 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
264 },
265 SubsSubsample {
266 size: SubsSubsampleSize::U16(1955),
267 priority: 0,
268 discardable: false,
269 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
270 },
271 SubsSubsample {
272 size: SubsSubsampleSize::U16(1525),
273 priority: 0,
274 discardable: false,
275 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
276 },
277 SubsSubsample {
278 size: SubsSubsampleSize::U16(842),
279 priority: 0,
280 discardable: false,
281 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
282 },
283 SubsSubsample {
284 size: SubsSubsampleSize::U16(1386),
285 priority: 0,
286 discardable: false,
287 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
288 },
289 ],
290 },
291 SubsEntry {
292 sample_delta: 1,
293 subsamples: vec![
294 SubsSubsample {
295 size: SubsSubsampleSize::U16(194),
296 priority: 0,
297 discardable: false,
298 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
299 },
300 SubsSubsample {
301 size: SubsSubsampleSize::U16(171),
302 priority: 0,
303 discardable: false,
304 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
305 },
306 SubsSubsample {
307 size: SubsSubsampleSize::U16(736),
308 priority: 0,
309 discardable: false,
310 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
311 },
312 SubsSubsample {
313 size: SubsSubsampleSize::U16(734),
314 priority: 0,
315 discardable: false,
316 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
317 },
318 SubsSubsample {
319 size: SubsSubsampleSize::U16(1470),
320 priority: 0,
321 discardable: false,
322 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
323 },
324 SubsSubsample {
325 size: SubsSubsampleSize::U16(330),
326 priority: 0,
327 discardable: false,
328 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
329 },
330 SubsSubsample {
331 size: SubsSubsampleSize::U16(150),
332 priority: 0,
333 discardable: false,
334 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
335 },
336 SubsSubsample {
337 size: SubsSubsampleSize::U16(1014),
338 priority: 0,
339 discardable: false,
340 codec_specific_parameters: 0u32.to_be_bytes().to_vec(),
341 },
342 ],
343 },
344 ],
345 };
346 let decoded = Subs::decode(&mut buf).expect("subs should decode successfully");
347 assert_eq!(subs, decoded);
348 let mut encoded = Vec::new();
349 subs.encode(&mut encoded)
350 .expect("encode should be successful");
351 assert_eq!(SUBS_COMPLEX, &encoded);
352 }
353}