1use nutype_enum::nutype_enum;
4use scuffle_bytes_util::zero_copy::{Deserialize, DeserializeSeed, Serialize, U24Be};
5
6use super::{
7 DataInformationBox, HintMediaHeaderBox, SampleTableBox, SoundMediaHeaderBox, SubtitleMediaHeaderBox,
8 VideoMediaHeaderBox, VolumetricVisualMediaHeaderBox,
9};
10use crate::common_types::Utf8String;
11use crate::{BoxHeader, FullBoxHeader, IsoBox, IsoSized, Langauge, UnknownBox};
12
13#[derive(IsoBox, Debug, PartialEq, Eq)]
17#[iso_box(box_type = b"mdia", crate_path = crate)]
18pub struct MediaBox<'a> {
19 #[iso_box(nested_box)]
21 pub mdhd: MediaHeaderBox,
22 #[iso_box(nested_box)]
24 pub hdlr: HandlerBox,
25 #[iso_box(nested_box(collect))]
27 pub elng: Option<ExtendedLanguageBox>,
28 #[iso_box(nested_box)]
30 pub minf: MediaInformationBox<'a>,
31 #[iso_box(nested_box(collect_unknown))]
33 pub unknown_boxes: Vec<UnknownBox<'a>>,
34}
35
36impl<'a> MediaBox<'a> {
37 pub fn new(mdhd: MediaHeaderBox, hdlr: HandlerBox, minf: MediaInformationBox<'a>) -> Self {
39 Self {
40 mdhd,
41 hdlr,
42 elng: None,
43 minf,
44 unknown_boxes: vec![],
45 }
46 }
47}
48
49#[derive(IsoBox, Debug, PartialEq, Eq)]
53#[iso_box(box_type = b"mdhd", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
54pub struct MediaHeaderBox {
55 pub full_header: FullBoxHeader,
57 pub creation_time: u64,
60 pub modification_time: u64,
63 pub timescale: u32,
67 pub duration: u64,
71 pub language: Langauge,
74 pub pre_defined: u16,
76}
77
78impl MediaHeaderBox {
79 pub fn new(creation_time: u64, modification_time: u64, timescale: u32, duration: u64) -> Self {
83 let version = if creation_time > u32::MAX as u64 || modification_time > u32::MAX as u64 || duration > u32::MAX as u64
84 {
85 1
86 } else {
87 0
88 };
89
90 Self {
91 full_header: FullBoxHeader {
92 version,
93 flags: U24Be(0),
94 },
95 creation_time,
96 modification_time,
97 timescale,
98 duration,
99 language: Langauge::UNDETERMINED,
100 pre_defined: 0,
101 }
102 }
103}
104
105impl<'a> DeserializeSeed<'a, BoxHeader> for MediaHeaderBox {
106 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> std::io::Result<Self>
107 where
108 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
109 {
110 let full_header = FullBoxHeader::deserialize(&mut reader)?;
111
112 let creation_time = if full_header.version == 1 {
113 u64::deserialize(&mut reader)?
114 } else {
115 u32::deserialize(&mut reader)? as u64
116 };
117 let modification_time = if full_header.version == 1 {
118 u64::deserialize(&mut reader)?
119 } else {
120 u32::deserialize(&mut reader)? as u64
121 };
122 let timescale = u32::deserialize(&mut reader)?;
123 let duration = if full_header.version == 1 {
124 u64::deserialize(&mut reader)?
125 } else {
126 u32::deserialize(&mut reader)? as u64
127 };
128
129 let language = Langauge::deserialize(&mut reader)?;
130 let pre_defined = u16::deserialize(&mut reader)?;
131
132 Ok(Self {
133 full_header,
134 creation_time,
135 modification_time,
136 timescale,
137 duration,
138 language,
139 pre_defined,
140 })
141 }
142}
143
144impl Serialize for MediaHeaderBox {
145 fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
146 where
147 W: std::io::Write,
148 {
149 self.serialize_box_header(&mut writer)?;
150 self.full_header.serialize(&mut writer)?;
151
152 if self.full_header.version == 1 {
153 self.creation_time.serialize(&mut writer)?;
154 self.modification_time.serialize(&mut writer)?;
155 self.timescale.serialize(&mut writer)?;
156 self.duration.serialize(&mut writer)?;
157 } else {
158 (self.creation_time as u32).serialize(&mut writer)?;
159 (self.modification_time as u32).serialize(&mut writer)?;
160 self.timescale.serialize(&mut writer)?;
161 (self.duration as u32).serialize(&mut writer)?;
162 }
163
164 self.language.serialize(&mut writer)?;
165 self.pre_defined.serialize(&mut writer)?;
166
167 Ok(())
168 }
169}
170
171impl IsoSized for MediaHeaderBox {
172 fn size(&self) -> usize {
173 let mut size = self.full_header.size();
174 if self.full_header.version == 1 {
175 size += 8 + 8 + 4 + 8; } else {
177 size += 4 + 4 + 4 + 4; }
179 size += self.language.size(); size += 2; Self::add_header_size(size)
183 }
184}
185
186nutype_enum! {
187 pub enum HandlerType([u8; 4]) {
189 Null = *b"null",
191 Video = *b"vide",
193 AuxiliaryVideo = *b"auxv",
195 Audio = *b"soun",
197 Metadata = *b"meta",
199 MetadataMpeg7t = *b"mp7t",
201 MetadataMpeg7b = *b"mp7b",
203 Hint = *b"hint",
205 Text = *b"text",
207 Subtitle = *b"subt",
209 Font = *b"fdsm",
211 VolumetricVisual = *b"volv",
213 Haptic = *b"hapt",
215 }
216}
217
218impl IsoSized for HandlerType {
219 fn size(&self) -> usize {
220 4
221 }
222}
223
224#[derive(IsoBox, Debug, PartialEq, Eq)]
228#[iso_box(box_type = b"hdlr", crate_path = crate)]
229pub struct HandlerBox {
230 pub full_header: FullBoxHeader,
232 pub pre_defined: u32,
234 #[iso_box(from = "[u8; 4]")]
240 pub handler_type: HandlerType,
241 pub reserved: [u32; 3],
243 pub name: Utf8String,
245}
246
247impl HandlerBox {
248 pub fn new(handler_type: HandlerType, name: Utf8String) -> Self {
250 Self {
251 full_header: FullBoxHeader::default(),
252 pre_defined: 0,
253 handler_type,
254 reserved: [0; 3],
255 name,
256 }
257 }
258}
259
260#[derive(IsoBox, Debug, PartialEq, Eq)]
264#[iso_box(box_type = b"minf", crate_path = crate)]
265pub struct MediaInformationBox<'a> {
266 #[iso_box(nested_box(collect))]
268 pub vmhd: Option<VideoMediaHeaderBox>,
269 #[iso_box(nested_box(collect))]
271 pub smhd: Option<SoundMediaHeaderBox>,
272 #[iso_box(nested_box(collect))]
274 pub hmhd: Option<HintMediaHeaderBox>,
275 #[iso_box(nested_box(collect))]
277 pub sthd: Option<SubtitleMediaHeaderBox>,
278 #[iso_box(nested_box(collect))]
280 pub vvhd: Option<VolumetricVisualMediaHeaderBox>,
281 #[iso_box(nested_box(collect_unknown))]
283 pub unknown_boxes: Vec<UnknownBox<'a>>,
284 #[iso_box(nested_box)]
286 pub dinf: DataInformationBox<'a>,
287 #[iso_box(nested_box)]
289 pub stbl: SampleTableBox<'a>,
290}
291
292impl<'a> MediaInformationBox<'a> {
293 pub fn new(stbl: SampleTableBox<'a>, vmhd: Option<VideoMediaHeaderBox>, smhd: Option<SoundMediaHeaderBox>) -> Self {
295 Self {
296 vmhd,
297 smhd,
298 hmhd: None,
299 sthd: None,
300 vvhd: None,
301 unknown_boxes: Vec::new(),
302 dinf: DataInformationBox::default(),
303 stbl,
304 }
305 }
306}
307
308#[derive(IsoBox, Debug, PartialEq, Eq)]
312#[iso_box(box_type = b"nmhd", crate_path = crate)]
313pub struct NullMediaHeaderBox {
314 pub full_header: FullBoxHeader,
316}
317
318#[derive(IsoBox, Debug, PartialEq, Eq)]
322#[iso_box(box_type = b"elng", crate_path = crate)]
323pub struct ExtendedLanguageBox {
324 pub full_header: FullBoxHeader,
326 pub extended_language: Utf8String,
329}