1use crate::error::{Error, Result};
31use alloc::vec::Vec;
32
33use broadcast_common::{Parse, Serialize};
34
35const BOX_HEADER_SIZE: usize = 8;
40const FULLBOX_EXTRA_SIZE: usize = 4;
41
42const PRFT_TYPE: u32 = u32::from_be_bytes(*b"prft");
43const SGPD_TYPE: u32 = u32::from_be_bytes(*b"sgpd");
44const SBGP_TYPE: u32 = u32::from_be_bytes(*b"sbgp");
45const SUBS_TYPE: u32 = u32::from_be_bytes(*b"subs");
46
47pub const GROUPING_TYPE_ROLL: u32 = u32::from_be_bytes(*b"roll");
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71#[cfg_attr(feature = "serde", derive(serde::Serialize))]
72pub struct ProducerReferenceTimeBox {
73 pub version: u8,
75 pub flags: u32,
77 pub reference_track_id: u32,
79 pub ntp_timestamp: u64,
81 pub media_time: u64,
85}
86
87impl ProducerReferenceTimeBox {
88 pub fn parse_body(body: &[u8]) -> Result<Self> {
90 let min = FULLBOX_EXTRA_SIZE + 4 + 8;
92 if body.len() < min {
93 return Err(Error::BufferTooShort {
94 need: min,
95 have: body.len(),
96 what: "prft body",
97 });
98 }
99 let version = body[0];
100 let flags = u32::from_be_bytes([0, body[1], body[2], body[3]]);
101 let mut c = FULLBOX_EXTRA_SIZE;
102 let reference_track_id =
103 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
104 c += 4;
105 let ntp_timestamp = u64::from_be_bytes([
106 body[c],
107 body[c + 1],
108 body[c + 2],
109 body[c + 3],
110 body[c + 4],
111 body[c + 5],
112 body[c + 6],
113 body[c + 7],
114 ]);
115 c += 8;
116 let media_time = if version == 0 {
117 if body.len() < c + 4 {
118 return Err(Error::BufferTooShort {
119 need: c + 4,
120 have: body.len(),
121 what: "prft media_time v0",
122 });
123 }
124 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]) as u64
125 } else {
126 if body.len() < c + 8 {
127 return Err(Error::BufferTooShort {
128 need: c + 8,
129 have: body.len(),
130 what: "prft media_time v1",
131 });
132 }
133 u64::from_be_bytes([
134 body[c],
135 body[c + 1],
136 body[c + 2],
137 body[c + 3],
138 body[c + 4],
139 body[c + 5],
140 body[c + 6],
141 body[c + 7],
142 ])
143 };
144 Ok(Self {
145 version,
146 flags,
147 reference_track_id,
148 ntp_timestamp,
149 media_time,
150 })
151 }
152}
153
154impl<'a> Parse<'a> for ProducerReferenceTimeBox {
155 type Error = Error;
156 fn parse(bytes: &'a [u8]) -> Result<Self> {
157 if bytes.len() < BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 + 8 + 4 {
158 return Err(Error::BufferTooShort {
159 need: BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 + 8 + 4,
160 have: bytes.len(),
161 what: "prft box",
162 });
163 }
164 let ty = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
165 if ty != PRFT_TYPE {
166 return Err(Error::InvalidValue {
167 field: "box_type",
168 value: ty as u64,
169 reason: "expected prft",
170 });
171 }
172 Self::parse_body(&bytes[BOX_HEADER_SIZE..])
173 }
174}
175
176impl Serialize for ProducerReferenceTimeBox {
177 type Error = Error;
178 fn serialized_len(&self) -> usize {
179 let mt_size = if self.version == 0 { 4 } else { 8 };
180 BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 + 8 + mt_size
181 }
182 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
183 let need = self.serialized_len();
184 if buf.len() < need {
185 return Err(Error::OutputBufferTooSmall {
186 need,
187 have: buf.len(),
188 });
189 }
190 let mut c = 0;
191 buf[c..c + 4].copy_from_slice(&(need as u32).to_be_bytes());
192 c += 4;
193 buf[c..c + 4].copy_from_slice(b"prft");
194 c += 4;
195 buf[c] = self.version;
196 let fb = self.flags.to_be_bytes();
197 buf[c + 1] = fb[1];
198 buf[c + 2] = fb[2];
199 buf[c + 3] = fb[3];
200 c += 4;
201 buf[c..c + 4].copy_from_slice(&self.reference_track_id.to_be_bytes());
202 c += 4;
203 buf[c..c + 8].copy_from_slice(&self.ntp_timestamp.to_be_bytes());
204 c += 8;
205 if self.version == 0 {
206 buf[c..c + 4].copy_from_slice(&(self.media_time as u32).to_be_bytes());
207 c += 4;
208 } else {
209 buf[c..c + 8].copy_from_slice(&self.media_time.to_be_bytes());
210 c += 8;
211 }
212 Ok(c)
213 }
214}
215
216#[derive(Debug, Clone, PartialEq, Eq)]
225#[cfg_attr(feature = "serde", derive(serde::Serialize))]
226#[non_exhaustive]
227pub enum SgpdEntry {
228 Roll {
233 roll_distance: i16,
235 },
236 Unknown(Vec<u8>),
238}
239
240impl SgpdEntry {
241 pub fn wire_len(&self) -> usize {
243 match self {
244 Self::Roll { .. } => 2,
245 Self::Unknown(v) => v.len(),
246 }
247 }
248}
249
250#[derive(Debug, Clone, PartialEq, Eq)]
270#[cfg_attr(feature = "serde", derive(serde::Serialize))]
271pub struct SampleGroupDescriptionBox {
272 pub version: u8,
274 pub flags: u32,
276 pub grouping_type: u32,
278 pub default_length: u32,
284 pub entries: Vec<SgpdEntry>,
286}
287
288impl SampleGroupDescriptionBox {
289 pub fn parse_body(body: &[u8]) -> Result<Self> {
291 if body.len() < FULLBOX_EXTRA_SIZE + 4 + 4 {
292 return Err(Error::BufferTooShort {
293 need: FULLBOX_EXTRA_SIZE + 4 + 4,
294 have: body.len(),
295 what: "sgpd body",
296 });
297 }
298 let version = body[0];
299 let flags = u32::from_be_bytes([0, body[1], body[2], body[3]]);
300 let mut c = FULLBOX_EXTRA_SIZE;
301 let grouping_type = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
302 c += 4;
303
304 let default_length = if version == 1 {
305 if body.len() < c + 4 {
306 return Err(Error::BufferTooShort {
307 need: c + 4,
308 have: body.len(),
309 what: "sgpd default_length",
310 });
311 }
312 let dl = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
313 c += 4;
314 dl
315 } else if version >= 2 {
316 if body.len() < c + 4 {
318 return Err(Error::BufferTooShort {
319 need: c + 4,
320 have: body.len(),
321 what: "sgpd default_sample_description_index",
322 });
323 }
324 c += 4; 0
326 } else {
327 0 };
329
330 if body.len() < c + 4 {
331 return Err(Error::BufferTooShort {
332 need: c + 4,
333 have: body.len(),
334 what: "sgpd entry_count",
335 });
336 }
337 let entry_count =
338 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]) as usize;
339 c += 4;
340
341 let mut entries = Vec::with_capacity(entry_count);
342 for _ in 0..entry_count {
343 let entry_len: usize = if version == 1 && default_length == 0 {
345 if body.len() < c + 4 {
346 return Err(Error::BufferTooShort {
347 need: c + 4,
348 have: body.len(),
349 what: "sgpd description_length",
350 });
351 }
352 let dl =
353 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]) as usize;
354 c += 4;
355 dl
356 } else if version == 1 {
357 default_length as usize
358 } else {
359 if grouping_type == GROUPING_TYPE_ROLL {
363 2
364 } else {
365 body.len() - c
367 }
368 };
369 if body.len() < c + entry_len {
370 return Err(Error::BufferTooShort {
371 need: c + entry_len,
372 have: body.len(),
373 what: "sgpd entry body",
374 });
375 }
376 let entry_bytes = &body[c..c + entry_len];
377 let entry = if grouping_type == GROUPING_TYPE_ROLL && entry_len >= 2 {
378 let rd = i16::from_be_bytes([entry_bytes[0], entry_bytes[1]]);
379 SgpdEntry::Roll { roll_distance: rd }
380 } else {
381 SgpdEntry::Unknown(entry_bytes.to_vec())
382 };
383 entries.push(entry);
384 c += entry_len;
385 }
386
387 Ok(Self {
388 version,
389 flags,
390 grouping_type,
391 default_length,
392 entries,
393 })
394 }
395}
396
397impl<'a> Parse<'a> for SampleGroupDescriptionBox {
398 type Error = Error;
399 fn parse(bytes: &'a [u8]) -> Result<Self> {
400 if bytes.len() < BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 {
401 return Err(Error::BufferTooShort {
402 need: BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4,
403 have: bytes.len(),
404 what: "sgpd box",
405 });
406 }
407 let ty = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
408 if ty != SGPD_TYPE {
409 return Err(Error::InvalidValue {
410 field: "box_type",
411 value: ty as u64,
412 reason: "expected sgpd",
413 });
414 }
415 Self::parse_body(&bytes[BOX_HEADER_SIZE..])
416 }
417}
418
419impl Serialize for SampleGroupDescriptionBox {
420 type Error = Error;
421 fn serialized_len(&self) -> usize {
422 let (use_default_len, per_entry_prefix) = self.effective_default_length();
424 let entry_overhead = if per_entry_prefix { 4 } else { 0 };
425 let entries_size: usize = self
426 .entries
427 .iter()
428 .map(|e| entry_overhead + e.wire_len())
429 .sum();
430 let dl_field = if self.version == 1 { 4 } else { 0 };
432 let _ = use_default_len;
433 BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 + dl_field + 4 + entries_size
434 }
435
436 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
437 let need = self.serialized_len();
438 if buf.len() < need {
439 return Err(Error::OutputBufferTooSmall {
440 need,
441 have: buf.len(),
442 });
443 }
444 let (effective_dl, per_entry_prefix) = self.effective_default_length();
445 let mut c = 0;
446 buf[c..c + 4].copy_from_slice(&(need as u32).to_be_bytes());
447 c += 4;
448 buf[c..c + 4].copy_from_slice(b"sgpd");
449 c += 4;
450 buf[c] = self.version;
451 let fb = self.flags.to_be_bytes();
452 buf[c + 1] = fb[1];
453 buf[c + 2] = fb[2];
454 buf[c + 3] = fb[3];
455 c += 4;
456 buf[c..c + 4].copy_from_slice(&self.grouping_type.to_be_bytes());
457 c += 4;
458 if self.version == 1 {
459 buf[c..c + 4].copy_from_slice(&effective_dl.to_be_bytes());
460 c += 4;
461 }
462 buf[c..c + 4].copy_from_slice(&(self.entries.len() as u32).to_be_bytes());
463 c += 4;
464 for entry in &self.entries {
465 if per_entry_prefix {
466 buf[c..c + 4].copy_from_slice(&(entry.wire_len() as u32).to_be_bytes());
467 c += 4;
468 }
469 match entry {
470 SgpdEntry::Roll { roll_distance } => {
471 buf[c..c + 2].copy_from_slice(&roll_distance.to_be_bytes());
472 c += 2;
473 }
474 SgpdEntry::Unknown(v) => {
475 buf[c..c + v.len()].copy_from_slice(v);
476 c += v.len();
477 }
478 }
479 }
480 Ok(c)
481 }
482}
483
484impl SampleGroupDescriptionBox {
485 fn effective_default_length(&self) -> (u32, bool) {
490 if self.version != 1 || self.entries.is_empty() {
491 return (0, false);
492 }
493 let first = self.entries[0].wire_len();
494 let uniform = self.entries.iter().all(|e| e.wire_len() == first);
495 if uniform {
496 (first as u32, false)
497 } else {
498 (0, true)
499 }
500 }
501}
502
503#[derive(Debug, Clone, Copy, PartialEq, Eq)]
509#[cfg_attr(feature = "serde", derive(serde::Serialize))]
510pub struct SbgpEntry {
511 pub sample_count: u32,
513 pub group_description_index: u32,
515}
516
517#[derive(Debug, Clone, PartialEq, Eq)]
530#[cfg_attr(feature = "serde", derive(serde::Serialize))]
531pub struct SampleToGroupBox {
532 pub version: u8,
534 pub flags: u32,
536 pub grouping_type: u32,
538 pub grouping_type_parameter: Option<u32>,
540 pub entries: Vec<SbgpEntry>,
542}
543
544impl SampleToGroupBox {
545 pub fn parse_body(body: &[u8]) -> Result<Self> {
547 if body.len() < FULLBOX_EXTRA_SIZE + 4 + 4 {
548 return Err(Error::BufferTooShort {
549 need: FULLBOX_EXTRA_SIZE + 4 + 4,
550 have: body.len(),
551 what: "sbgp body",
552 });
553 }
554 let version = body[0];
555 let flags = u32::from_be_bytes([0, body[1], body[2], body[3]]);
556 let mut c = FULLBOX_EXTRA_SIZE;
557 let grouping_type = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
558 c += 4;
559 let grouping_type_parameter = if version == 1 {
560 if body.len() < c + 4 {
561 return Err(Error::BufferTooShort {
562 need: c + 4,
563 have: body.len(),
564 what: "sbgp grouping_type_parameter",
565 });
566 }
567 let v = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
568 c += 4;
569 Some(v)
570 } else {
571 None
572 };
573 if body.len() < c + 4 {
574 return Err(Error::BufferTooShort {
575 need: c + 4,
576 have: body.len(),
577 what: "sbgp entry_count",
578 });
579 }
580 let entry_count =
581 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]) as usize;
582 c += 4;
583 let mut entries = Vec::with_capacity(entry_count);
584 for _ in 0..entry_count {
585 if body.len() < c + 8 {
586 return Err(Error::BufferTooShort {
587 need: c + 8,
588 have: body.len(),
589 what: "sbgp entry",
590 });
591 }
592 let sample_count = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
593 let group_description_index =
594 u32::from_be_bytes([body[c + 4], body[c + 5], body[c + 6], body[c + 7]]);
595 entries.push(SbgpEntry {
596 sample_count,
597 group_description_index,
598 });
599 c += 8;
600 }
601 Ok(Self {
602 version,
603 flags,
604 grouping_type,
605 grouping_type_parameter,
606 entries,
607 })
608 }
609}
610
611impl<'a> Parse<'a> for SampleToGroupBox {
612 type Error = Error;
613 fn parse(bytes: &'a [u8]) -> Result<Self> {
614 if bytes.len() < BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 {
615 return Err(Error::BufferTooShort {
616 need: BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4,
617 have: bytes.len(),
618 what: "sbgp box",
619 });
620 }
621 let ty = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
622 if ty != SBGP_TYPE {
623 return Err(Error::InvalidValue {
624 field: "box_type",
625 value: ty as u64,
626 reason: "expected sbgp",
627 });
628 }
629 Self::parse_body(&bytes[BOX_HEADER_SIZE..])
630 }
631}
632
633impl Serialize for SampleToGroupBox {
634 type Error = Error;
635 fn serialized_len(&self) -> usize {
636 let gtp_size = if self.version == 1 { 4 } else { 0 };
637 BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 + gtp_size + 4 + self.entries.len() * 8
638 }
639 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
640 let need = self.serialized_len();
641 if buf.len() < need {
642 return Err(Error::OutputBufferTooSmall {
643 need,
644 have: buf.len(),
645 });
646 }
647 let mut c = 0;
648 buf[c..c + 4].copy_from_slice(&(need as u32).to_be_bytes());
649 c += 4;
650 buf[c..c + 4].copy_from_slice(b"sbgp");
651 c += 4;
652 buf[c] = self.version;
653 let fb = self.flags.to_be_bytes();
654 buf[c + 1] = fb[1];
655 buf[c + 2] = fb[2];
656 buf[c + 3] = fb[3];
657 c += 4;
658 buf[c..c + 4].copy_from_slice(&self.grouping_type.to_be_bytes());
659 c += 4;
660 if self.version == 1 {
661 let gtp = self.grouping_type_parameter.unwrap_or(0);
662 buf[c..c + 4].copy_from_slice(>p.to_be_bytes());
663 c += 4;
664 }
665 buf[c..c + 4].copy_from_slice(&(self.entries.len() as u32).to_be_bytes());
666 c += 4;
667 for entry in &self.entries {
668 buf[c..c + 4].copy_from_slice(&entry.sample_count.to_be_bytes());
669 buf[c + 4..c + 8].copy_from_slice(&entry.group_description_index.to_be_bytes());
670 c += 8;
671 }
672 Ok(c)
673 }
674}
675
676#[derive(Debug, Clone, Copy, PartialEq, Eq)]
685#[cfg_attr(feature = "serde", derive(serde::Serialize))]
686pub struct SubSampleDescriptor {
687 pub subsample_size: u32,
689 pub subsample_priority: u8,
691 pub discardable: u8,
693 pub codec_specific_parameters: u32,
695}
696
697impl SubSampleDescriptor {
698 fn wire_len(version: u8) -> usize {
699 let size_field = if version == 1 { 4 } else { 2 };
700 size_field + 1 + 1 + 4
701 }
702}
703
704#[derive(Debug, Clone, PartialEq, Eq)]
706#[cfg_attr(feature = "serde", derive(serde::Serialize))]
707pub struct SubsEntry {
708 pub sample_delta: u32,
711 pub subsamples: Vec<SubSampleDescriptor>,
713}
714
715impl SubsEntry {
716 fn wire_len(&self, version: u8) -> usize {
717 4 + 2 + self.subsamples.len() * SubSampleDescriptor::wire_len(version)
718 }
719}
720
721#[derive(Debug, Clone, PartialEq, Eq)]
737#[cfg_attr(feature = "serde", derive(serde::Serialize))]
738pub struct SubSampleInformationBox {
739 pub version: u8,
741 pub flags: u32,
743 pub entries: Vec<SubsEntry>,
745}
746
747impl SubSampleInformationBox {
748 pub fn parse_body(body: &[u8]) -> Result<Self> {
750 if body.len() < FULLBOX_EXTRA_SIZE + 4 {
751 return Err(Error::BufferTooShort {
752 need: FULLBOX_EXTRA_SIZE + 4,
753 have: body.len(),
754 what: "subs body",
755 });
756 }
757 let version = body[0];
758 let flags = u32::from_be_bytes([0, body[1], body[2], body[3]]);
759 let mut c = FULLBOX_EXTRA_SIZE;
760 let entry_count =
761 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]) as usize;
762 c += 4;
763 let ss_size_field = if version == 1 { 4usize } else { 2usize };
764 let mut entries = Vec::with_capacity(entry_count);
765 for _ in 0..entry_count {
766 if body.len() < c + 4 + 2 {
767 return Err(Error::BufferTooShort {
768 need: c + 6,
769 have: body.len(),
770 what: "subs entry header",
771 });
772 }
773 let sample_delta = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
774 c += 4;
775 let subsample_count = u16::from_be_bytes([body[c], body[c + 1]]) as usize;
776 c += 2;
777 let ss_wire = ss_size_field + 1 + 1 + 4;
778 let mut subsamples = Vec::with_capacity(subsample_count);
779 for _ in 0..subsample_count {
780 if body.len() < c + ss_wire {
781 return Err(Error::BufferTooShort {
782 need: c + ss_wire,
783 have: body.len(),
784 what: "subs subsample",
785 });
786 }
787 let subsample_size = if version == 1 {
788 let v = u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
789 c += 4;
790 v
791 } else {
792 let v = u16::from_be_bytes([body[c], body[c + 1]]) as u32;
793 c += 2;
794 v
795 };
796 let subsample_priority = body[c];
797 let discardable = body[c + 1];
798 c += 2;
799 let codec_specific_parameters =
800 u32::from_be_bytes([body[c], body[c + 1], body[c + 2], body[c + 3]]);
801 c += 4;
802 subsamples.push(SubSampleDescriptor {
803 subsample_size,
804 subsample_priority,
805 discardable,
806 codec_specific_parameters,
807 });
808 }
809 entries.push(SubsEntry {
810 sample_delta,
811 subsamples,
812 });
813 }
814 Ok(Self {
815 version,
816 flags,
817 entries,
818 })
819 }
820}
821
822impl<'a> Parse<'a> for SubSampleInformationBox {
823 type Error = Error;
824 fn parse(bytes: &'a [u8]) -> Result<Self> {
825 if bytes.len() < BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 {
826 return Err(Error::BufferTooShort {
827 need: BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4,
828 have: bytes.len(),
829 what: "subs box",
830 });
831 }
832 let ty = u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]);
833 if ty != SUBS_TYPE {
834 return Err(Error::InvalidValue {
835 field: "box_type",
836 value: ty as u64,
837 reason: "expected subs",
838 });
839 }
840 Self::parse_body(&bytes[BOX_HEADER_SIZE..])
841 }
842}
843
844impl Serialize for SubSampleInformationBox {
845 type Error = Error;
846 fn serialized_len(&self) -> usize {
847 let entries_size: usize = self.entries.iter().map(|e| e.wire_len(self.version)).sum();
848 BOX_HEADER_SIZE + FULLBOX_EXTRA_SIZE + 4 + entries_size
849 }
850 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
851 let need = self.serialized_len();
852 if buf.len() < need {
853 return Err(Error::OutputBufferTooSmall {
854 need,
855 have: buf.len(),
856 });
857 }
858 let mut c = 0;
859 buf[c..c + 4].copy_from_slice(&(need as u32).to_be_bytes());
860 c += 4;
861 buf[c..c + 4].copy_from_slice(b"subs");
862 c += 4;
863 buf[c] = self.version;
864 let fb = self.flags.to_be_bytes();
865 buf[c + 1] = fb[1];
866 buf[c + 2] = fb[2];
867 buf[c + 3] = fb[3];
868 c += 4;
869 buf[c..c + 4].copy_from_slice(&(self.entries.len() as u32).to_be_bytes());
870 c += 4;
871 for entry in &self.entries {
872 buf[c..c + 4].copy_from_slice(&entry.sample_delta.to_be_bytes());
873 c += 4;
874 buf[c..c + 2].copy_from_slice(&(entry.subsamples.len() as u16).to_be_bytes());
875 c += 2;
876 for ss in &entry.subsamples {
877 if self.version == 1 {
878 buf[c..c + 4].copy_from_slice(&ss.subsample_size.to_be_bytes());
879 c += 4;
880 } else {
881 buf[c..c + 2].copy_from_slice(&(ss.subsample_size as u16).to_be_bytes());
882 c += 2;
883 }
884 buf[c] = ss.subsample_priority;
885 buf[c + 1] = ss.discardable;
886 c += 2;
887 buf[c..c + 4].copy_from_slice(&ss.codec_specific_parameters.to_be_bytes());
888 c += 4;
889 }
890 }
891 Ok(c)
892 }
893}
894
895#[cfg(test)]
900mod tests {
901 use super::*;
902 use broadcast_common::Serialize;
903
904 #[test]
909 fn prft_round_trip_v0() {
910 let b = ProducerReferenceTimeBox {
911 version: 0,
912 flags: 0,
913 reference_track_id: 1,
914 ntp_timestamp: 0x1234_5678_9abc_def0,
915 media_time: 0x0000_0000_0000_1234,
916 };
917 let bytes = b.to_bytes();
918 assert_eq!(bytes.len(), 8 + 4 + 4 + 8 + 4);
919 let parsed = ProducerReferenceTimeBox::parse(&bytes).unwrap();
920 assert_eq!(parsed, b);
921 }
922
923 #[test]
924 fn prft_round_trip_v1() {
925 let b = ProducerReferenceTimeBox {
926 version: 1,
927 flags: 0x000018,
928 reference_track_id: 1,
929 ntp_timestamp: 0xedefe3e3_a7ae147a,
930 media_time: 0x0000_0000_0000_1c20,
931 };
932 let bytes = b.to_bytes();
933 assert_eq!(bytes.len(), 8 + 4 + 4 + 8 + 8);
934 let parsed = ProducerReferenceTimeBox::parse(&bytes).unwrap();
935 assert_eq!(parsed, b);
936 }
937
938 #[test]
943 fn sgpd_round_trip_roll_v1() {
944 let b = SampleGroupDescriptionBox {
945 version: 1,
946 flags: 0,
947 grouping_type: GROUPING_TYPE_ROLL,
948 default_length: 2,
949 entries: vec![SgpdEntry::Roll { roll_distance: -1 }],
950 };
951 let bytes = b.to_bytes();
952 let parsed = SampleGroupDescriptionBox::parse(&bytes).unwrap();
953 assert_eq!(parsed.entries.len(), 1);
954 assert_eq!(parsed.entries[0], SgpdEntry::Roll { roll_distance: -1 });
955 assert_eq!(parsed.to_bytes(), bytes);
956 }
957
958 #[test]
959 fn sgpd_round_trip_two_roll_entries() {
960 let b = SampleGroupDescriptionBox {
961 version: 1,
962 flags: 0,
963 grouping_type: GROUPING_TYPE_ROLL,
964 default_length: 2,
965 entries: vec![
966 SgpdEntry::Roll { roll_distance: -4 },
967 SgpdEntry::Roll { roll_distance: -1 },
968 ],
969 };
970 let bytes = b.to_bytes();
971 let parsed = SampleGroupDescriptionBox::parse(&bytes).unwrap();
972 assert_eq!(parsed.entries.len(), 2);
973 assert_eq!(parsed.to_bytes(), bytes);
974 }
975
976 #[test]
981 fn sbgp_round_trip_v0() {
982 let b = SampleToGroupBox {
983 version: 0,
984 flags: 0,
985 grouping_type: GROUPING_TYPE_ROLL,
986 grouping_type_parameter: None,
987 entries: vec![
988 SbgpEntry {
989 sample_count: 1,
990 group_description_index: 1,
991 },
992 SbgpEntry {
993 sample_count: 10,
994 group_description_index: 0,
995 },
996 ],
997 };
998 let bytes = b.to_bytes();
999 let parsed = SampleToGroupBox::parse(&bytes).unwrap();
1000 assert_eq!(parsed, b);
1001 }
1002
1003 #[test]
1004 fn sbgp_round_trip_v1() {
1005 let b = SampleToGroupBox {
1006 version: 1,
1007 flags: 0,
1008 grouping_type: GROUPING_TYPE_ROLL,
1009 grouping_type_parameter: Some(0xDEAD_BEEF),
1010 entries: vec![SbgpEntry {
1011 sample_count: 5,
1012 group_description_index: 1,
1013 }],
1014 };
1015 let bytes = b.to_bytes();
1016 let parsed = SampleToGroupBox::parse(&bytes).unwrap();
1017 assert_eq!(parsed, b);
1018 }
1019
1020 #[test]
1025 fn subs_round_trip_v0() {
1026 let b = SubSampleInformationBox {
1027 version: 0,
1028 flags: 0,
1029 entries: vec![SubsEntry {
1030 sample_delta: 1,
1031 subsamples: vec![
1032 SubSampleDescriptor {
1033 subsample_size: 100,
1034 subsample_priority: 255,
1035 discardable: 0,
1036 codec_specific_parameters: 0,
1037 },
1038 SubSampleDescriptor {
1039 subsample_size: 200,
1040 subsample_priority: 128,
1041 discardable: 1,
1042 codec_specific_parameters: 0,
1043 },
1044 ],
1045 }],
1046 };
1047 let bytes = b.to_bytes();
1048 let parsed = SubSampleInformationBox::parse(&bytes).unwrap();
1049 assert_eq!(parsed, b);
1050 assert_eq!(parsed.to_bytes(), bytes);
1051 }
1052
1053 #[test]
1054 fn subs_round_trip_v1() {
1055 let b = SubSampleInformationBox {
1056 version: 1,
1057 flags: 0,
1058 entries: vec![SubsEntry {
1059 sample_delta: 5,
1060 subsamples: vec![SubSampleDescriptor {
1061 subsample_size: 0x0001_2345,
1062 subsample_priority: 200,
1063 discardable: 0,
1064 codec_specific_parameters: 0xABCD_EF01,
1065 }],
1066 }],
1067 };
1068 let bytes = b.to_bytes();
1069 let parsed = SubSampleInformationBox::parse(&bytes).unwrap();
1070 assert_eq!(parsed, b);
1071 assert_eq!(parsed.to_bytes(), bytes);
1072 }
1073
1074 #[test]
1075 fn subs_empty_round_trip() {
1076 let b = SubSampleInformationBox {
1077 version: 0,
1078 flags: 0,
1079 entries: vec![],
1080 };
1081 let bytes = b.to_bytes();
1082 let parsed = SubSampleInformationBox::parse(&bytes).unwrap();
1083 assert_eq!(parsed, b);
1084 }
1085}