mp4/mp4box/
moof.rs

1use serde::Serialize;
2use std::io::{Read, Seek, Write};
3
4use crate::mp4box::*;
5use crate::mp4box::{mfhd::MfhdBox, traf::TrafBox};
6
7#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
8pub struct MoofBox {
9    pub mfhd: MfhdBox,
10
11    #[serde(rename = "traf")]
12    pub trafs: Vec<TrafBox>,
13}
14
15impl MoofBox {
16    pub fn get_type(&self) -> BoxType {
17        BoxType::MoofBox
18    }
19
20    pub fn get_size(&self) -> u64 {
21        let mut size = HEADER_SIZE + self.mfhd.box_size();
22        for traf in self.trafs.iter() {
23            size += traf.box_size();
24        }
25        size
26    }
27}
28
29impl Mp4Box for MoofBox {
30    fn box_type(&self) -> BoxType {
31        self.get_type()
32    }
33
34    fn box_size(&self) -> u64 {
35        self.get_size()
36    }
37
38    fn to_json(&self) -> Result<String> {
39        Ok(serde_json::to_string(&self).unwrap())
40    }
41
42    fn summary(&self) -> Result<String> {
43        let s = format!("trafs={}", self.trafs.len());
44        Ok(s)
45    }
46}
47
48impl<R: Read + Seek> ReadBox<&mut R> for MoofBox {
49    fn read_box(reader: &mut R, size: u64) -> Result<Self> {
50        let start = box_start(reader)?;
51
52        let mut mfhd = None;
53        let mut trafs = Vec::new();
54
55        let mut current = reader.stream_position()?;
56        let end = start + size;
57        while current < end {
58            // Get box header.
59            let header = BoxHeader::read(reader)?;
60            let BoxHeader { name, size: s } = header;
61            if s > size {
62                return Err(Error::InvalidData(
63                    "moof box contains a box with a larger size than it",
64                ));
65            }
66
67            match name {
68                BoxType::MfhdBox => {
69                    mfhd = Some(MfhdBox::read_box(reader, s)?);
70                }
71                BoxType::TrafBox => {
72                    let traf = TrafBox::read_box(reader, s)?;
73                    trafs.push(traf);
74                }
75                _ => {
76                    // XXX warn!()
77                    skip_box(reader, s)?;
78                }
79            }
80            current = reader.stream_position()?;
81        }
82
83        if mfhd.is_none() {
84            return Err(Error::BoxNotFound(BoxType::MfhdBox));
85        }
86
87        skip_bytes_to(reader, start + size)?;
88
89        Ok(MoofBox {
90            mfhd: mfhd.unwrap(),
91            trafs,
92        })
93    }
94}
95
96impl<W: Write> WriteBox<&mut W> for MoofBox {
97    fn write_box(&self, writer: &mut W) -> Result<u64> {
98        let size = self.box_size();
99        BoxHeader::new(self.box_type(), size).write(writer)?;
100
101        self.mfhd.write_box(writer)?;
102        for traf in self.trafs.iter() {
103            traf.write_box(writer)?;
104        }
105        Ok(0)
106    }
107}