1use serde::Serialize;
2use std::io::{Read, Seek, Write};
3
4use crate::mp4box::*;
5use crate::mp4box::{
6 co64::Co64Box, ctts::CttsBox, stco::StcoBox, stsc::StscBox, stsd::StsdBox, stss::StssBox,
7 stsz::StszBox, stts::SttsBox,
8};
9
10#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
11pub struct StblBox {
12 pub stsd: StsdBox,
13 pub stts: SttsBox,
14
15 #[serde(skip_serializing_if = "Option::is_none")]
16 pub ctts: Option<CttsBox>,
17
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub stss: Option<StssBox>,
20 pub stsc: StscBox,
21 pub stsz: StszBox,
22
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub stco: Option<StcoBox>,
25
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub co64: Option<Co64Box>,
28}
29
30impl StblBox {
31 pub fn get_type(&self) -> BoxType {
32 BoxType::StblBox
33 }
34
35 pub fn get_size(&self) -> u64 {
36 let mut size = HEADER_SIZE;
37 size += self.stsd.box_size();
38 size += self.stts.box_size();
39 if let Some(ref ctts) = self.ctts {
40 size += ctts.box_size();
41 }
42 if let Some(ref stss) = self.stss {
43 size += stss.box_size();
44 }
45 size += self.stsc.box_size();
46 size += self.stsz.box_size();
47 if let Some(ref stco) = self.stco {
48 size += stco.box_size();
49 }
50 if let Some(ref co64) = self.co64 {
51 size += co64.box_size();
52 }
53 size
54 }
55}
56
57impl Mp4Box for StblBox {
58 fn box_type(&self) -> BoxType {
59 self.get_type()
60 }
61
62 fn box_size(&self) -> u64 {
63 self.get_size()
64 }
65
66 fn to_json(&self) -> Result<String> {
67 Ok(serde_json::to_string(&self).unwrap())
68 }
69
70 fn summary(&self) -> Result<String> {
71 let s = String::new();
72 Ok(s)
73 }
74}
75
76impl<R: Read + Seek> ReadBox<&mut R> for StblBox {
77 fn read_box(reader: &mut R, size: u64) -> Result<Self> {
78 let start = box_start(reader)?;
79
80 let mut stsd = None;
81 let mut stts = None;
82 let mut ctts = None;
83 let mut stss = None;
84 let mut stsc = None;
85 let mut stsz = None;
86 let mut stco = None;
87 let mut co64 = None;
88
89 let mut current = reader.stream_position()?;
90 let end = start + size;
91 while current < end {
92 let header = BoxHeader::read(reader)?;
94 let BoxHeader { name, size: s } = header;
95 if s > size {
96 return Err(Error::InvalidData(
97 "stbl box contains a box with a larger size than it",
98 ));
99 }
100
101 match name {
102 BoxType::StsdBox => {
103 stsd = Some(StsdBox::read_box(reader, s)?);
104 }
105 BoxType::SttsBox => {
106 stts = Some(SttsBox::read_box(reader, s)?);
107 }
108 BoxType::CttsBox => {
109 ctts = Some(CttsBox::read_box(reader, s)?);
110 }
111 BoxType::StssBox => {
112 stss = Some(StssBox::read_box(reader, s)?);
113 }
114 BoxType::StscBox => {
115 stsc = Some(StscBox::read_box(reader, s)?);
116 }
117 BoxType::StszBox => {
118 stsz = Some(StszBox::read_box(reader, s)?);
119 }
120 BoxType::StcoBox => {
121 stco = Some(StcoBox::read_box(reader, s)?);
122 }
123 BoxType::Co64Box => {
124 co64 = Some(Co64Box::read_box(reader, s)?);
125 }
126 _ => {
127 skip_box(reader, s)?;
129 }
130 }
131 current = reader.stream_position()?;
132 }
133
134 if stsd.is_none() {
135 return Err(Error::BoxNotFound(BoxType::StsdBox));
136 }
137 if stts.is_none() {
138 return Err(Error::BoxNotFound(BoxType::SttsBox));
139 }
140 if stsc.is_none() {
141 return Err(Error::BoxNotFound(BoxType::StscBox));
142 }
143 if stsz.is_none() {
144 return Err(Error::BoxNotFound(BoxType::StszBox));
145 }
146 if stco.is_none() && co64.is_none() {
147 return Err(Error::Box2NotFound(BoxType::StcoBox, BoxType::Co64Box));
148 }
149
150 skip_bytes_to(reader, start + size)?;
151
152 Ok(StblBox {
153 stsd: stsd.unwrap(),
154 stts: stts.unwrap(),
155 ctts,
156 stss,
157 stsc: stsc.unwrap(),
158 stsz: stsz.unwrap(),
159 stco,
160 co64,
161 })
162 }
163}
164
165impl<W: Write> WriteBox<&mut W> for StblBox {
166 fn write_box(&self, writer: &mut W) -> Result<u64> {
167 let size = self.box_size();
168 BoxHeader::new(self.box_type(), size).write(writer)?;
169
170 self.stsd.write_box(writer)?;
171 self.stts.write_box(writer)?;
172 if let Some(ref ctts) = self.ctts {
173 ctts.write_box(writer)?;
174 }
175 if let Some(ref stss) = self.stss {
176 stss.write_box(writer)?;
177 }
178 self.stsc.write_box(writer)?;
179 self.stsz.write_box(writer)?;
180 if let Some(ref stco) = self.stco {
181 stco.write_box(writer)?;
182 }
183 if let Some(ref co64) = self.co64 {
184 co64.write_box(writer)?;
185 }
186
187 Ok(size)
188 }
189}