@@ -10,10 +10,51 @@ import std.io;
1010import std.mem;
1111import std.string;
1212
13+ // All known MP4/ISOBMFF container box types (boxes that contain other boxes)
14+ str CONTAINER_BOX_TYPES[28] = {
15+ "moov", // Movie
16+ "trak", // Track
17+ "edts", // Edit
18+ "mdia", // Media
19+ "minf", // Media Information
20+ "dinf", // Data Information
21+ "stbl", // Sample Table
22+ "mvex", // Movie Extends
23+ "moof", // Movie Fragment
24+ "traf", // Track Fragment
25+ "mfra", // Movie Fragment Random Access
26+ "udta", // User Data
27+ "meta", // Metadata
28+ "ilst", // Item List (iTunes metadata)
29+ "meco", // Additional Metadata Container
30+ "tref", // Track Reference
31+ "trgr", // Track Grouping
32+ "sinf", // Protection Scheme Information
33+ "schi", // Scheme Information
34+ "ipro", // Item Protection
35+ "iprp", // Item Properties
36+ "ipco", // Item Property Container
37+ "iref", // Item Reference
38+ "grpl", // Group List
39+ "clip", // Clipping (QuickTime)
40+ "matt", // Track Matte (QuickTime)
41+ "strk", // Sub Track
42+ "strd" // Sub Track Definition
43+ };
44+
1345fn to_string(auto var) {
1446 return str(var);
1547};
1648
49+ fn is_container_box(str type_str) {
50+ for (u32 i = 0, i < 28, i += 1) {
51+ if (CONTAINER_BOX_TYPES[i] == type_str) {
52+ return true;
53+ }
54+ }
55+ return false;
56+ };
57+
1758fn format_string(auto string) {
1859 return string.value;
1960};
@@ -40,6 +81,8 @@ struct string {
4081 char value[std::mem::find_sequence_in_range(0, $, std::mem::size(), 0x00) - $];
4182} [[sealed, format("format_string")]];
4283
84+ using Box;
85+
4386struct BaseBox {
4487 u64 boxSize = 0;
4588 u64 startOffset = $;
@@ -55,13 +98,19 @@ struct BaseBox {
5598 if (this.size == 1) {
5699 u64 largeSize;
57100 boxSize = largeSize;
58- endOffset = startOffset + boxSize;
101+ if (startOffset + boxSize > std::mem::size())
102+ endOffset = std::mem::size();
103+ else
104+ endOffset = startOffset + boxSize;
59105 } else if (this.size == 0) {
60106 boxSize = std::mem::size() - startOffset;
61107 endOffset = std::mem::size();
62108 } else {
63109 boxSize = size;
64- endOffset = startOffset + boxSize;
110+ if (startOffset + boxSize > std::mem::size())
111+ endOffset = std::mem::size();
112+ else
113+ endOffset = startOffset + boxSize;
65114 }
66115
67116 if (this.type == "uuid") {
@@ -150,19 +199,6 @@ struct DataReferenceBox : FullBox {
150199 DataEntryBox data_entries[this.entry_count];
151200};
152201
153- struct SubDataInformationBox {
154- u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
155-
156- match (str(type)) {
157- ("dref"): DataReferenceBox box [[inline]];
158- (_): UnknownBox box [[inline]];
159- }
160- } [[name(std::format("DataInformationBox({})", box.type))]];
161-
162- struct DataInformationBox : BaseBox {
163- SubDataInformationBox box[while($ < endOffset)] [[inline]];
164- };
165-
166202struct HandlerBox : FullBox {
167203 u32 component_type;
168204 char handler_type[4];
@@ -213,19 +249,9 @@ struct Mp4aBox : BaseBox {
213249 u8 unk[while($ != endOffset)];
214250};
215251
216- struct SubSampleDescriptionBox {
217- u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
218-
219- match (str(type)) {
220- ("mp4a"): Mp4aBox box [[inline]];
221- ("avc1"): Avc1Box box [[inline]];
222- (_): UnknownBox box [[inline]];
223- }
224- } [[name(std::format("SubSampleDescriptionBox({})", box.type))]];
225-
226252struct SampleDescriptionBox : FullBox {
227253 u32 entry_count;
228- SubSampleDescriptionBox box[while($ < endOffset)] [[inline]];
254+ Box box[while($ < endOffset)] [[inline]];
229255};
230256
231257struct SampleTimeToSampleEntry {
@@ -291,41 +317,6 @@ struct SampleSizeBox: FullBox {
291317 }
292318};
293319
294- struct SubSampleBoxTable {
295- u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
296-
297- match (str(type)) {
298- ("stsd"): SampleDescriptionBox box [[inline]];
299- ("stts"): SampleTimeToSampleBox box [[inline]];
300- ("stsc"): SampleToChunkBox box [[inline]];
301- ("stco"): ChunkOffsetBox box [[inline]];
302- ("stss"): SyncSampleBox box [[inline]];
303- ("ctts"): CompositionOffsetBox box [[inline]];
304- ("stsz"): SampleSizeBox box [[inline]];
305- (_): UnknownBox box [[inline]];
306- }
307- } [[name(std::format("SubSampleBoxTable({})", box.type))]];
308-
309- struct SampleBoxTable : BaseBox {
310- SubSampleBoxTable box[while($ < endOffset)] [[inline]];
311- };
312-
313- struct SubMediaInformationBox {
314- u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
315-
316- match (str(type)) {
317- ("vmhd"): VideoMediaHeaderBox box [[inline]];
318- ("hdlr"): HandlerBox box [[inline]];
319- ("dinf"): DataInformationBox box [[inline]];
320- ("stbl"): SampleBoxTable box [[inline]];
321- (_): UnknownBox box [[inline]];
322- }
323- } [[name(std::format("MediaInformationBox({})", box.type))]];
324-
325- struct MediaInformationBox : BaseBox {
326- SubMediaInformationBox box[while($ < endOffset)] [[inline]];
327- };
328-
329320struct MediaHeaderBox : FullBox {
330321 if (this.version == 1) {
331322 u64 creation_time;
@@ -342,21 +333,6 @@ struct MediaHeaderBox : FullBox {
342333 u16 quality;
343334};
344335
345- struct SubMediaBox {
346- u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
347-
348- match (str(type)) {
349- ("mdhd"): MediaHeaderBox box [[inline]];
350- ("hdlr"): HandlerBox box [[inline]];
351- ("minf"): MediaInformationBox box [[inline]];
352- (_): UnknownBox box [[inline]];
353- }
354- } [[name(std::format("MediaBox({})", box.type))]];
355-
356- struct MediaBox : BaseBox {
357- SubMediaBox box[while($ < endOffset)] [[inline]];
358- };
359-
360336struct EditListEntry64 {
361337 u64 segment_duration;
362338 s64 media_time;
@@ -380,61 +356,43 @@ struct EditListBox : FullBox {
380356 }
381357};
382358
383- struct SubEditBox {
384- u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
385-
386- match (str(type)) {
387- ("elst"): EditListBox box [[inline]];
388- (_): UnknownBox box [[inline]];
389- }
390- } [[name(std::format("EditBox({})", box.type))]];
391-
392- struct EditBox : BaseBox {
393- SubEditBox box[while($ < endOffset)] [[inline]];
394- };
395-
396- struct SubTrackBox {
397- u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
398-
399- match (str(type)) {
400- ("mdia"): MediaBox box [[inline]];
401- ("edts"): EditBox box [[inline]];
402- ("tkhd"): TrackHeaderBox box [[inline]];
403- (_): UnknownBox box [[inline]];
404- }
405- } [[name(std::format("TrackBox({})", box.type))]];
406-
407- struct TrackBox : BaseBox {
408- SubTrackBox box[while($ < endOffset)] [[inline]];
359+ struct MediaDataBox : BaseBox {
360+ std::mem::Bytes<endOffset - $> data;
409361};
410362
411- struct SubMovieBox {
412- u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
413-
414- match (str(type)) {
415- ("mvhd"): MovieHeaderBox box [[inline]];
416- ("trak"): TrackBox box [[inline]];
417- (_): UnknownBox box [[inline]];
418- // TODO: Add "iods" box
419- }
420- } [[name(std::format("MovieBox({})", box.type))]];
421-
422- struct MovieBox : BaseBox {
423- SubMovieBox box[while($ < endOffset)] [[inline]];
424- };
363+ using Box;
425364
426- struct MediaDataBox : BaseBox {
427- std::mem::Bytes<boxSize - sizeof(size) - sizeof(type)> data ;
365+ struct ContainerBox : BaseBox {
366+ Box children[while($ < endOffset)] [[inline]] ;
428367};
429368
430369struct Box {
431370 u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
432371
433372 match (str(type)) {
434373 ("ftyp"): FileTypeBox box [[inline]];
435- ("moov"): MovieBox box [[inline]];
436374 ("mdat"): MediaDataBox box [[inline]];
437- (_): UnknownBox box [[inline]];
375+ ("mvhd"): MovieHeaderBox box [[inline]];
376+ ("mdhd"): MediaHeaderBox box [[inline]];
377+ ("dref"): DataReferenceBox box [[inline]];
378+ ("tkhd"): TrackHeaderBox box [[inline]];
379+ ("mp4a"): Mp4aBox box [[inline]];
380+ ("avc1"): Avc1Box box [[inline]];
381+ ("stsd"): SampleDescriptionBox box [[inline]];
382+ ("stts"): SampleTimeToSampleBox box [[inline]];
383+ ("stsc"): SampleToChunkBox box [[inline]];
384+ ("stco"): ChunkOffsetBox box [[inline]];
385+ ("stss"): SyncSampleBox box [[inline]];
386+ ("ctts"): CompositionOffsetBox box [[inline]];
387+ ("stsz"): SampleSizeBox box [[inline]];
388+ ("vmhd"): VideoMediaHeaderBox box [[inline]];
389+ ("hdlr"): HandlerBox box [[inline]];
390+ ("elst"): EditListBox box [[inline]];
391+ (_): if (is_container_box(str(type))) {
392+ ContainerBox box [[inline]];
393+ } else {
394+ UnknownBox box [[inline]];
395+ }
438396 }
439397} [[name(std::format("Box({})", box.type))]];
440398
0 commit comments