1use crate::*;
2
3use super::spatial::{decode_children, decode_slot, encode_kept, keep_invalid, spatial_children};
4
5#[derive(Debug, Clone, PartialEq, Default)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17#[cfg_attr(feature = "serde", serde(default))]
18pub struct Vexu {
19 pub must: Option<Must>,
20 pub proj: Option<VexuProj>,
21 pub eyes: Option<Eyes>,
22 pub pack: Option<Pack>,
23 pub unknown: Vec<Any>,
24}
25
26impl Eq for Vexu {}
27
28impl Atom for Vexu {
29 const KIND: FourCC = FourCC::new(b"vexu");
30
31 spatial_children! { must: Must, eyes: Eyes, pack: Pack; last proj: VexuProj }
36}
37
38#[derive(Debug, Clone, PartialEq, Eq, Default)]
41#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
42pub struct Must {
43 pub required_box_types: Vec<FourCC>,
44}
45
46impl AtomExt for Must {
47 type Ext = FullBoxV0;
48
49 const KIND_EXT: FourCC = FourCC::new(b"must");
50
51 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: FullBoxV0) -> Result<Self> {
52 let mut required_box_types = Vec::with_capacity(buf.remaining() / 4);
53 while buf.remaining() >= 4 {
54 required_box_types.push(FourCC::decode(buf)?);
55 }
56 Ok(Must { required_box_types })
57 }
58
59 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<FullBoxV0> {
60 self.required_box_types.encode(buf)?;
61 Ok(FullBoxV0)
62 }
63}
64
65#[derive(Debug, Clone, PartialEq, Default)]
69#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
70#[cfg_attr(feature = "serde", serde(default))]
71pub struct VexuProj {
72 pub must: Option<Must>,
73 pub prji: Option<Prji>,
74 pub kind: Option<VexuProjKind>,
75 pub unknown: Vec<Any>,
76}
77
78impl Eq for VexuProj {}
79
80impl Atom for VexuProj {
81 const KIND: FourCC = FourCC::new(b"proj");
82
83 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
84 let mut proj = VexuProj::default();
85 decode_children(buf, |kind, body| match kind {
86 Must::KIND => decode_slot(Self::KIND, &mut proj.must, body, &mut proj.unknown),
87 Prji::KIND => decode_slot(Self::KIND, &mut proj.prji, body, &mut proj.unknown),
88 kind => match VexuProjKind::from_kind(kind) {
89 Some(projection) => {
90 let decoded = match proj.kind {
91 Some(_) => Err(Error::DuplicateBox(kind)),
92 None => VexuProjKind::check_box(kind, body),
93 };
94 match decoded {
95 Ok(()) => proj.kind = Some(projection),
96 Err(err) => keep_invalid(Self::KIND, kind, body, err, &mut proj.unknown),
97 }
98 }
99 None => proj.unknown.push(Any::Unknown(kind, body.to_vec())),
100 },
101 })?;
102 Ok(proj)
103 }
104
105 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
108 let projection_kind = |kind| VexuProjKind::from_kind(kind).is_some();
109 self.prji.encode(buf)?;
110 encode_kept(&self.unknown, |kind| kind == Prji::KIND, buf)?;
111 self.kind.encode(buf)?;
112 encode_kept(&self.unknown, projection_kind, buf)?;
113 self.must.encode(buf)?;
114 encode_kept(&self.unknown, |kind| kind == Must::KIND, buf)?;
115 encode_kept(
116 &self.unknown,
117 |kind| !matches!(kind, Prji::KIND | Must::KIND) && !projection_kind(kind),
118 buf,
119 )
120 }
121}
122
123#[derive(Debug, Clone, Copy, PartialEq, Eq)]
125#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
126pub struct Prji {
127 pub projection_kind: FourCC,
128}
129
130impl Prji {
131 pub const RECTILINEAR: FourCC = FourCC::new(b"rect");
132 pub const EQUIRECTANGULAR: FourCC = FourCC::new(b"equi");
133 pub const HALF_EQUIRECTANGULAR: FourCC = FourCC::new(b"hequ");
134 pub const FISHEYE: FourCC = FourCC::new(b"fish");
135 pub const PARAMETRIC_IMMERSIVE: FourCC = FourCC::new(b"prim");
136}
137
138impl AtomExt for Prji {
139 type Ext = FullBoxV0;
140
141 const KIND_EXT: FourCC = FourCC::new(b"prji");
142
143 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: FullBoxV0) -> Result<Self> {
144 Ok(Prji {
145 projection_kind: FourCC::decode(buf)?,
146 })
147 }
148
149 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<FullBoxV0> {
150 self.projection_kind.encode(buf)?;
151 Ok(FullBoxV0)
152 }
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq)]
158#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
159#[non_exhaustive]
160pub enum VexuProjKind {
161 Rectilinear,
163 Equirectangular,
165 HalfEquirectangular,
167 Fisheye,
169 ParametricImmersive,
171}
172
173impl VexuProjKind {
174 pub fn kind(self) -> FourCC {
176 match self {
177 Self::Rectilinear => Prji::RECTILINEAR,
178 Self::Equirectangular => Prji::EQUIRECTANGULAR,
179 Self::HalfEquirectangular => Prji::HALF_EQUIRECTANGULAR,
180 Self::Fisheye => Prji::FISHEYE,
181 Self::ParametricImmersive => Prji::PARAMETRIC_IMMERSIVE,
182 }
183 }
184
185 fn from_kind(kind: FourCC) -> Option<Self> {
186 Some(match kind {
187 Prji::RECTILINEAR => Self::Rectilinear,
188 Prji::EQUIRECTANGULAR => Self::Equirectangular,
189 Prji::HALF_EQUIRECTANGULAR => Self::HalfEquirectangular,
190 Prji::FISHEYE => Self::Fisheye,
191 Prji::PARAMETRIC_IMMERSIVE => Self::ParametricImmersive,
192 _ => return None,
193 })
194 }
195
196 fn check_box(kind: FourCC, mut body: &[u8]) -> Result<()> {
198 FullBoxV0::decode(u32::decode(&mut body)?)?;
199 match body.is_empty() {
200 true => Ok(()),
201 false => Err(Error::UnderDecode(kind)),
202 }
203 }
204}
205
206impl Encode for VexuProjKind {
207 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
208 buf.encode_atom(self.kind(), |buf| 0u32.encode(buf))
209 }
210}
211
212#[derive(Debug, Clone, PartialEq, Default)]
215#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
216#[cfg_attr(feature = "serde", serde(default))]
217pub struct Eyes {
218 pub must: Option<Must>,
219 pub stri: Option<Stri>,
220 pub hero: Option<Hero>,
221 pub cams: Option<Cams>,
222 pub cmfy: Option<Cmfy>,
223 pub unknown: Vec<Any>,
224}
225
226impl Eq for Eyes {}
227
228impl Atom for Eyes {
229 const KIND: FourCC = FourCC::new(b"eyes");
230
231 spatial_children! { must: Must, stri: Stri, hero: Hero, cams: Cams, cmfy: Cmfy }
232}
233
234#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
237#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
238pub struct Stri {
239 pub eye_views_reversed: bool,
240 pub has_additional_views: bool,
241 pub has_right_eye_view: bool,
242 pub has_left_eye_view: bool,
243}
244
245impl AtomExt for Stri {
246 type Ext = FullBoxV0;
247
248 const KIND_EXT: FourCC = FourCC::new(b"stri");
249
250 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: FullBoxV0) -> Result<Self> {
251 let bits = u8::decode(buf)?;
252 if bits & 0xf0 != 0 {
253 return Err(Error::Reserved);
254 }
255 Ok(Stri {
256 eye_views_reversed: bits & 0b1000 != 0,
257 has_additional_views: bits & 0b0100 != 0,
258 has_right_eye_view: bits & 0b0010 != 0,
259 has_left_eye_view: bits & 0b0001 != 0,
260 })
261 }
262
263 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<FullBoxV0> {
264 let bits = (self.eye_views_reversed as u8) << 3
265 | (self.has_additional_views as u8) << 2
266 | (self.has_right_eye_view as u8) << 1
267 | (self.has_left_eye_view as u8);
268 bits.encode(buf)?;
269 Ok(FullBoxV0)
270 }
271}
272
273#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
276#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
277pub struct Hero {
278 pub hero_eye_indicator: u8,
279}
280
281impl Hero {
282 pub const NONE: u8 = 0;
283 pub const LEFT: u8 = 1;
284 pub const RIGHT: u8 = 2;
285}
286
287impl AtomExt for Hero {
288 type Ext = FullBoxV0;
289
290 const KIND_EXT: FourCC = FourCC::new(b"hero");
291
292 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: FullBoxV0) -> Result<Self> {
293 Ok(Hero {
294 hero_eye_indicator: u8::decode(buf)?,
295 })
296 }
297
298 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<FullBoxV0> {
299 self.hero_eye_indicator.encode(buf)?;
300 Ok(FullBoxV0)
301 }
302}
303
304#[derive(Debug, Clone, PartialEq, Default)]
308#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
309#[cfg_attr(feature = "serde", serde(default))]
310pub struct Cams {
311 pub must: Option<Must>,
312 pub blin: Option<Blin>,
313 pub unknown: Vec<Any>,
314}
315
316impl Eq for Cams {}
317
318impl Atom for Cams {
319 const KIND: FourCC = FourCC::new(b"cams");
320
321 spatial_children! { must: Must, blin: Blin }
322}
323
324#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
327#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
328pub struct Blin {
329 pub baseline_value: u32,
330}
331
332impl AtomExt for Blin {
333 type Ext = FullBoxV0;
334
335 const KIND_EXT: FourCC = FourCC::new(b"blin");
336
337 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: FullBoxV0) -> Result<Self> {
338 Ok(Blin {
339 baseline_value: u32::decode(buf)?,
340 })
341 }
342
343 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<FullBoxV0> {
344 self.baseline_value.encode(buf)?;
345 Ok(FullBoxV0)
346 }
347}
348
349#[derive(Debug, Clone, PartialEq, Default)]
353#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
354#[cfg_attr(feature = "serde", serde(default))]
355pub struct Cmfy {
356 pub must: Option<Must>,
357 pub dadj: Option<Dadj>,
358 pub unknown: Vec<Any>,
359}
360
361impl Eq for Cmfy {}
362
363impl Atom for Cmfy {
364 const KIND: FourCC = FourCC::new(b"cmfy");
365
366 spatial_children! { must: Must, dadj: Dadj }
367}
368
369#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
373#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
374pub struct Dadj {
375 pub disparity_adjustment: i32,
376}
377
378impl Dadj {
379 pub const DENOMINATOR: i32 = 10_000;
380}
381
382impl AtomExt for Dadj {
383 type Ext = FullBoxV0;
384
385 const KIND_EXT: FourCC = FourCC::new(b"dadj");
386
387 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: FullBoxV0) -> Result<Self> {
388 Ok(Dadj {
389 disparity_adjustment: i32::decode(buf)?,
390 })
391 }
392
393 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<FullBoxV0> {
394 self.disparity_adjustment.encode(buf)?;
395 Ok(FullBoxV0)
396 }
397}
398
399#[derive(Debug, Clone, PartialEq, Default)]
401#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
402#[cfg_attr(feature = "serde", serde(default))]
403pub struct Pack {
404 pub must: Option<Must>,
405 pub pkin: Option<Pkin>,
406 pub unknown: Vec<Any>,
407}
408
409impl Eq for Pack {}
410
411impl Atom for Pack {
412 const KIND: FourCC = FourCC::new(b"pack");
413
414 spatial_children! { must: Must, pkin: Pkin }
415}
416
417#[derive(Debug, Clone, Copy, PartialEq, Eq)]
420#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
421pub struct Pkin {
422 pub view_packing_kind: FourCC,
423}
424
425impl Pkin {
426 pub const SIDE_BY_SIDE: FourCC = FourCC::new(b"side");
427 pub const OVER_UNDER: FourCC = FourCC::new(b"over");
428}
429
430impl AtomExt for Pkin {
431 type Ext = FullBoxV0;
432
433 const KIND_EXT: FourCC = FourCC::new(b"pkin");
434
435 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: FullBoxV0) -> Result<Self> {
436 Ok(Pkin {
437 view_packing_kind: FourCC::decode(buf)?,
438 })
439 }
440
441 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<FullBoxV0> {
442 self.view_packing_kind.encode(buf)?;
443 Ok(FullBoxV0)
444 }
445}
446
447#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
453#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
454pub struct Hfov {
455 pub field_of_view: u32,
456}
457
458impl Hfov {
459 pub const DENOMINATOR: u32 = 1_000;
460}
461
462impl Atom for Hfov {
463 const KIND: FourCC = FourCC::new(b"hfov");
464
465 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
466 Ok(Hfov {
467 field_of_view: u32::decode(buf)?,
468 })
469 }
470
471 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
472 self.field_of_view.encode(buf)
473 }
474}