1+ // inspired by: https://gist.github.com/Zaggy1024/a030cf23069ed62d452161f579ed272f
2+
13#pragma endian big
24
35
@@ -94,14 +96,36 @@ struct CTYPAtom : Atom {
9496 char id[4];
9597};
9698
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+
97120// moov -> udta
98121struct UserDataChildAtomSelector {
99122 Atom atom_header [[hidden]];
100-
123+
101124 $ = addressof(this);
102125
103- match(atom_header.box_type) {
126+ match(atom_header.box_type) {
104127 ("ctyp"): CTYPAtom ctyp;
128+ ("NAVG"): NAVGAtom navg;
105129 (_): UnknownAtom unknown [[name(atom_header.box_type)]];
106130 }
107131} [[inline]];
@@ -188,7 +212,18 @@ struct MovieHeaderAtom : FullAtom {
188212 u32 next_track_id;
189213}[[format("format_mvhd")]];
190214
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;
192227 u32 creation_time;
193228 u32 modification_time;
194229 u32 track_id;
@@ -200,8 +235,8 @@ struct TrackHeaderAtom : FullAtom {
200235 fixed_s16 volume;
201236 padding[sizeof(u16)];
202237 Matrix matrix;
203- fixed_u32 track_width;
204- fixed_u32 track_height;
238+ fixed_s32 track_width;
239+ fixed_s32 track_height;
205240};
206241
207242using EditListAtom;
@@ -246,7 +281,7 @@ struct ChunkOffsetAtom : FullAtom {
246281
247282struct UnknownSampleEntryChildSelector {
248283 Atom box_header [[hidden]];
249-
284+
250285 $ = addressof(this);
251286 match(atom_header.box_type) {
252287 (_): UnknownAtom unknown [[name(box_header.box_type)]];
@@ -277,8 +312,8 @@ struct VisualSampleEntry : SampleEntry {
277312 u32 spatial_quality;
278313 u16 width;
279314 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
282317 padding[sizeof(u32)];
283318 u16 frame_count_per_sample;
284319 u8 compressorname_size [[hidden]];
@@ -296,9 +331,9 @@ struct PanoSampleDescription: Atom {
296331 // https://developer.apple.com/library/archive/technotes/tn/tn1035.html
297332 std::print("pano located at: 0x{:X}", addressof(this));
298333 padding[sizeof(u32)];
299- padding[sizeof(u32)];
334+ padding[sizeof(u32)]; // must be zero, sometimes it contains a 1
300335
301- s16 majorVersion;
336+ s16 majorVersion; // must be zero, sometimes it contains a 1
302337 s16 minorVersion;
303338 s32 sceneTrackID;
304339 s32 loResSceneTrackID;
@@ -311,7 +346,7 @@ struct PanoSampleDescription: Atom {
311346 fixed_s32 vPanBottom; // TODO: number is off...
312347 fixed_s32 minimumZoom;
313348 fixed_s32 maximumZoom;
314-
349+
315350 // Info for highest res version of scene track
316351
317352 s32 sceneSizeX;
@@ -321,26 +356,29 @@ struct PanoSampleDescription: Atom {
321356 s16 sceneNumFramesX;
322357 s16 sceneNumFramesY;
323358 s16 sceneColorDepth;
324-
359+
325360 // Info for highest res version of hotSpot track
326361 s32 hotSpotSizeX;
327362 s32 hotSpotSizeY;
328363 padding[sizeof(u16)];
329- s16 hotSponNumFramesX ;
364+ s16 hotSpotNumFramesX ;
330365 s16 hotSpotNumFrameY;
331- s16 hotsportColorDepth ;
366+ s16 hotspotColorDepth ;
332367
333368 $ += contents_size(addressof(this), box_size);
334369};
335370
336371struct SampleEntrySelector {
337372 Atom atom_header [[hidden]];
338-
373+
339374 $ = addressof(this);
340375 match(atom_header.box_type) {
341376 ("cvid"): VisualSampleEntry cvid;
342377 ("smc "): VisualSampleEntry smc;
343- ("pano"): PanoSampleDescription pano;
378+ ("rle "): VisualSampleEntry rle;
379+ ("pano"): PanoSampleDescription pano;
380+ ("SVQ1"): VisualSampleEntry svq;
381+ //("qtvr"): QTVRSampleDescription qtvr;
344382 (_): UnknownSampleEntry unknown [[name(atom_header.box_type)]];
345383 }
346384
@@ -357,11 +395,11 @@ struct SampleDescriptionAtom : FullAtom {
357395// moov -> trak -> mdia -> minf -> stbl -> stts
358396struct TimeToSampleEntry {
359397 u32 sample_count;
360- u32 sample_delta ;
398+ u32 sample_duration ;
361399} [[format("format_stts_entry")]];
362400
363401fn 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 );
365403};
366404
367405struct TimeToSampleAtom : FullAtom {
@@ -434,7 +472,7 @@ using DataReferenceAtom;
434472
435473struct DataEntryAtomSelector {
436474 Atom atom_header [[hidden]];
437-
475+
438476 $ = addressof(this);
439477 match(atom_header.box_type) {
440478 ("alis"): FullAtom alis;
@@ -451,7 +489,7 @@ struct DataReferenceAtom : FullAtom {
451489
452490struct DataInformationChildAtomSelector {
453491 Atom atom_header [[hidden]];
454-
492+
455493 $ = addressof(this);
456494 match(atom_header.box_type) {
457495 ("dref"): DataReferenceAtom dref;
@@ -508,7 +546,7 @@ struct STPanoMediaInfoAtom: Atom {
508546 STPanoMediaInfoChildAtomSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
509547};
510548
511- struct GMHDChildAtomSelector {
549+ struct GMHDChildAtomSelector {
512550 Atom atom_header [[hidden]];
513551
514552 $ = addressof(this);
@@ -530,7 +568,7 @@ struct MediaInformationChildAtomSelector {
530568 Atom atom_header [[hidden]];
531569
532570 $ = addressof(this);
533-
571+
534572 match(atom_header.box_type) {
535573 ("stbl"): SampleTableAtom stbl;
536574 ("hdlr"): HandlerAtom hdlr;
@@ -691,3 +729,117 @@ struct RootAtom {
691729} [[inline]];
692730
693731RootAtom 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