1use std::io;
2
3use scuffle_bytes_util::BitWriter;
4use scuffle_bytes_util::zero_copy::{Deserialize, DeserializeSeed, Serialize, U24Be, ZeroCopyReader};
5
6use super::SampleGroupDescriptionEntry;
7use crate::{BoxHeader, FullBoxHeader, IsoBox, IsoSized};
8
9#[derive(IsoBox, Debug, PartialEq, Eq)]
13#[iso_box(box_type = b"sbgp", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
14pub struct SampleToGroupBox {
15 pub full_header: FullBoxHeader,
17 pub grouping_type: [u8; 4],
22 pub grouping_type_parameter: Option<u32>,
24 pub entry_count: u32,
26 pub entries: Vec<SampleToGroupBoxEntry>,
28}
29
30impl<'a> DeserializeSeed<'a, BoxHeader> for SampleToGroupBox {
31 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
32 where
33 R: ZeroCopyReader<'a>,
34 {
35 let full_header = FullBoxHeader::deserialize(&mut reader)?;
36
37 let grouping_type = <[u8; 4]>::deserialize(&mut reader)?;
38 let grouping_type_parameter = if full_header.version == 1 {
39 Some(u32::deserialize(&mut reader)?)
40 } else {
41 None
42 };
43
44 let entry_count = u32::deserialize(&mut reader)?;
45 let mut entries = Vec::with_capacity(entry_count as usize);
46 for _ in 0..entry_count {
47 entries.push(SampleToGroupBoxEntry::deserialize(&mut reader)?);
48 }
49
50 Ok(Self {
51 full_header,
52 grouping_type,
53 grouping_type_parameter,
54 entry_count,
55 entries,
56 })
57 }
58}
59
60impl Serialize for SampleToGroupBox {
61 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
62 where
63 W: std::io::Write,
64 {
65 self.serialize_box_header(&mut writer)?;
66 self.full_header.serialize(&mut writer)?;
67
68 self.grouping_type.serialize(&mut writer)?;
69 if self.full_header.version == 1 {
70 self.grouping_type_parameter
71 .ok_or(io::Error::new(
72 io::ErrorKind::InvalidData,
73 "grouping_type_parameter is required",
74 ))?
75 .serialize(&mut writer)?;
76 }
77
78 self.entry_count.serialize(&mut writer)?;
79 for entry in &self.entries {
80 entry.serialize(&mut writer)?;
81 }
82
83 Ok(())
84 }
85}
86
87impl IsoSized for SampleToGroupBox {
88 fn size(&self) -> usize {
89 let mut size = self.full_header.size();
90 size += 4; if self.full_header.version == 1 {
92 size += 4; }
94 size += 4; size += self.entries.size();
96
97 Self::add_header_size(size)
98 }
99}
100
101#[derive(Debug, PartialEq, Eq)]
103pub struct SampleToGroupBoxEntry {
104 pub sample_count: u32,
112 pub group_description_index: u32,
117}
118
119impl<'a> Deserialize<'a> for SampleToGroupBoxEntry {
120 fn deserialize<R>(mut reader: R) -> io::Result<Self>
121 where
122 R: ZeroCopyReader<'a>,
123 {
124 Ok(Self {
125 sample_count: u32::deserialize(&mut reader)?,
126 group_description_index: u32::deserialize(&mut reader)?,
127 })
128 }
129}
130
131impl Serialize for SampleToGroupBoxEntry {
132 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
133 where
134 W: std::io::Write,
135 {
136 self.sample_count.serialize(&mut writer)?;
137 self.group_description_index.serialize(&mut writer)?;
138 Ok(())
139 }
140}
141
142impl IsoSized for SampleToGroupBoxEntry {
143 fn size(&self) -> usize {
144 4 + 4 }
146}
147
148#[derive(IsoBox, Debug, PartialEq, Eq)]
152#[iso_box(box_type = b"sgpd", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
153pub struct SampleGroupDescriptionBox<'a> {
154 pub full_header: FullBoxHeader,
156 pub grouping_type: [u8; 4],
158 pub default_length: Option<u32>,
160 pub default_group_description_index: Option<u32>,
165 pub entry_count: u32,
167 pub entries: Vec<SampleGroupDescriptionEntry<'a>>,
169}
170
171impl<'a> DeserializeSeed<'a, BoxHeader> for SampleGroupDescriptionBox<'a> {
172 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
173 where
174 R: ZeroCopyReader<'a>,
175 {
176 let full_header = FullBoxHeader::deserialize(&mut reader)?;
177
178 let grouping_type = <[u8; 4]>::deserialize(&mut reader)?;
179 let default_length = if full_header.version >= 1 {
180 Some(u32::deserialize(&mut reader)?)
181 } else {
182 None
183 };
184 let default_group_description_index = if full_header.version >= 2 {
185 Some(u32::deserialize(&mut reader)?)
186 } else {
187 None
188 };
189
190 let entry_count = u32::deserialize(&mut reader)?;
191 let mut entries = Vec::with_capacity(entry_count as usize);
192 for _ in 0..entry_count {
193 let description_length = if default_length.is_some_and(|l| l == 0) {
194 Some(u32::deserialize(&mut reader)?)
195 } else {
196 None
197 };
198
199 let length = description_length.or(default_length);
200
201 let sample_group_description_entry =
202 SampleGroupDescriptionEntry::deserialize_seed(&mut reader, (grouping_type, length))?;
203
204 entries.push(sample_group_description_entry);
205 }
206
207 Ok(Self {
208 full_header,
209 grouping_type,
210 default_length,
211 default_group_description_index,
212 entry_count,
213 entries,
214 })
215 }
216}
217
218impl Serialize for SampleGroupDescriptionBox<'_> {
219 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
220 where
221 W: std::io::Write,
222 {
223 self.serialize_box_header(&mut writer)?;
224 self.full_header.serialize(&mut writer)?;
225
226 self.grouping_type.serialize(&mut writer)?;
227 if self.full_header.version >= 1 {
228 self.default_length
229 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "default_length is required"))?
230 .serialize(&mut writer)?;
231 }
232 if self.full_header.version >= 2 {
233 self.default_group_description_index
234 .ok_or(io::Error::new(
235 io::ErrorKind::InvalidData,
236 "default_group_description_index is required",
237 ))?
238 .serialize(&mut writer)?;
239 }
240
241 self.entry_count.serialize(&mut writer)?;
242 for entry in &self.entries {
243 if self.full_header.version >= 1 && self.default_length.is_some_and(|l| l == 0) {
244 (entry.size() as u32).serialize(&mut writer)?;
245 }
246 entry.serialize(&mut writer)?;
247 }
248
249 Ok(())
250 }
251}
252
253impl IsoSized for SampleGroupDescriptionBox<'_> {
254 fn size(&self) -> usize {
255 let mut size = self.full_header.size();
256 size += 4; if self.full_header.version >= 1 {
258 size += 4; }
260 if self.full_header.version >= 2 {
261 size += 4; }
263 size += 4; size += self
265 .entries
266 .iter()
267 .map(|entry| {
268 let mut size = 0;
269 if self.full_header.version >= 1 && self.default_length.is_some_and(|l| l == 0) {
270 size += 4; }
272 size += entry.size();
273 size
274 })
275 .sum::<usize>();
276
277 Self::add_header_size(size)
278 }
279}
280
281#[derive(IsoBox, Debug, PartialEq, Eq)]
285#[iso_box(box_type = b"csgp", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
286pub struct CompactSampleToGroupBox {
287 pub version: u8,
290 pub flags: CompactSampleToGroupBoxFlags,
292 pub grouping_type: [u8; 4],
298 pub grouping_type_parameter: Option<u32>,
300 pub pattern_count: u32,
303 pub patterns: Vec<CompactSampleToGroupBoxPattern>,
305 pub sample_group_description_index: Vec<Vec<CompactSampleToGroupBoxSampleGroupDescriptionIndex>>,
309}
310
311#[derive(Debug, PartialEq, Eq, Clone, Copy)]
313pub struct CompactSampleToGroupBoxFlags {
314 pub index_msb_indicates_fragment_local_description: bool,
323 pub grouping_type_parameter_present: bool,
325 pub pattern_size_code: u8,
332 pub count_size_code: u8,
339 pub index_size_code: u8,
346}
347
348impl<'a> Deserialize<'a> for CompactSampleToGroupBoxFlags {
349 fn deserialize<R>(reader: R) -> io::Result<Self>
350 where
351 R: ZeroCopyReader<'a>,
352 {
353 let value = U24Be::deserialize(reader)?.0;
354
355 Ok(Self {
356 index_msb_indicates_fragment_local_description: (value >> 7) & 0b1 != 0,
357 grouping_type_parameter_present: (value >> 6) & 0b1 != 0,
358 pattern_size_code: ((value >> 4) & 0b11) as u8,
359 count_size_code: ((value >> 2) & 0b11) as u8,
360 index_size_code: (value & 0b11) as u8,
361 })
362 }
363}
364
365impl Serialize for CompactSampleToGroupBoxFlags {
366 fn serialize<W>(&self, writer: W) -> io::Result<()>
367 where
368 W: std::io::Write,
369 {
370 let mut bit_writer = BitWriter::new(writer);
371 bit_writer.write_bit(self.index_msb_indicates_fragment_local_description)?;
372 bit_writer.write_bit(self.grouping_type_parameter_present)?;
373 bit_writer.write_bits(self.pattern_size_code as u64, 2)?;
374 bit_writer.write_bits(self.count_size_code as u64, 2)?;
375 bit_writer.write_bits(self.index_size_code as u64, 2)?;
376 Ok(())
377 }
378}
379
380impl IsoSized for CompactSampleToGroupBoxFlags {
381 fn size(&self) -> usize {
382 3
383 }
384}
385
386impl<'a> DeserializeSeed<'a, BoxHeader> for CompactSampleToGroupBox {
387 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
388 where
389 R: ZeroCopyReader<'a>,
390 {
391 let version = u8::deserialize(&mut reader)?;
392 let flags = CompactSampleToGroupBoxFlags::deserialize(&mut reader)?;
393
394 let grouping_type = <[u8; 4]>::deserialize(&mut reader)?;
395 let grouping_type_parameter = if flags.grouping_type_parameter_present {
396 Some(u32::deserialize(&mut reader)?)
397 } else {
398 None
399 };
400
401 let pattern_count = u32::deserialize(&mut reader)?;
402
403 let mut patterns = Vec::with_capacity(pattern_count as usize);
404 for _ in 0..pattern_count {
405 patterns.push(CompactSampleToGroupBoxPattern::deserialize_seed(&mut reader, flags)?);
406 }
407
408 let mut sample_group_description_index = Vec::with_capacity(pattern_count as usize);
409
410 let mut next_value = None; for pattern in patterns.iter_mut() {
412 let mut current = Vec::with_capacity(pattern.pattern_length as usize);
413
414 for _ in 0..pattern.pattern_length {
415 match flags.index_size_code {
416 0 => match next_value {
417 None => {
418 let byte = u8::deserialize(&mut reader)?;
419
420 let mut value = byte >> 4;
421 let fragment_local = flags.index_msb_indicates_fragment_local_description.then(|| {
422 let msb = (value >> 3) & 0b1 != 0;
424 value &= 0b0111;
425 msb
426 });
427
428 current.push(CompactSampleToGroupBoxSampleGroupDescriptionIndex {
429 value: value as u32,
430 fragment_local,
431 });
432 next_value = Some(byte & 0b0000_1111);
433 }
434 Some(mut value) => {
435 let fragment_local = flags.index_msb_indicates_fragment_local_description.then(|| {
436 let msb = (value >> 3) & 0b1 != 0;
438 value &= 0b0111;
439 msb
440 });
441
442 current.push(CompactSampleToGroupBoxSampleGroupDescriptionIndex {
443 value: value as u32,
444 fragment_local,
445 });
446 next_value = None;
447 }
448 },
449 1 => {
450 let mut value = u8::deserialize(&mut reader)?;
451 let fragment_local = flags.index_msb_indicates_fragment_local_description.then(|| {
452 let msb = (value >> 7) & 0b1 != 0;
454 value &= 0b0111_1111;
455 msb
456 });
457 current.push(CompactSampleToGroupBoxSampleGroupDescriptionIndex {
458 value: value as u32,
459 fragment_local,
460 });
461 }
462 2 => {
463 let mut value = u16::deserialize(&mut reader)?;
464 let fragment_local = flags.index_msb_indicates_fragment_local_description.then(|| {
465 let msb = (value >> 15) & 0b1 != 0;
467 value &= 0b0111_1111_1111_1111;
468 msb
469 });
470
471 current.push(CompactSampleToGroupBoxSampleGroupDescriptionIndex {
472 value: value as u32,
473 fragment_local,
474 });
475 }
476 3 => {
477 let mut value = u32::deserialize(&mut reader)?;
478 let fragment_local = flags.index_msb_indicates_fragment_local_description.then(|| {
479 let msb = (value >> 31) & 0b1 != 0;
481 value &= 0b0111_1111_1111_1111_1111_1111_1111_1111;
482 msb
483 });
484
485 current.push(CompactSampleToGroupBoxSampleGroupDescriptionIndex { value, fragment_local });
486 }
487 _ => unreachable!(),
488 }
489 }
490
491 sample_group_description_index.push(current);
492 }
493
494 Ok(Self {
495 version,
496 flags,
497 grouping_type,
498 grouping_type_parameter,
499 pattern_count,
500 patterns,
501 sample_group_description_index,
502 })
503 }
504}
505
506fn f(index: u8) -> u8 {
507 match index {
508 0 => 4,
509 1 => 8,
510 2 => 16,
511 3 => 32,
512 _ => unreachable!(),
513 }
514}
515
516impl Serialize for CompactSampleToGroupBox {
517 fn serialize<W>(&self, writer: W) -> io::Result<()>
518 where
519 W: std::io::Write,
520 {
521 let mut bit_writer = BitWriter::new(writer);
522
523 self.serialize_box_header(&mut bit_writer)?;
524 self.version.serialize(&mut bit_writer)?;
525 self.flags.serialize(&mut bit_writer)?;
526
527 self.grouping_type.serialize(&mut bit_writer)?;
528
529 if let Some(grouping_type_parameter) = self.grouping_type_parameter {
530 grouping_type_parameter.serialize(&mut bit_writer)?;
531 }
532
533 self.pattern_count.serialize(&mut bit_writer)?;
534 for pattern in &self.patterns {
535 bit_writer.write_bits(pattern.pattern_length as u64, f(self.flags.pattern_size_code))?;
536 bit_writer.write_bits(pattern.sample_count as u64, f(self.flags.count_size_code))?;
537 }
538
539 for j in &self.sample_group_description_index {
540 for k in j {
541 let bit_count = f(self.flags.index_size_code);
542 bit_writer.write_bits(k.to_value(bit_count) as u64, bit_count)?;
543 }
544 }
545
546 bit_writer.align()?;
547
548 Ok(())
549 }
550}
551
552impl IsoSized for CompactSampleToGroupBox {
553 fn size(&self) -> usize {
554 let mut size = 0;
555 size += self.version.size();
556 size += self.flags.size();
557 size += 4; if self.grouping_type_parameter.is_some() {
559 size += 4; }
561 size += 4; let mut bits = 0;
564 bits += (f(self.flags.pattern_size_code) + f(self.flags.count_size_code)) * self.patterns.len() as u8;
565 for j in &self.sample_group_description_index {
566 bits += f(self.flags.index_size_code) * j.len() as u8;
567 }
568 size += (bits as usize).div_ceil(8);
569
570 Self::add_header_size(size)
571 }
572}
573
574#[derive(Debug, PartialEq, Eq)]
576pub struct CompactSampleToGroupBoxPattern {
577 pub pattern_length: u32,
580 pub sample_count: u32,
584}
585
586impl<'a> DeserializeSeed<'a, CompactSampleToGroupBoxFlags> for CompactSampleToGroupBoxPattern {
587 fn deserialize_seed<R>(mut reader: R, seed: CompactSampleToGroupBoxFlags) -> io::Result<Self>
588 where
589 R: ZeroCopyReader<'a>,
590 {
591 if (seed.pattern_size_code == 0) != (seed.count_size_code == 0) {
592 return Err(io::Error::new(
593 io::ErrorKind::InvalidData,
594 "If one of pattern size code and count size is 0, the other must be 0 too".to_string(),
595 ));
596 }
597
598 let mut pattern_length = match seed.pattern_size_code {
599 1 => u8::deserialize(&mut reader)? as u32, 2 => u16::deserialize(&mut reader)? as u32, 3 => u32::deserialize(&mut reader)?, _ => 0, };
604
605 let sample_count = match seed.count_size_code {
606 0 => {
607 let byte = u8::deserialize(&mut reader)?;
609 pattern_length = (byte >> 4) as u32;
610 (byte & 0b0000_1111) as u32
611 }
612 1 => u8::deserialize(&mut reader)? as u32, 2 => u16::deserialize(&mut reader)? as u32, 3 => u32::deserialize(&mut reader)?, _ => unreachable!(),
616 };
617
618 Ok(Self {
619 pattern_length,
620 sample_count,
621 })
622 }
623}
624
625#[derive(Debug, PartialEq, Eq)]
627pub struct CompactSampleToGroupBoxSampleGroupDescriptionIndex {
628 pub value: u32,
633 pub fragment_local: Option<bool>,
635}
636
637impl CompactSampleToGroupBoxSampleGroupDescriptionIndex {
638 pub fn to_value(&self, size: u8) -> u32 {
640 if let Some(fl) = self.fragment_local {
641 let mut value = (fl as u32) << (size - 1);
642 value |= self.value & ((1 << (size - 1)) - 1);
643 value
644 } else {
645 self.value & ((1 << size) - 1)
646 }
647 }
648}