Skip to main content

mp4/mp4box/
trak.rs

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