1use crate::error::{Error, Result};
31use crate::init_segment::bounded_entry_count;
32use alloc::vec::Vec;
33
34use broadcast_common::{Parse, Serialize};
35
36const BOX_HEADER_SIZE: usize = 8;
41const FULLBOX_EXTRA_SIZE: usize = 4;
42
43const PRFT_TYPE: u32 = u32::from_be_bytes(*b"prft");
44const SGPD_TYPE: u32 = u32::from_be_bytes(*b"sgpd");
45const SBGP_TYPE: u32 = u32::from_be_bytes(*b"sbgp");
46const SUBS_TYPE: u32 = u32::from_be_bytes(*b"subs");
47
48pub const GROUPING_TYPE_ROLL: u32 = u32::from_be_bytes(*b"roll");
50
51pub const GROUPING_TYPE_SEIG: u32 = u32::from_be_bytes(*b"seig");
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
84#[cfg_attr(feature = "serde", derive(serde::Serialize))]
85pub struct ProducerReferenceTimeBox {
86 pub version: u8,
88 pub flags: u32,
90 pub reference_track_id: u32,
92 pub ntp_timestamp: u64,
94 pub media_time: u64,
98}
99
100impl ProducerReferenceTimeBox {
101 pub fn parse_body(body: &[u8]) -> Result<Self> {
103 let min = FULLBOX_EXTRA_SIZE + 4 + 8;
105 if body.len() < min {
106 return Err(Error::BufferTooShort {
107 need: min,
108 have: body.len(),
109 what: "prft body",
110 });
111 }
112 let version = body[0];
113 let flags = u32::from_be_bytes([0, body[1], body[2], body[3]]);
114 let mut c = FULLBOX_EXTRA_SIZE;
115 let reference_track_id =
116 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
117 c += 4;
118 let ntp_timestamp = u64::from_be_bytes([
119 body[c],
120 body[c + 1],
121 body[c + 2],
122 body[c + 3],
123 body[c + 4],
124 body[c + 5],
125 body[c + 6],
126 body[c + 7],
127 ]);
128 c += 8;
129 let media_time = if version == 0 {
130 if body.len() < c + 4 {
131 return Err(Error::BufferTooShort {
132 need: c + 4,
133 have: body.len(),
134 what: "prft media_time v0",
135 });
136 }
137 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]) as u64
138 } else {
139 if body.len() < c + 8 {
140 return Err(Error::BufferTooShort {
141 need: c + 8,
142 have: body.len(),
143 what: "prft media_time v1",
144 });
145 }
146 u64::from_be_bytes([
147 body[c],
148 body[c + 1],
149 body[c + 2],
150 body[c + 3],
151 body[c + 4],
152 body[c + 5],
153 body[c + 6],
154 body[c + 7],
155 ])
156 };
157 Ok(Self {
158 version,
159 flags,
160 reference_track_id,
161 ntp_timestamp,
162 media_time,
163 })
164 }
165}
166
167impl<'a> Parse<'a> for ProducerReferenceTimeBox {
168 type Error = Error;
169 fn parse(bytes: &'a [u8]) -> Result<Self> {
170 if bytes.len() < BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 + 8 + 4 {
171 return Err(Error::BufferTooShort {
172 need: BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 + 8 + 4,
173 have: bytes.len(),
174 what: "prft box",
175 });
176 }
177 let ty = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
178 if ty != PRFT_TYPE {
179 return Err(Error::InvalidValue {
180 field: "box_type",
181 value: ty as u64,
182 reason: "expected prft",
183 });
184 }
185 Self::parse_body(&bytes[BOX_HEADER_SIZE..])
186 }
187}
188
189impl Serialize for ProducerReferenceTimeBox {
190 type Error = Error;
191 fn serialized_len(&self) -> usize {
192 let mt_size = if self.version == 0 { 4 } else { 8 };
193 BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 + 8 + mt_size
194 }
195 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
196 let need = self.serialized_len();
197 if buf.len() < need {
198 return Err(Error::OutputBufferTooSmall {
199 need,
200 have: buf.len(),
201 });
202 }
203 let mut c = 0;
204 buf[c..c + 4].copy_from_slice(&(need as u32).to_be_bytes());
205 c += 4;
206 buf[c..c + 4].copy_from_slice(b"prft");
207 c += 4;
208 buf[c] = self.version;
209 let fb = self.flags.to_be_bytes();
210 buf[c + 1] = fb[1];
211 buf[c + 2] = fb[2];
212 buf[c + 3] = fb[3];
213 c += 4;
214 buf[c..c + 4].copy_from_slice(&self.reference_track_id.to_be_bytes());
215 c += 4;
216 buf[c..c + 8].copy_from_slice(&self.ntp_timestamp.to_be_bytes());
217 c += 8;
218 if self.version == 0 {
219 buf[c..c + 4].copy_from_slice(&(self.media_time as u32).to_be_bytes());
220 c += 4;
221 } else {
222 buf[c..c + 8].copy_from_slice(&self.media_time.to_be_bytes());
223 c += 8;
224 }
225 Ok(c)
226 }
227}
228
229#[derive(Debug, Clone, PartialEq, Eq)]
238#[cfg_attr(feature = "serde", derive(serde::Serialize))]
239#[non_exhaustive]
240pub enum SgpdEntry {
241 Roll {
246 roll_distance: i16,
248 },
249 Unknown(Vec<u8>),
251}
252
253impl SgpdEntry {
254 pub fn wire_len(&self) -> usize {
256 match self {
257 Self::Roll { .. } => 2,
258 Self::Unknown(v) => v.len(),
259 }
260 }
261}
262
263#[derive(Debug, Clone, PartialEq, Eq)]
283#[cfg_attr(feature = "serde", derive(serde::Serialize))]
284pub struct SampleGroupDescriptionBox {
285 pub version: u8,
287 pub flags: u32,
289 pub grouping_type: u32,
291 pub default_length: u32,
297 pub entries: Vec<SgpdEntry>,
299}
300
301impl SampleGroupDescriptionBox {
302 pub fn parse_body(body: &[u8]) -> Result<Self> {
304 if body.len() < FULLBOX_EXTRA_SIZE + 4 + 4 {
305 return Err(Error::BufferTooShort {
306 need: FULLBOX_EXTRA_SIZE + 4 + 4,
307 have: body.len(),
308 what: "sgpd body",
309 });
310 }
311 let version = body[0];
312 let flags = u32::from_be_bytes([0, body[1], body[2], body[3]]);
313 let mut c = FULLBOX_EXTRA_SIZE;
314 let grouping_type = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
315 c += 4;
316
317 let default_length = if version == 1 {
318 if body.len() < c + 4 {
319 return Err(Error::BufferTooShort {
320 need: c + 4,
321 have: body.len(),
322 what: "sgpd default_length",
323 });
324 }
325 let dl = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
326 c += 4;
327 dl
328 } else if version >= 2 {
329 if body.len() < c + 4 {
331 return Err(Error::BufferTooShort {
332 need: c + 4,
333 have: body.len(),
334 what: "sgpd default_sample_description_index",
335 });
336 }
337 c += 4; 0
339 } else {
340 0 };
342
343 if body.len() < c + 4 {
344 return Err(Error::BufferTooShort {
345 need: c + 4,
346 have: body.len(),
347 what: "sgpd entry_count",
348 });
349 }
350 let entry_count =
351 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]) as usize;
352 c += 4;
353
354 let sgpd_min_entry_len: usize = if version == 1 {
361 if default_length == 0 {
362 4
363 } else {
364 default_length as usize
365 }
366 } else if grouping_type == GROUPING_TYPE_ROLL {
367 2
368 } else {
369 1
370 };
371 let mut entries = Vec::with_capacity(bounded_entry_count(
372 body.len().saturating_sub(c),
373 sgpd_min_entry_len,
374 entry_count,
375 ));
376 for _ in 0..entry_count {
377 let entry_len: usize = if version == 1 && default_length == 0 {
379 if body.len() < c + 4 {
380 return Err(Error::BufferTooShort {
381 need: c + 4,
382 have: body.len(),
383 what: "sgpd description_length",
384 });
385 }
386 let dl =
387 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]) as usize;
388 c += 4;
389 dl
390 } else if version == 1 {
391 default_length as usize
392 } else {
393 if grouping_type == GROUPING_TYPE_ROLL {
397 2
398 } else {
399 body.len() - c
401 }
402 };
403 if body.len() < c + entry_len {
404 return Err(Error::BufferTooShort {
405 need: c + entry_len,
406 have: body.len(),
407 what: "sgpd entry body",
408 });
409 }
410 let entry_bytes = &body[c..c + entry_len];
411 let entry = if grouping_type == GROUPING_TYPE_ROLL && entry_len >= 2 {
412 let rd = i16::from_be_bytes([entry_bytes[0], entry_bytes[1]]);
413 SgpdEntry::Roll { roll_distance: rd }
414 } else {
415 SgpdEntry::Unknown(entry_bytes.to_vec())
416 };
417 entries.push(entry);
418 c += entry_len;
419 }
420
421 Ok(Self {
422 version,
423 flags,
424 grouping_type,
425 default_length,
426 entries,
427 })
428 }
429}
430
431impl<'a> Parse<'a> for SampleGroupDescriptionBox {
432 type Error = Error;
433 fn parse(bytes: &'a [u8]) -> Result<Self> {
434 if bytes.len() < BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 {
435 return Err(Error::BufferTooShort {
436 need: BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4,
437 have: bytes.len(),
438 what: "sgpd box",
439 });
440 }
441 let ty = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
442 if ty != SGPD_TYPE {
443 return Err(Error::InvalidValue {
444 field: "box_type",
445 value: ty as u64,
446 reason: "expected sgpd",
447 });
448 }
449 Self::parse_body(&bytes[BOX_HEADER_SIZE..])
450 }
451}
452
453impl Serialize for SampleGroupDescriptionBox {
454 type Error = Error;
455 fn serialized_len(&self) -> usize {
456 let (use_default_len, per_entry_prefix) = self.effective_default_length();
458 let entry_overhead = if per_entry_prefix { 4 } else { 0 };
459 let entries_size: usize = self
460 .entries
461 .iter()
462 .map(|e| entry_overhead + e.wire_len())
463 .sum();
464 let dl_field = if self.version == 1 { 4 } else { 0 };
466 let _ = use_default_len;
467 BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 + dl_field + 4 + entries_size
468 }
469
470 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
471 let need = self.serialized_len();
472 if buf.len() < need {
473 return Err(Error::OutputBufferTooSmall {
474 need,
475 have: buf.len(),
476 });
477 }
478 let (effective_dl, per_entry_prefix) = self.effective_default_length();
479 let mut c = 0;
480 buf[c..c + 4].copy_from_slice(&(need as u32).to_be_bytes());
481 c += 4;
482 buf[c..c + 4].copy_from_slice(b"sgpd");
483 c += 4;
484 buf[c] = self.version;
485 let fb = self.flags.to_be_bytes();
486 buf[c + 1] = fb[1];
487 buf[c + 2] = fb[2];
488 buf[c + 3] = fb[3];
489 c += 4;
490 buf[c..c + 4].copy_from_slice(&self.grouping_type.to_be_bytes());
491 c += 4;
492 if self.version == 1 {
493 buf[c..c + 4].copy_from_slice(&effective_dl.to_be_bytes());
494 c += 4;
495 }
496 buf[c..c + 4].copy_from_slice(&(self.entries.len() as u32).to_be_bytes());
497 c += 4;
498 for entry in &self.entries {
499 if per_entry_prefix {
500 buf[c..c + 4].copy_from_slice(&(entry.wire_len() as u32).to_be_bytes());
501 c += 4;
502 }
503 match entry {
504 SgpdEntry::Roll { roll_distance } => {
505 buf[c..c + 2].copy_from_slice(&roll_distance.to_be_bytes());
506 c += 2;
507 }
508 SgpdEntry::Unknown(v) => {
509 buf[c..c + v.len()].copy_from_slice(v);
510 c += v.len();
511 }
512 }
513 }
514 Ok(c)
515 }
516}
517
518impl SampleGroupDescriptionBox {
519 fn effective_default_length(&self) -> (u32, bool) {
524 if self.version != 1 || self.entries.is_empty() {
525 return (0, false);
526 }
527 let first = self.entries[0].wire_len();
528 let uniform = self.entries.iter().all(|e| e.wire_len() == first);
529 if uniform {
530 (first as u32, false)
531 } else {
532 (0, true)
533 }
534 }
535}
536
537#[derive(Debug, Clone, Copy, PartialEq, Eq)]
543#[cfg_attr(feature = "serde", derive(serde::Serialize))]
544pub struct SbgpEntry {
545 pub sample_count: u32,
547 pub group_description_index: u32,
549}
550
551#[derive(Debug, Clone, PartialEq, Eq)]
564#[cfg_attr(feature = "serde", derive(serde::Serialize))]
565pub struct SampleToGroupBox {
566 pub version: u8,
568 pub flags: u32,
570 pub grouping_type: u32,
572 pub grouping_type_parameter: Option<u32>,
574 pub entries: Vec<SbgpEntry>,
576}
577
578impl SampleToGroupBox {
579 pub fn parse_body(body: &[u8]) -> Result<Self> {
581 if body.len() < FULLBOX_EXTRA_SIZE + 4 + 4 {
582 return Err(Error::BufferTooShort {
583 need: FULLBOX_EXTRA_SIZE + 4 + 4,
584 have: body.len(),
585 what: "sbgp body",
586 });
587 }
588 let version = body[0];
589 let flags = u32::from_be_bytes([0, body[1], body[2], body[3]]);
590 let mut c = FULLBOX_EXTRA_SIZE;
591 let grouping_type = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
592 c += 4;
593 let grouping_type_parameter = if version == 1 {
594 if body.len() < c + 4 {
595 return Err(Error::BufferTooShort {
596 need: c + 4,
597 have: body.len(),
598 what: "sbgp grouping_type_parameter",
599 });
600 }
601 let v = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
602 c += 4;
603 Some(v)
604 } else {
605 None
606 };
607 if body.len() < c + 4 {
608 return Err(Error::BufferTooShort {
609 need: c + 4,
610 have: body.len(),
611 what: "sbgp entry_count",
612 });
613 }
614 let entry_count =
615 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]) as usize;
616 c += 4;
617 let mut entries = Vec::with_capacity(bounded_entry_count(
619 body.len().saturating_sub(c),
620 8,
621 entry_count,
622 ));
623 for _ in 0..entry_count {
624 if body.len() < c + 8 {
625 return Err(Error::BufferTooShort {
626 need: c + 8,
627 have: body.len(),
628 what: "sbgp entry",
629 });
630 }
631 let sample_count = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
632 let group_description_index =
633 u32::from_be_bytes([body[c + 4], body[c + 5], body[c + 6], body[c + 7]]);
634 entries.push(SbgpEntry {
635 sample_count,
636 group_description_index,
637 });
638 c += 8;
639 }
640 Ok(Self {
641 version,
642 flags,
643 grouping_type,
644 grouping_type_parameter,
645 entries,
646 })
647 }
648}
649
650impl<'a> Parse<'a> for SampleToGroupBox {
651 type Error = Error;
652 fn parse(bytes: &'a [u8]) -> Result<Self> {
653 if bytes.len() < BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 {
654 return Err(Error::BufferTooShort {
655 need: BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4,
656 have: bytes.len(),
657 what: "sbgp box",
658 });
659 }
660 let ty = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
661 if ty != SBGP_TYPE {
662 return Err(Error::InvalidValue {
663 field: "box_type",
664 value: ty as u64,
665 reason: "expected sbgp",
666 });
667 }
668 Self::parse_body(&bytes[BOX_HEADER_SIZE..])
669 }
670}
671
672impl Serialize for SampleToGroupBox {
673 type Error = Error;
674 fn serialized_len(&self) -> usize {
675 let gtp_size = if self.version == 1 { 4 } else { 0 };
676 BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 + gtp_size + 4 + self.entries.len() * 8
677 }
678 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
679 let need = self.serialized_len();
680 if buf.len() < need {
681 return Err(Error::OutputBufferTooSmall {
682 need,
683 have: buf.len(),
684 });
685 }
686 let mut c = 0;
687 buf[c..c + 4].copy_from_slice(&(need as u32).to_be_bytes());
688 c += 4;
689 buf[c..c + 4].copy_from_slice(b"sbgp");
690 c += 4;
691 buf[c] = self.version;
692 let fb = self.flags.to_be_bytes();
693 buf[c + 1] = fb[1];
694 buf[c + 2] = fb[2];
695 buf[c + 3] = fb[3];
696 c += 4;
697 buf[c..c + 4].copy_from_slice(&self.grouping_type.to_be_bytes());
698 c += 4;
699 if self.version == 1 {
700 let gtp = self.grouping_type_parameter.unwrap_or(0);
701 buf[c..c + 4].copy_from_slice(>p.to_be_bytes());
702 c += 4;
703 }
704 buf[c..c + 4].copy_from_slice(&(self.entries.len() as u32).to_be_bytes());
705 c += 4;
706 for entry in &self.entries {
707 buf[c..c + 4].copy_from_slice(&entry.sample_count.to_be_bytes());
708 buf[c + 4..c + 8].copy_from_slice(&entry.group_description_index.to_be_bytes());
709 c += 8;
710 }
711 Ok(c)
712 }
713}
714
715#[derive(Debug, Clone, Copy, PartialEq, Eq)]
724#[cfg_attr(feature = "serde", derive(serde::Serialize))]
725pub struct SubSampleDescriptor {
726 pub subsample_size: u32,
728 pub subsample_priority: u8,
730 pub discardable: u8,
732 pub codec_specific_parameters: u32,
734}
735
736impl SubSampleDescriptor {
737 fn wire_len(version: u8) -> usize {
738 let size_field = if version == 1 { 4 } else { 2 };
739 size_field + 1 + 1 + 4
740 }
741}
742
743#[derive(Debug, Clone, PartialEq, Eq)]
745#[cfg_attr(feature = "serde", derive(serde::Serialize))]
746pub struct SubsEntry {
747 pub sample_delta: u32,
750 pub subsamples: Vec<SubSampleDescriptor>,
752}
753
754impl SubsEntry {
755 fn wire_len(&self, version: u8) -> usize {
756 4 + 2 + self.subsamples.len() * SubSampleDescriptor::wire_len(version)
757 }
758}
759
760#[derive(Debug, Clone, PartialEq, Eq)]
776#[cfg_attr(feature = "serde", derive(serde::Serialize))]
777pub struct SubSampleInformationBox {
778 pub version: u8,
780 pub flags: u32,
782 pub entries: Vec<SubsEntry>,
784}
785
786impl SubSampleInformationBox {
787 pub fn parse_body(body: &[u8]) -> Result<Self> {
789 if body.len() < FULLBOX_EXTRA_SIZE + 4 {
790 return Err(Error::BufferTooShort {
791 need: FULLBOX_EXTRA_SIZE + 4,
792 have: body.len(),
793 what: "subs body",
794 });
795 }
796 let version = body[0];
797 let flags = u32::from_be_bytes([0, body[1], body[2], body[3]]);
798 let mut c = FULLBOX_EXTRA_SIZE;
799 let entry_count =
800 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]) as usize;
801 c += 4;
802 let ss_size_field = if version == 1 { 4usize } else { 2usize };
803 let mut entries = Vec::with_capacity(bounded_entry_count(
807 body.len().saturating_sub(c),
808 4 + 2,
809 entry_count,
810 ));
811 for _ in 0..entry_count {
812 if body.len() < c + 4 + 2 {
813 return Err(Error::BufferTooShort {
814 need: c + 6,
815 have: body.len(),
816 what: "subs entry header",
817 });
818 }
819 let sample_delta = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
820 c += 4;
821 let subsample_count = u16::from_be_bytes([body[c], body[c + 1]]) as usize;
822 c += 2;
823 let ss_wire = ss_size_field + 1 + 1 + 4;
824 let mut subsamples = Vec::with_capacity(bounded_entry_count(
825 body.len().saturating_sub(c),
826 ss_wire,
827 subsample_count,
828 ));
829 for _ in 0..subsample_count {
830 if body.len() < c + ss_wire {
831 return Err(Error::BufferTooShort {
832 need: c + ss_wire,
833 have: body.len(),
834 what: "subs subsample",
835 });
836 }
837 let subsample_size = if version == 1 {
838 let v = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
839 c += 4;
840 v
841 } else {
842 let v = u16::from_be_bytes([body[c], body[c + 1]]) as u32;
843 c += 2;
844 v
845 };
846 let subsample_priority = body[c];
847 let discardable = body[c + 1];
848 c += 2;
849 let codec_specific_parameters =
850 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
851 c += 4;
852 subsamples.push(SubSampleDescriptor {
853 subsample_size,
854 subsample_priority,
855 discardable,
856 codec_specific_parameters,
857 });
858 }
859 entries.push(SubsEntry {
860 sample_delta,
861 subsamples,
862 });
863 }
864 Ok(Self {
865 version,
866 flags,
867 entries,
868 })
869 }
870}
871
872impl<'a> Parse<'a> for SubSampleInformationBox {
873 type Error = Error;
874 fn parse(bytes: &'a [u8]) -> Result<Self> {
875 if bytes.len() < BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 {
876 return Err(Error::BufferTooShort {
877 need: BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4,
878 have: bytes.len(),
879 what: "subs box",
880 });
881 }
882 let ty = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
883 if ty != SUBS_TYPE {
884 return Err(Error::InvalidValue {
885 field: "box_type",
886 value: ty as u64,
887 reason: "expected subs",
888 });
889 }
890 Self::parse_body(&bytes[BOX_HEADER_SIZE..])
891 }
892}
893
894impl Serialize for SubSampleInformationBox {
895 type Error = Error;
896 fn serialized_len(&self) -> usize {
897 let entries_size: usize = self.entries.iter().map(|e| e.wire_len(self.version)).sum();
898 BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 + entries_size
899 }
900 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
901 let need = self.serialized_len();
902 if buf.len() < need {
903 return Err(Error::OutputBufferTooSmall {
904 need,
905 have: buf.len(),
906 });
907 }
908 let mut c = 0;
909 buf[c..c + 4].copy_from_slice(&(need as u32).to_be_bytes());
910 c += 4;
911 buf[c..c + 4].copy_from_slice(b"subs");
912 c += 4;
913 buf[c] = self.version;
914 let fb = self.flags.to_be_bytes();
915 buf[c + 1] = fb[1];
916 buf[c + 2] = fb[2];
917 buf[c + 3] = fb[3];
918 c += 4;
919 buf[c..c + 4].copy_from_slice(&(self.entries.len() as u32).to_be_bytes());
920 c += 4;
921 for entry in &self.entries {
922 buf[c..c + 4].copy_from_slice(&entry.sample_delta.to_be_bytes());
923 c += 4;
924 buf[c..c + 2].copy_from_slice(&(entry.subsamples.len() as u16).to_be_bytes());
925 c += 2;
926 for ss in &entry.subsamples {
927 if self.version == 1 {
928 buf[c..c + 4].copy_from_slice(&ss.subsample_size.to_be_bytes());
929 c += 4;
930 } else {
931 buf[c..c + 2].copy_from_slice(&(ss.subsample_size as u16).to_be_bytes());
932 c += 2;
933 }
934 buf[c] = ss.subsample_priority;
935 buf[c + 1] = ss.discardable;
936 c += 2;
937 buf[c..c + 4].copy_from_slice(&ss.codec_specific_parameters.to_be_bytes());
938 c += 4;
939 }
940 }
941 Ok(c)
942 }
943}
944
945#[cfg(test)]
950mod tests {
951 use super::*;
952 use broadcast_common::Serialize;
953
954 #[test]
959 fn prft_round_trip_v0() {
960 let b = ProducerReferenceTimeBox {
961 version: 0,
962 flags: 0,
963 reference_track_id: 1,
964 ntp_timestamp: 0x1234_5678_9abc_def0,
965 media_time: 0x0000_0000_0000_1234,
966 };
967 let bytes = b.to_bytes();
968 assert_eq!(bytes.len(), 8 + 4 + 4 + 8 + 4);
969 let parsed = ProducerReferenceTimeBox::parse(&bytes).unwrap();
970 assert_eq!(parsed, b);
971 }
972
973 #[test]
974 fn prft_round_trip_v1() {
975 let b = ProducerReferenceTimeBox {
976 version: 1,
977 flags: 0x000018,
978 reference_track_id: 1,
979 ntp_timestamp: 0xedefe3e3_a7ae147a,
980 media_time: 0x0000_0000_0000_1c20,
981 };
982 let bytes = b.to_bytes();
983 assert_eq!(bytes.len(), 8 + 4 + 4 + 8 + 8);
984 let parsed = ProducerReferenceTimeBox::parse(&bytes).unwrap();
985 assert_eq!(parsed, b);
986 }
987
988 #[test]
993 fn sgpd_round_trip_roll_v1() {
994 let b = SampleGroupDescriptionBox {
995 version: 1,
996 flags: 0,
997 grouping_type: GROUPING_TYPE_ROLL,
998 default_length: 2,
999 entries: vec![SgpdEntry::Roll { roll_distance: -1 }],
1000 };
1001 let bytes = b.to_bytes();
1002 let parsed = SampleGroupDescriptionBox::parse(&bytes).unwrap();
1003 assert_eq!(parsed.entries.len(), 1);
1004 assert_eq!(parsed.entries[0], SgpdEntry::Roll { roll_distance: -1 });
1005 assert_eq!(parsed.to_bytes(), bytes);
1006 }
1007
1008 #[test]
1009 fn sgpd_round_trip_two_roll_entries() {
1010 let b = SampleGroupDescriptionBox {
1011 version: 1,
1012 flags: 0,
1013 grouping_type: GROUPING_TYPE_ROLL,
1014 default_length: 2,
1015 entries: vec![
1016 SgpdEntry::Roll { roll_distance: -4 },
1017 SgpdEntry::Roll { roll_distance: -1 },
1018 ],
1019 };
1020 let bytes = b.to_bytes();
1021 let parsed = SampleGroupDescriptionBox::parse(&bytes).unwrap();
1022 assert_eq!(parsed.entries.len(), 2);
1023 assert_eq!(parsed.to_bytes(), bytes);
1024 }
1025
1026 #[test]
1031 fn sbgp_round_trip_v0() {
1032 let b = SampleToGroupBox {
1033 version: 0,
1034 flags: 0,
1035 grouping_type: GROUPING_TYPE_ROLL,
1036 grouping_type_parameter: None,
1037 entries: vec![
1038 SbgpEntry {
1039 sample_count: 1,
1040 group_description_index: 1,
1041 },
1042 SbgpEntry {
1043 sample_count: 10,
1044 group_description_index: 0,
1045 },
1046 ],
1047 };
1048 let bytes = b.to_bytes();
1049 let parsed = SampleToGroupBox::parse(&bytes).unwrap();
1050 assert_eq!(parsed, b);
1051 }
1052
1053 #[test]
1054 fn sbgp_round_trip_v1() {
1055 let b = SampleToGroupBox {
1056 version: 1,
1057 flags: 0,
1058 grouping_type: GROUPING_TYPE_ROLL,
1059 grouping_type_parameter: Some(0xDEAD_BEEF),
1060 entries: vec![SbgpEntry {
1061 sample_count: 5,
1062 group_description_index: 1,
1063 }],
1064 };
1065 let bytes = b.to_bytes();
1066 let parsed = SampleToGroupBox::parse(&bytes).unwrap();
1067 assert_eq!(parsed, b);
1068 }
1069
1070 #[test]
1075 fn subs_round_trip_v0() {
1076 let b = SubSampleInformationBox {
1077 version: 0,
1078 flags: 0,
1079 entries: vec![SubsEntry {
1080 sample_delta: 1,
1081 subsamples: vec![
1082 SubSampleDescriptor {
1083 subsample_size: 100,
1084 subsample_priority: 255,
1085 discardable: 0,
1086 codec_specific_parameters: 0,
1087 },
1088 SubSampleDescriptor {
1089 subsample_size: 200,
1090 subsample_priority: 128,
1091 discardable: 1,
1092 codec_specific_parameters: 0,
1093 },
1094 ],
1095 }],
1096 };
1097 let bytes = b.to_bytes();
1098 let parsed = SubSampleInformationBox::parse(&bytes).unwrap();
1099 assert_eq!(parsed, b);
1100 assert_eq!(parsed.to_bytes(), bytes);
1101 }
1102
1103 #[test]
1104 fn subs_round_trip_v1() {
1105 let b = SubSampleInformationBox {
1106 version: 1,
1107 flags: 0,
1108 entries: vec![SubsEntry {
1109 sample_delta: 5,
1110 subsamples: vec![SubSampleDescriptor {
1111 subsample_size: 0x0001_2345,
1112 subsample_priority: 200,
1113 discardable: 0,
1114 codec_specific_parameters: 0xABCD_EF01,
1115 }],
1116 }],
1117 };
1118 let bytes = b.to_bytes();
1119 let parsed = SubSampleInformationBox::parse(&bytes).unwrap();
1120 assert_eq!(parsed, b);
1121 assert_eq!(parsed.to_bytes(), bytes);
1122 }
1123
1124 #[test]
1125 fn subs_empty_round_trip() {
1126 let b = SubSampleInformationBox {
1127 version: 0,
1128 flags: 0,
1129 entries: vec![],
1130 };
1131 let bytes = b.to_bytes();
1132 let parsed = SubSampleInformationBox::parse(&bytes).unwrap();
1133 assert_eq!(parsed, b);
1134 }
1135}