Skip to main content

mp4/mp4box/
dinf.rs

1use serde::Serialize;
2use std::io::{Read, Seek, Write};
3
4use crate::mp4box::*;
5
6#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
7pub struct DinfBox {
8    dref: DrefBox,
9}
10
11impl DinfBox {
12    pub fn get_type(&self) -> BoxType {
13        BoxType::DinfBox
14    }
15
16    pub fn get_size(&self) -> u64 {
17        HEADER_SIZE + self.dref.box_size()
18    }
19}
20
21impl Mp4Box for DinfBox {
22    fn box_type(&self) -> BoxType {
23        self.get_type()
24    }
25
26    fn box_size(&self) -> u64 {
27        self.get_size()
28    }
29
30    fn to_json(&self) -> Result<String> {
31        Ok(serde_json::to_string(&self).unwrap())
32    }
33
34    fn summary(&self) -> Result<String> {
35        let s = String::new();
36        Ok(s)
37    }
38}
39
40impl<R: Read + Seek> ReadBox<&mut R> for DinfBox {
41    fn read_box(reader: &mut R, size: u64) -> Result<Self> {
42        let start = box_start(reader)?;
43
44        let mut dref = None;
45
46        let mut current = reader.stream_position()?;
47        let end = start + size;
48        while current < end {
49            // Get box header.
50            let header = BoxHeader::read(reader)?;
51            let BoxHeader { name, size: s } = header;
52            if s > size {
53                return Err(Error::InvalidData(
54                    "dinf box contains a box with a larger size than it",
55                ));
56            }
57
58            match name {
59                BoxType::DrefBox => {
60                    dref = Some(DrefBox::read_box(reader, s)?);
61                }
62                _ => {
63                    // XXX warn!()
64                    skip_box(reader, s)?;
65                }
66            }
67
68            current = reader.stream_position()?;
69        }
70
71        if dref.is_none() {
72            return Err(Error::BoxNotFound(BoxType::DrefBox));
73        }
74
75        skip_bytes_to(reader, start + size)?;
76
77        Ok(DinfBox {
78            dref: dref.unwrap(),
79        })
80    }
81}
82
83impl<W: Write> WriteBox<&mut W> for DinfBox {
84    fn write_box(&self, writer: &mut W) -> Result<u64> {
85        let size = self.box_size();
86        BoxHeader::new(self.box_type(), size).write(writer)?;
87        self.dref.write_box(writer)?;
88        Ok(size)
89    }
90}
91
92#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
93pub struct DrefBox {
94    pub version: u8,
95    pub flags: u32,
96
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub url: Option<UrlBox>,
99}
100
101impl Default for DrefBox {
102    fn default() -> Self {
103        DrefBox {
104            version: 0,
105            flags: 0,
106            url: Some(UrlBox::default()),
107        }
108    }
109}
110
111impl DrefBox {
112    pub fn get_type(&self) -> BoxType {
113        BoxType::DrefBox
114    }
115
116    pub fn get_size(&self) -> u64 {
117        let mut size = HEADER_SIZE + HEADER_EXT_SIZE + 4;
118        if let Some(ref url) = self.url {
119            size += url.box_size();
120        }
121        size
122    }
123}
124
125impl Mp4Box for DrefBox {
126    fn box_type(&self) -> BoxType {
127        self.get_type()
128    }
129
130    fn box_size(&self) -> u64 {
131        self.get_size()
132    }
133
134    fn to_json(&self) -> Result<String> {
135        Ok(serde_json::to_string(&self).unwrap())
136    }
137
138    fn summary(&self) -> Result<String> {
139        let s = String::new();
140        Ok(s)
141    }
142}
143
144impl<R: Read + Seek> ReadBox<&mut R> for DrefBox {
145    fn read_box(reader: &mut R, size: u64) -> Result<Self> {
146        let start = box_start(reader)?;
147
148        let mut current = reader.stream_position()?;
149
150        let (version, flags) = read_box_header_ext(reader)?;
151        let end = start + size;
152
153        let mut url = None;
154
155        let entry_count = reader.read_u32::<BigEndian>()?;
156        for _i in 0..entry_count {
157            if current >= end {
158                break;
159            }
160
161            // Get box header.
162            let header = BoxHeader::read(reader)?;
163            let BoxHeader { name, size: s } = header;
164            if s > size {
165                return Err(Error::InvalidData(
166                    "dinf box contains a box with a larger size than it",
167                ));
168            }
169
170            match name {
171                BoxType::UrlBox => {
172                    url = Some(UrlBox::read_box(reader, s)?);
173                }
174                _ => {
175                    skip_box(reader, s)?;
176                }
177            }
178
179            current = reader.stream_position()?;
180        }
181
182        skip_bytes_to(reader, start + size)?;
183
184        Ok(DrefBox {
185            version,
186            flags,
187            url,
188        })
189    }
190}
191
192impl<W: Write> WriteBox<&mut W> for DrefBox {
193    fn write_box(&self, writer: &mut W) -> Result<u64> {
194        let size = self.box_size();
195        BoxHeader::new(self.box_type(), size).write(writer)?;
196
197        write_box_header_ext(writer, self.version, self.flags)?;
198
199        writer.write_u32::<BigEndian>(1)?;
200
201        if let Some(ref url) = self.url {
202            url.write_box(writer)?;
203        }
204
205        Ok(size)
206    }
207}
208
209#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
210pub struct UrlBox {
211    pub version: u8,
212    pub flags: u32,
213    pub location: String,
214}
215
216impl Default for UrlBox {
217    fn default() -> Self {
218        UrlBox {
219            version: 0,
220            flags: 1,
221            location: String::default(),
222        }
223    }
224}
225
226impl UrlBox {
227    pub fn get_type(&self) -> BoxType {
228        BoxType::UrlBox
229    }
230
231    pub fn get_size(&self) -> u64 {
232        let mut size = HEADER_SIZE + HEADER_EXT_SIZE;
233
234        if !self.location.is_empty() {
235            size += self.location.bytes().len() as u64 + 1;
236        }
237
238        size
239    }
240}
241
242impl Mp4Box for UrlBox {
243    fn box_type(&self) -> BoxType {
244        self.get_type()
245    }
246
247    fn box_size(&self) -> u64 {
248        self.get_size()
249    }
250
251    fn to_json(&self) -> Result<String> {
252        Ok(serde_json::to_string(&self).unwrap())
253    }
254
255    fn summary(&self) -> Result<String> {
256        let s = format!("location={}", self.location);
257        Ok(s)
258    }
259}
260
261impl<R: Read + Seek> ReadBox<&mut R> for UrlBox {
262    fn read_box(reader: &mut R, size: u64) -> Result<Self> {
263        let start = box_start(reader)?;
264
265        let (version, flags) = read_box_header_ext(reader)?;
266
267        let buf_size = size
268            .checked_sub(HEADER_SIZE + HEADER_EXT_SIZE)
269            .ok_or(Error::InvalidData("url size too small"))?;
270
271        let mut buf = vec![0u8; buf_size as usize];
272        reader.read_exact(&mut buf)?;
273        if let Some(end) = buf.iter().position(|&b| b == b'\0') {
274            buf.truncate(end);
275        }
276        let location = String::from_utf8(buf).unwrap_or_default();
277
278        skip_bytes_to(reader, start + size)?;
279
280        Ok(UrlBox {
281            version,
282            flags,
283            location,
284        })
285    }
286}
287
288impl<W: Write> WriteBox<&mut W> for UrlBox {
289    fn write_box(&self, writer: &mut W) -> Result<u64> {
290        let size = self.box_size();
291        BoxHeader::new(self.box_type(), size).write(writer)?;
292
293        write_box_header_ext(writer, self.version, self.flags)?;
294
295        if !self.location.is_empty() {
296            writer.write_all(self.location.as_bytes())?;
297            writer.write_u8(0)?;
298        }
299
300        Ok(size)
301    }
302}