1use fixed::FixedU32;
4use fixed::types::extra::U16;
5use scuffle_bytes_util::zero_copy::{Deserialize, DeserializeSeed, Serialize};
6use scuffle_bytes_util::{BitWriter, BytesCow};
7
8use super::SampleEntry;
9use crate::{BoxHeader, FullBoxHeader, IsoBox, IsoSized};
10
11#[derive(IsoBox, Debug, PartialEq, Eq, Default)]
15#[iso_box(box_type = b"vmhd", crate_path = crate)]
16pub struct VideoMediaHeaderBox {
17 pub full_header: FullBoxHeader,
19 pub graphicsmode: u16,
24 pub opcolor: [u16; 3],
26}
27
28#[derive(Debug, PartialEq, Eq)]
43pub struct VisualSampleEntry {
44 pub sample_entry: SampleEntry,
46 pub pre_defined: u16,
48 pub reserved1: u16,
50 pub pre_defined2: [u32; 3],
52 pub width: u16,
54 pub height: u16,
56 pub horiz_resolution: FixedU32<U16>,
58 pub vert_resolution: FixedU32<U16>,
60 pub reserved2: u32,
62 pub frame_count: u16,
65 pub compressor_name: [u8; 32],
70 pub depth: u16,
74 pub pre_defined4: i16,
76}
77
78impl VisualSampleEntry {
79 pub fn new(sample_entry: SampleEntry, width: u16, height: u16, compressor_name: [u8; 32]) -> Self {
81 Self {
82 sample_entry,
83 pre_defined: 0,
84 reserved1: 0,
85 pre_defined2: [0; 3],
86 width,
87 height,
88 horiz_resolution: FixedU32::from_bits(0x00480000),
89 vert_resolution: FixedU32::from_bits(0x00480000),
90 reserved2: 0,
91 frame_count: 1,
92 compressor_name,
93 depth: 0x0018,
94 pre_defined4: -1,
95 }
96 }
97}
98
99impl<'a> Deserialize<'a> for VisualSampleEntry {
100 fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
101 where
102 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
103 {
104 let sample_entry = SampleEntry::deserialize(&mut reader)?;
105 let pre_defined = u16::deserialize(&mut reader)?;
106 let reserved1 = u16::deserialize(&mut reader)?;
107 let pre_defined2 = <[u32; 3]>::deserialize(&mut reader)?;
108 let width = u16::deserialize(&mut reader)?;
109 let height = u16::deserialize(&mut reader)?;
110 let horiz_resolution = FixedU32::from_bits(u32::deserialize(&mut reader)?);
111 let vert_resolution = FixedU32::from_bits(u32::deserialize(&mut reader)?);
112 let reserved2 = u32::deserialize(&mut reader)?;
113 let frame_count = u16::deserialize(&mut reader)?;
114 let compressor_name = <[u8; 32]>::deserialize(&mut reader)?;
115 let depth = u16::deserialize(&mut reader)?;
116 let pre_defined4 = i16::deserialize(&mut reader)?;
117
118 Ok(Self {
119 sample_entry,
120 pre_defined,
121 reserved1,
122 pre_defined2,
123 width,
124 height,
125 horiz_resolution,
126 vert_resolution,
127 reserved2,
128 frame_count,
129 compressor_name,
130 depth,
131 pre_defined4,
132 })
133 }
134}
135
136impl Serialize for VisualSampleEntry {
137 fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
138 where
139 W: std::io::Write,
140 {
141 self.sample_entry.serialize(&mut writer)?;
142 self.pre_defined.serialize(&mut writer)?;
143 self.reserved1.serialize(&mut writer)?;
144 self.pre_defined2.serialize(&mut writer)?;
145 self.width.serialize(&mut writer)?;
146 self.height.serialize(&mut writer)?;
147 self.horiz_resolution.to_bits().serialize(&mut writer)?;
148 self.vert_resolution.to_bits().serialize(&mut writer)?;
149 self.reserved2.serialize(&mut writer)?;
150 self.frame_count.serialize(&mut writer)?;
151 self.compressor_name.serialize(&mut writer)?;
152 self.depth.serialize(&mut writer)?;
153 self.pre_defined4.serialize(&mut writer)?;
154 Ok(())
155 }
156}
157
158impl IsoSized for VisualSampleEntry {
159 fn size(&self) -> usize {
160 self.sample_entry.size()
161 + 2 + 2 + self.pre_defined2.size() + 2 + 2 + 4 + 4 + 4 + 2 + self.compressor_name.size() + 2 + 2 }
174}
175
176#[derive(IsoBox, Debug, PartialEq, Eq)]
180#[iso_box(box_type = b"clap", crate_path = crate)]
181pub struct CleanApertureBox {
182 pub clean_aperture_width_n: u32,
184 pub clean_aperture_width_d: u32,
186 pub clean_aperture_height_n: u32,
188 pub clean_aperture_height_d: u32,
190 pub horiz_off_n: u32,
193 pub horiz_off_d: u32,
196 pub vert_off_n: u32,
199 pub vert_off_d: u32,
202}
203
204#[derive(IsoBox, Debug, PartialEq, Eq)]
208#[iso_box(box_type = b"pasp", crate_path = crate)]
209pub struct PixelAspectRatioBox {
210 pub h_spacing: u32,
212 pub v_spacing: u32,
214}
215
216impl Default for PixelAspectRatioBox {
217 fn default() -> Self {
218 Self {
219 h_spacing: 1,
220 v_spacing: 1,
221 }
222 }
223}
224
225#[derive(IsoBox, Debug, PartialEq, Eq)]
229#[iso_box(box_type = b"colr", crate_path = crate)]
230pub struct ColourInformationBox<'a> {
231 pub colour_info: ColourInformation<'a>,
233}
234
235#[derive(Debug, PartialEq, Eq)]
237pub enum ColourInformation<'a> {
238 Nclx(NclxColourInformation),
240 RIcc {
242 icc_profile: BytesCow<'a>,
244 },
245 Prof {
247 icc_profile: BytesCow<'a>,
249 },
250 Other {
252 colour_type: [u8; 4],
254 data: BytesCow<'a>,
256 },
257}
258
259impl<'a> Deserialize<'a> for ColourInformation<'a> {
260 fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
261 where
262 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
263 {
264 let colour_type = <[u8; 4]>::deserialize(&mut reader)?;
265
266 match &colour_type {
267 b"nclx" => {
268 let colour_info = NclxColourInformation::deserialize(&mut reader)?;
269 Ok(ColourInformation::Nclx(colour_info))
270 }
271 b"rICC" => {
272 let icc_profile = reader.try_read_to_end()?;
273 Ok(ColourInformation::RIcc { icc_profile })
274 }
275 b"prof" => {
276 let icc_profile = reader.try_read_to_end()?;
277 Ok(ColourInformation::Prof { icc_profile })
278 }
279 _ => Ok(Self::Other {
280 colour_type,
281 data: reader.try_read_to_end()?,
282 }),
283 }
284 }
285}
286
287impl Serialize for ColourInformation<'_> {
288 fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
289 where
290 W: std::io::Write,
291 {
292 match self {
293 ColourInformation::Nclx(info) => {
294 b"nclx".serialize(&mut writer)?;
295 info.serialize(&mut writer)?;
296 }
297 ColourInformation::RIcc { icc_profile } => {
298 b"rICC".serialize(&mut writer)?;
299 icc_profile.serialize(&mut writer)?;
300 }
301 ColourInformation::Prof { icc_profile } => {
302 b"prof".serialize(&mut writer)?;
303 icc_profile.serialize(&mut writer)?;
304 }
305 ColourInformation::Other { colour_type, data } => {
306 colour_type.serialize(&mut writer)?;
307 data.serialize(&mut writer)?;
308 }
309 }
310 Ok(())
311 }
312}
313
314impl IsoSized for ColourInformation<'_> {
315 fn size(&self) -> usize {
316 match self {
317 ColourInformation::Nclx(info) => 4 + info.size(),
318 ColourInformation::RIcc { icc_profile } => 4 + icc_profile.size(),
319 ColourInformation::Prof { icc_profile } => 4 + icc_profile.size(),
320 ColourInformation::Other { data, .. } => 4 + data.size(),
321 }
322 }
323}
324
325#[derive(Debug, PartialEq, Eq)]
327pub struct NclxColourInformation {
328 pub colour_primaries: u16,
330 pub transfer_characteristics: u16,
332 pub matrix_coefficients: u16,
334 pub full_range_flag: bool,
336}
337
338impl<'a> Deserialize<'a> for NclxColourInformation {
339 fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
340 where
341 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
342 {
343 Ok(Self {
344 colour_primaries: u16::deserialize(&mut reader)?,
345 transfer_characteristics: u16::deserialize(&mut reader)?,
346 matrix_coefficients: u16::deserialize(&mut reader)?,
347 full_range_flag: u8::deserialize(&mut reader)? >> 7 != 0,
348 })
349 }
350}
351
352impl Serialize for NclxColourInformation {
353 fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
354 where
355 W: std::io::Write,
356 {
357 self.colour_primaries.serialize(&mut writer)?;
358 self.transfer_characteristics.serialize(&mut writer)?;
359 self.matrix_coefficients.serialize(&mut writer)?;
360 ((self.full_range_flag as u8) << 7).serialize(&mut writer)?;
361 Ok(())
362 }
363}
364
365impl IsoSized for NclxColourInformation {
366 fn size(&self) -> usize {
367 2 + 2 + 2 + 1
368 }
369}
370
371#[derive(IsoBox, Debug, PartialEq, Eq)]
379#[iso_box(box_type = b"clli", crate_path = crate)]
380pub struct ContentLightLevelBox {
381 pub max_content_light_level: u16,
383 pub max_pic_average_light_level: u16,
385}
386
387#[derive(IsoBox, Debug, PartialEq, Eq)]
395#[iso_box(box_type = b"mdcv", crate_path = crate)]
396pub struct MasteringDisplayColourVolumeBox {
397 pub display_primaries: [[u16; 2]; 6],
399 pub white_point_x: u16,
401 pub white_point_y: u16,
403 pub max_display_mastering_luminance: u32,
405 pub min_display_mastering_luminance: u32,
407}
408
409#[derive(IsoBox, Debug, PartialEq, Eq)]
418#[iso_box(box_type = b"cclv", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
419pub struct ContentColourVolumeBox {
420 pub reserved1: bool,
422 pub reserved2: bool,
424 pub ccv_reserved_zero_2bits: u8,
426 pub ccv_primaries: Option<[[i32; 2]; 3]>,
428 pub ccv_min_luminance_value: Option<u32>,
430 pub ccv_max_luminance_value: Option<u32>,
432 pub ccv_avg_luminance_value: Option<u32>,
434}
435
436impl<'a> DeserializeSeed<'a, BoxHeader> for ContentColourVolumeBox {
437 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> std::io::Result<Self>
438 where
439 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
440 {
441 let byte = u8::deserialize(&mut reader)?;
442 let reserved1 = ((byte >> 7) & 0b1) != 0;
443 let reserved2 = ((byte >> 6) & 0b1) != 0;
444 let ccv_primaries_present_flag = ((byte >> 5) & 0b1) != 0;
445 let ccv_min_luminance_value_present_flag = ((byte >> 4) & 0b1) != 0;
446 let ccv_max_luminance_value_present_flag = ((byte >> 3) & 0b1) != 0;
447 let ccv_avg_luminance_value_present_flag = ((byte >> 2) & 0b1) != 0;
448 let ccv_reserved_zero_2bits = byte & 0b11;
449
450 let ccv_primaries = if ccv_primaries_present_flag {
451 Some(<[[i32; 2]; 3]>::deserialize(&mut reader)?)
452 } else {
453 None
454 };
455
456 let ccv_min_luminance_value = if ccv_min_luminance_value_present_flag {
457 Some(u32::deserialize(&mut reader)?)
458 } else {
459 None
460 };
461
462 let ccv_max_luminance_value = if ccv_max_luminance_value_present_flag {
463 Some(u32::deserialize(&mut reader)?)
464 } else {
465 None
466 };
467
468 let ccv_avg_luminance_value = if ccv_avg_luminance_value_present_flag {
469 Some(u32::deserialize(&mut reader)?)
470 } else {
471 None
472 };
473
474 Ok(Self {
475 reserved1,
476 reserved2,
477 ccv_reserved_zero_2bits,
478 ccv_primaries,
479 ccv_min_luminance_value,
480 ccv_max_luminance_value,
481 ccv_avg_luminance_value,
482 })
483 }
484}
485
486impl Serialize for ContentColourVolumeBox {
487 fn serialize<W>(&self, writer: W) -> std::io::Result<()>
488 where
489 W: std::io::Write,
490 {
491 let mut bit_writer = BitWriter::new(writer);
492
493 bit_writer.write_bit(self.reserved1)?;
494 bit_writer.write_bit(self.reserved2)?;
495 bit_writer.write_bit(self.ccv_primaries.is_some())?;
496 bit_writer.write_bit(self.ccv_min_luminance_value.is_some())?;
497 bit_writer.write_bit(self.ccv_max_luminance_value.is_some())?;
498 bit_writer.write_bit(self.ccv_avg_luminance_value.is_some())?;
499 bit_writer.write_bits(self.ccv_reserved_zero_2bits as u64, 2)?;
500
501 if let Some(ccv_primaries) = &self.ccv_primaries {
502 ccv_primaries.serialize(&mut bit_writer)?;
503 }
504 if let Some(ccv_min_luminance_value) = &self.ccv_min_luminance_value {
505 ccv_min_luminance_value.serialize(&mut bit_writer)?;
506 }
507 if let Some(ccv_max_luminance_value) = &self.ccv_max_luminance_value {
508 ccv_max_luminance_value.serialize(&mut bit_writer)?;
509 }
510 if let Some(ccv_avg_luminance_value) = &self.ccv_avg_luminance_value {
511 ccv_avg_luminance_value.serialize(&mut bit_writer)?;
512 }
513
514 Ok(())
515 }
516}
517
518impl IsoSized for ContentColourVolumeBox {
519 fn size(&self) -> usize {
520 let mut size = 0;
521 size += 1; if let Some(ccv_primaries) = self.ccv_primaries {
523 size += ccv_primaries.size();
524 }
525 if let Some(ccv_min_luminance_value) = self.ccv_min_luminance_value {
526 size += ccv_min_luminance_value.size();
527 }
528 if let Some(ccv_max_luminance_value) = self.ccv_max_luminance_value {
529 size += ccv_max_luminance_value.size();
530 }
531 if let Some(ccv_avg_luminance_value) = self.ccv_avg_luminance_value {
532 size += ccv_avg_luminance_value.size();
533 }
534
535 Self::add_header_size(size)
536 }
537}
538
539#[derive(IsoBox, Debug, PartialEq, Eq)]
546#[iso_box(box_type = b"amve", crate_path = crate)]
547pub struct AmbientViewingEnvironmentBox {
548 pub ambient_illuminance: u32,
550 pub ambient_light_x: u16,
552 pub ambient_light_y: u16,
554}