1
+ // inspired by: https://gist.github.com/Zaggy1024/a030cf23069ed62d452161f579ed272f
2
+
1
3
#pragma endian big
2
4
3
5
@@ -94,14 +96,36 @@ struct CTYPAtom : Atom {
94
96
char id[4];
95
97
};
96
98
99
+ struct NAVGAtom: Atom {
100
+ u16 version;
101
+ u16 columns;
102
+ u16 rows;
103
+ padding[2];
104
+ u16 loop_size;
105
+ u16 frame_duration;
106
+
107
+ u16 movie_type;
108
+ u16 ticks;
109
+ fixed_s32 field_of_view;
110
+ fixed_s32 startHPan;
111
+ fixed_s32 endHPan;
112
+ fixed_s32 endVPan;
113
+ fixed_s32 startVPan;
114
+ fixed_s32 initialHPan;
115
+ fixed_s32 initialVPan;
116
+ padding[4];
117
+
118
+ };
119
+
97
120
// moov -> udta
98
121
struct UserDataChildAtomSelector {
99
122
Atom atom_header [[hidden]];
100
-
123
+
101
124
$ = addressof(this);
102
125
103
- match(atom_header.box_type) {
126
+ match(atom_header.box_type) {
104
127
("ctyp"): CTYPAtom ctyp;
128
+ ("NAVG"): NAVGAtom navg;
105
129
(_): UnknownAtom unknown [[name(atom_header.box_type)]];
106
130
}
107
131
} [[inline]];
@@ -188,7 +212,18 @@ struct MovieHeaderAtom : FullAtom {
188
212
u32 next_track_id;
189
213
}[[format("format_mvhd")]];
190
214
191
- struct TrackHeaderAtom : FullAtom {
215
+ bitfield TrackHeaderFlags {
216
+ padding : 4;
217
+ bool track_in_poster: 1;
218
+ bool track_in_preview: 1;
219
+ bool track_in_movie: 1;
220
+ bool track_enabled : 1;
221
+ };
222
+
223
+ struct TrackHeaderAtom : Atom {
224
+ u8 version;
225
+ padding[2];
226
+ TrackHeaderFlags;
192
227
u32 creation_time;
193
228
u32 modification_time;
194
229
u32 track_id;
@@ -200,8 +235,8 @@ struct TrackHeaderAtom : FullAtom {
200
235
fixed_s16 volume;
201
236
padding[sizeof(u16)];
202
237
Matrix matrix;
203
- fixed_u32 track_width;
204
- fixed_u32 track_height;
238
+ fixed_s32 track_width;
239
+ fixed_s32 track_height;
205
240
};
206
241
207
242
using EditListAtom;
@@ -246,7 +281,7 @@ struct ChunkOffsetAtom : FullAtom {
246
281
247
282
struct UnknownSampleEntryChildSelector {
248
283
Atom box_header [[hidden]];
249
-
284
+
250
285
$ = addressof(this);
251
286
match(atom_header.box_type) {
252
287
(_): UnknownAtom unknown [[name(box_header.box_type)]];
@@ -277,8 +312,8 @@ struct VisualSampleEntry : SampleEntry {
277
312
u32 spatial_quality;
278
313
u16 width;
279
314
u16 height;
280
- fixed_u32 horizresolution;
281
- fixed_u32 vertresolution;
315
+ fixed_s32 horizresolution; // in pixels per inch
316
+ fixed_s32 vertresolution; // in pixels per inch
282
317
padding[sizeof(u32)];
283
318
u16 frame_count_per_sample;
284
319
u8 compressorname_size [[hidden]];
@@ -296,9 +331,9 @@ struct PanoSampleDescription: Atom {
296
331
// https://developer.apple.com/library/archive/technotes/tn/tn1035.html
297
332
std::print("pano located at: 0x{:X}", addressof(this));
298
333
padding[sizeof(u32)];
299
- padding[sizeof(u32)];
334
+ padding[sizeof(u32)]; // must be zero, sometimes it contains a 1
300
335
301
- s16 majorVersion;
336
+ s16 majorVersion; // must be zero, sometimes it contains a 1
302
337
s16 minorVersion;
303
338
s32 sceneTrackID;
304
339
s32 loResSceneTrackID;
@@ -311,7 +346,7 @@ struct PanoSampleDescription: Atom {
311
346
fixed_s32 vPanBottom; // TODO: number is off...
312
347
fixed_s32 minimumZoom;
313
348
fixed_s32 maximumZoom;
314
-
349
+
315
350
// Info for highest res version of scene track
316
351
317
352
s32 sceneSizeX;
@@ -321,26 +356,29 @@ struct PanoSampleDescription: Atom {
321
356
s16 sceneNumFramesX;
322
357
s16 sceneNumFramesY;
323
358
s16 sceneColorDepth;
324
-
359
+
325
360
// Info for highest res version of hotSpot track
326
361
s32 hotSpotSizeX;
327
362
s32 hotSpotSizeY;
328
363
padding[sizeof(u16)];
329
- s16 hotSponNumFramesX ;
364
+ s16 hotSpotNumFramesX ;
330
365
s16 hotSpotNumFrameY;
331
- s16 hotsportColorDepth ;
366
+ s16 hotspotColorDepth ;
332
367
333
368
$ += contents_size(addressof(this), box_size);
334
369
};
335
370
336
371
struct SampleEntrySelector {
337
372
Atom atom_header [[hidden]];
338
-
373
+
339
374
$ = addressof(this);
340
375
match(atom_header.box_type) {
341
376
("cvid"): VisualSampleEntry cvid;
342
377
("smc "): VisualSampleEntry smc;
343
- ("pano"): PanoSampleDescription pano;
378
+ ("rle "): VisualSampleEntry rle;
379
+ ("pano"): PanoSampleDescription pano;
380
+ ("SVQ1"): VisualSampleEntry svq;
381
+ //("qtvr"): QTVRSampleDescription qtvr;
344
382
(_): UnknownSampleEntry unknown [[name(atom_header.box_type)]];
345
383
}
346
384
@@ -357,11 +395,11 @@ struct SampleDescriptionAtom : FullAtom {
357
395
// moov -> trak -> mdia -> minf -> stbl -> stts
358
396
struct TimeToSampleEntry {
359
397
u32 sample_count;
360
- u32 sample_delta ;
398
+ u32 sample_duration ;
361
399
} [[format("format_stts_entry")]];
362
400
363
401
fn format_stts_entry(auto stts_entry) {
364
- return std::format("count = {}, delta = {}", stts_entry.sample_count, stts_entry.sample_delta );
402
+ return std::format("count = {}, duration = {}", stts_entry.sample_count, stts_entry.sample_duration );
365
403
};
366
404
367
405
struct TimeToSampleAtom : FullAtom {
@@ -434,7 +472,7 @@ using DataReferenceAtom;
434
472
435
473
struct DataEntryAtomSelector {
436
474
Atom atom_header [[hidden]];
437
-
475
+
438
476
$ = addressof(this);
439
477
match(atom_header.box_type) {
440
478
("alis"): FullAtom alis;
@@ -451,7 +489,7 @@ struct DataReferenceAtom : FullAtom {
451
489
452
490
struct DataInformationChildAtomSelector {
453
491
Atom atom_header [[hidden]];
454
-
492
+
455
493
$ = addressof(this);
456
494
match(atom_header.box_type) {
457
495
("dref"): DataReferenceAtom dref;
@@ -508,7 +546,7 @@ struct STPanoMediaInfoAtom: Atom {
508
546
STPanoMediaInfoChildAtomSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
509
547
};
510
548
511
- struct GMHDChildAtomSelector {
549
+ struct GMHDChildAtomSelector {
512
550
Atom atom_header [[hidden]];
513
551
514
552
$ = addressof(this);
@@ -530,7 +568,7 @@ struct MediaInformationChildAtomSelector {
530
568
Atom atom_header [[hidden]];
531
569
532
570
$ = addressof(this);
533
-
571
+
534
572
match(atom_header.box_type) {
535
573
("stbl"): SampleTableAtom stbl;
536
574
("hdlr"): HandlerAtom hdlr;
@@ -691,3 +729,117 @@ struct RootAtom {
691
729
} [[inline]];
692
730
693
731
RootAtom atoms[while(std::mem::size() - $ > MIN_BOX_SIZE)] @ 0x00 [[format("format_box_array")]];
732
+
733
+ struct HotSpotEntry {
734
+ u16 hotSpotId;
735
+ padding[2];
736
+ char type[4];
737
+ u32 typeData;
738
+ fixed_s32 viewHPan;
739
+ fixed_s32 viewVPan;
740
+ fixed_s32 viewZoom;
741
+ u16 rect1;
742
+ u16 rect2;
743
+ u16 rect3;
744
+ u16 rect4;
745
+ s32 mouseOVerCursorID;
746
+ s32 mouseDownCursorID;
747
+ s32 mouseUpCursorID;
748
+ padding[sizeof(s32)];
749
+ s32 nameStrOffset;
750
+ s32 commentStrOffset;
751
+ };
752
+
753
+ struct pHot: Atom {
754
+ padding[2];
755
+ u16 numHotSpots;
756
+ HotSpotEntry entries[numHotSpots];
757
+ };
758
+
759
+ struct pHdr: Atom {
760
+ u32 nodeID;
761
+ fixed_s32 defHPan;
762
+ fixed_s32 defVPan;
763
+ fixed_s32 defZoom;
764
+ fixed_s32 minHPan;
765
+ fixed_s32 minVPan;
766
+ fixed_s32 minZoom;
767
+ fixed_s32 maxHPan;
768
+ fixed_s32 maxVPan;
769
+ fixed_s32 maxZoom;
770
+ padding[sizeof(u32)];
771
+ padding[sizeof(u32)];
772
+ u32 nameStrOffset;
773
+ u32 commentStrOffset;
774
+ };
775
+
776
+ struct PanoLink {
777
+ u16 linkID;
778
+ padding[sizeof(u16)];
779
+ padding[sizeof(u32)];
780
+ padding[sizeof(u32)];
781
+ u32 toNodeID;
782
+ padding[sizeof(u32) * 3];
783
+ fixed_s32 toHPan;
784
+ fixed_s32 toVPan;
785
+ fixed_s32 toZoom;
786
+ padding[sizeof(u32)];
787
+ padding[sizeof(u32)];
788
+ u32 nameStrOffset;
789
+ u32 commentStrOffset;
790
+ };
791
+
792
+ struct LinkTableAtom : Atom {
793
+ padding[sizeof(u16)];
794
+ u16 numLinks;
795
+ PanoLink entries[numLinks];
796
+ };
797
+
798
+ struct NavgObject {
799
+ u16 objID;
800
+ padding[sizeof(u16)]; // reserved1
801
+ padding[sizeof(u32)]; // reserved2
802
+ fixed_s32 navgHPan;
803
+ fixed_s32 navgVPan;
804
+ fixed_s32 navgZoom;
805
+ u16 rect1;
806
+ u16 rect2;
807
+ u16 rect3;
808
+ u16 rect4;
809
+ padding[sizeof(u32)]; // reserved3
810
+ u32 nameStrOffset;
811
+ u32 commentStrOffset;
812
+ };
813
+
814
+ struct NavgTableAtom : Atom {
815
+ padding[sizeof(u16)];
816
+ u16 numObjects;
817
+ NavgObject entries[numObjects];
818
+ };
819
+
820
+ struct PascalString {
821
+ std::string::SizedString<u8> name;
822
+ };
823
+
824
+ struct StringTableAtom : Atom {
825
+ PascalString children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
826
+ };
827
+
828
+ struct PanoramaMDAT {
829
+ Atom atom_header [[hidden]];
830
+ $ = addressof(this);
831
+ if ($ + contents_size(addressof(this), atom_header.box_size) <= std::mem::size()) {
832
+
833
+ match(atom_header.box_type) {
834
+ ("pHot"): pHot phot;
835
+ ("pHdr"): pHdr phdr;
836
+ ("pLnk"): LinkTableAtom plnk;
837
+ ("strT"): StringTableAtom strt;
838
+ ("pNav"): NavgTableAtom pnav;
839
+ (_): UnknownAtomSelector unknown [[name(atom_header.box_type)]];
840
+ }
841
+ } else {
842
+ $ = std::mem::size();
843
+ }
844
+
845
+ } [[inline]];
0 commit comments