mp4_atom/moov/trak/
tref.rs1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct TrackReferenceTypeBox {
11 pub reference_type: FourCC,
12 pub track_ids: Vec<u32>,
13}
14
15impl TrackReferenceTypeBox {
16 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
17 if self.track_ids.len() * 4 > (u32::MAX as usize) - 8 {
18 return Err(Error::InvalidSize);
20 }
21 let size: u32 = 4u32 + 4u32 + (self.track_ids.len() as u32) * 4;
22 size.encode(buf)?;
23 self.reference_type.encode(buf)?;
24 self.track_ids.encode(buf)
25 }
26
27 fn decode<B: Buf>(buf: &mut B) -> Result<TrackReferenceTypeBox> {
28 let header = Header::decode(buf)?;
29 let size = header.size.unwrap_or(buf.remaining());
30 if size > buf.remaining() {
31 return Err(Error::InvalidSize);
32 }
33 let num_entries = size / 4; let mut track_ids = Vec::with_capacity(num_entries.min(16));
35 for _ in 0..num_entries {
36 track_ids.push(u32::decode(buf)?);
37 }
38 if cfg!(feature = "strict") && (size % 4 != 0) {
40 return Err(Error::InvalidSize);
41 }
42 buf.advance(size % 4);
43 Ok(TrackReferenceTypeBox {
44 reference_type: header.kind,
45 track_ids,
46 })
47 }
48}
49
50#[derive(Debug, Clone, PartialEq, Eq, Default)]
52#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
53pub struct Tref {
54 pub track_reference_type_boxes: Vec<TrackReferenceTypeBox>,
55}
56
57impl Atom for Tref {
58 const KIND: FourCC = FourCC::new(b"tref");
59
60 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
61 let mut track_reference_type_boxes = vec![];
62 while buf.has_remaining() {
63 let reference = TrackReferenceTypeBox::decode(buf)?;
64 track_reference_type_boxes.push(reference);
65 }
66 Ok(Self {
67 track_reference_type_boxes,
68 })
69 }
70
71 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
72 for b in &self.track_reference_type_boxes {
73 b.encode(buf)?;
74 }
75 Ok(())
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 const ENCODED_TREF: &[u8] = &[
85 0x00, 0x00, 0x00, 0x24, 0x74, 0x72, 0x65, 0x66, 0x00, 0x00, 0x00, 0x0c, 0x73, 0x79, 0x6e,
86 0x63, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x6d, 0x70, 0x6f, 0x64, 0x00, 0x00,
87 0x00, 0xc9, 0x00, 0x00, 0x00, 0x65,
88 ];
89
90 #[test]
91 fn test_tref_decode() {
92 let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_TREF);
93
94 let tref = Tref::decode(buf).expect("failed to decode tref");
95
96 assert_eq!(
97 tref,
98 Tref {
99 track_reference_type_boxes: vec![
100 TrackReferenceTypeBox {
101 reference_type: b"sync".into(),
102 track_ids: vec![1]
103 },
104 TrackReferenceTypeBox {
105 reference_type: b"mpod".into(),
106 track_ids: vec![201, 101]
107 }
108 ]
109 }
110 );
111 }
112
113 #[test]
114 fn test_tref_encode() {
115 let tref = Tref {
116 track_reference_type_boxes: vec![
117 TrackReferenceTypeBox {
118 reference_type: b"sync".into(),
119 track_ids: vec![1],
120 },
121 TrackReferenceTypeBox {
122 reference_type: b"mpod".into(),
123 track_ids: vec![201, 101],
124 },
125 ],
126 };
127
128 let mut buf = Vec::new();
129 tref.encode(&mut buf).unwrap();
130
131 assert_eq!(buf.as_slice(), ENCODED_TREF);
132 }
133}