oximedia_codec/container/
isobmff.rs1use std::io::{self, Read};
7
8pub fn make_box(fourcc: [u8; 4], payload: &[u8]) -> Vec<u8> {
23 let payload_len = payload.len();
24 if let Ok(size) = u32::try_from(payload_len + 8) {
25 let mut out = Vec::with_capacity(8 + payload_len);
26 out.extend_from_slice(&size.to_be_bytes());
27 out.extend_from_slice(&fourcc);
28 out.extend_from_slice(payload);
29 out
30 } else {
31 let size64 = (payload_len as u64) + 16; let mut out = Vec::with_capacity(16 + payload_len);
34 out.extend_from_slice(&1u32.to_be_bytes()); out.extend_from_slice(&fourcc);
36 out.extend_from_slice(&size64.to_be_bytes());
37 out.extend_from_slice(payload);
38 out
39 }
40}
41
42pub fn make_full_box(fourcc: [u8; 4], version: u8, flags: u32, payload: &[u8]) -> Vec<u8> {
49 let mut full_payload = Vec::with_capacity(4 + payload.len());
50 full_payload.push(version);
51 let flags_be = flags.to_be_bytes();
52 full_payload.extend_from_slice(&flags_be[1..4]); full_payload.extend_from_slice(payload);
54 make_box(fourcc, &full_payload)
55}
56
57pub struct BoxIter<R: Read> {
63 reader: R,
64 done: bool,
65}
66
67impl<R: Read> BoxIter<R> {
68 pub fn new(reader: R) -> Self {
70 Self {
71 reader,
72 done: false,
73 }
74 }
75}
76
77impl<R: Read> Iterator for BoxIter<R> {
78 type Item = io::Result<([u8; 4], Vec<u8>)>;
79
80 fn next(&mut self) -> Option<Self::Item> {
81 if self.done {
82 return None;
83 }
84
85 let mut header = [0u8; 8];
87 match self.reader.read_exact(&mut header) {
88 Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => {
89 self.done = true;
90 return None;
91 }
92 Err(e) => {
93 self.done = true;
94 return Some(Err(e));
95 }
96 Ok(()) => {}
97 }
98
99 let mut size_bytes = [0u8; 4];
101 size_bytes.copy_from_slice(&header[0..4]);
102 let size_field = u32::from_be_bytes(size_bytes);
103
104 let mut fourcc = [0u8; 4];
105 fourcc.copy_from_slice(&header[4..8]);
106
107 let payload_len: usize = match size_field {
108 0 => {
109 let mut payload = Vec::new();
111 if let Err(e) = self.reader.read_to_end(&mut payload) {
112 self.done = true;
113 return Some(Err(e));
114 }
115 self.done = true;
116 return Some(Ok((fourcc, payload)));
117 }
118 1 => {
119 let mut ls = [0u8; 8];
121 if let Err(e) = self.reader.read_exact(&mut ls) {
122 self.done = true;
123 return Some(Err(e));
124 }
125 let total = u64::from_be_bytes(ls);
126 (total as usize).saturating_sub(16)
128 }
129 n => {
130 (n as usize).saturating_sub(8)
132 }
133 };
134
135 let mut payload = vec![0u8; payload_len];
136 if let Err(e) = self.reader.read_exact(&mut payload) {
137 self.done = true;
138 return Some(Err(e));
139 }
140 Some(Ok((fourcc, payload)))
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147 use std::io::Cursor;
148
149 #[test]
150 fn make_box_32bit_layout() {
151 let payload = b"hello";
152 let boxed = make_box(*b"test", payload);
153 assert_eq!(boxed.len(), 13);
155 let mut size_buf = [0u8; 4];
156 size_buf.copy_from_slice(&boxed[0..4]);
157 assert_eq!(u32::from_be_bytes(size_buf), 13);
158 assert_eq!(&boxed[4..8], b"test");
159 assert_eq!(&boxed[8..], b"hello");
160 }
161
162 #[test]
163 fn make_full_box_layout() {
164 let payload = b"data";
165 let boxed = make_full_box(*b"mdhd", 0, 0x000001, payload);
166 assert_eq!(boxed.len(), 16);
168 assert_eq!(boxed[8], 0);
170 assert_eq!(&boxed[9..12], &[0x00, 0x00, 0x01]);
172 }
173
174 #[test]
175 fn box_iter_single_box() {
176 let boxed = make_box(*b"foo1", b"abcd");
177 let parsed: Vec<_> = BoxIter::new(Cursor::new(boxed))
178 .collect::<Result<Vec<_>, _>>()
179 .expect("parse ok");
180 assert_eq!(parsed.len(), 1);
181 assert_eq!(&parsed[0].0, b"foo1");
182 assert_eq!(&parsed[0].1, b"abcd");
183 }
184
185 #[test]
186 fn box_iter_multiple_boxes() {
187 let box1 = make_box(*b"foo1", b"aaaa");
188 let box2 = make_box(*b"foo2", b"bbbb");
189 let mut combined = box1;
190 combined.extend(box2);
191 let parsed: Vec<_> = BoxIter::new(Cursor::new(combined))
192 .collect::<Result<Vec<_>, _>>()
193 .expect("parse ok");
194 assert_eq!(parsed.len(), 2);
195 assert_eq!(&parsed[0].0, b"foo1");
196 assert_eq!(&parsed[1].0, b"foo2");
197 assert_eq!(&parsed[0].1, b"aaaa");
198 assert_eq!(&parsed[1].1, b"bbbb");
199 }
200
201 #[test]
202 fn box_iter_empty_payload() {
203 let boxed = make_box(*b"free", b"");
204 let parsed: Vec<_> = BoxIter::new(Cursor::new(boxed))
205 .collect::<Result<Vec<_>, _>>()
206 .expect("parse ok");
207 assert_eq!(parsed.len(), 1);
208 assert!(parsed[0].1.is_empty());
209 }
210}