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 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 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}