Skip to content

Instantly share code, notes, and snippets.

@Zaggy1024
Created March 10, 2023 10:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Zaggy1024/a030cf23069ed62d452161f579ed272f to your computer and use it in GitHub Desktop.
Save Zaggy1024/a030cf23069ed62d452161f579ed272f to your computer and use it in GitHub Desktop.
//#pragma debug
#pragma endian big
#include <std/core.pat>
#include <std/fxpt.pat>
#include <std/io.pat>
#include <std/math.pat>
#include <std/mem.pat>
#include <std/string.pat>
#include <std/time.pat>
#include <type/byte.pat>
#include <type/guid.pat>
#include <type/size.pat>
#define MIN_BOX_SIZE 8
str current_handler;
fn contents_size(u128 base_offset, u64 size) {
s128 end = size == 0 ? std::mem::size() : base_offset + size;
end = std::math::min(end, std::mem::size());
s128 offset_signed = $;
return end - offset_signed;
};
fn get_box_size() {
u64 size = be u32(std::mem::read_unsigned($, sizeof(u32)));
if (size == 1) {
size = be u64(std::mem::read_unsigned($ + (sizeof(u32) * 2), sizeof(u64)));
}
return size;
};
fn get_box_type() {
u128 start = $ + sizeof(u32);
char a = std::mem::read_unsigned(start, 1);
char b = std::mem::read_unsigned(start + 1, 1);
char c = std::mem::read_unsigned(start + 2, 1);
char d = std::mem::read_unsigned(start + 3, 1);
return std::format("{:c}{:c}{:c}{:c}", a, b, c, d);
};
struct Box {
type::Size32 box_size;
char box_type[4];
if (box_size == 1) {
type::Size64 box_size;
}
if (box_type == "uuid") {
type::GUID user_type;
}
};
using UnknownBox;
fn appears_to_contain_boxes(ref u128 contents_offset, u128 contents_size) {
u128 current_offset = contents_offset;
while (true) {
u32 current_size_raw @ current_offset;
u32 current_size = be u32(current_size_raw);
current_offset += current_size;
if (current_offset == contents_offset || current_offset >= (contents_offset + contents_size)) {
break;
}
}
return current_offset == (contents_offset + contents_size);
};
struct UnknownBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
UnknownBox unknown [[name(box_header.box_type)]];
} [[inline]];
struct UnknownBox : Box {
if (appears_to_contain_boxes($, contents_size(addressof(this), box_size))) {
UnknownBoxSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE && std::mem::size() - $ > MIN_BOX_SIZE)];
} else {
$ += sizeof(u32);
if (appears_to_contain_boxes($, contents_size(addressof(this), box_size))) {
$ -= sizeof(u32);
u8 version;
u24 flags;
UnknownBoxSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE && std::mem::size() - $ > MIN_BOX_SIZE)];
} else {
$ -= sizeof(u32);
}
}
u128 next_offset = std::math::min($ + contents_size(addressof(this), box_size), std::mem::size());
if (next_offset > $) {
u8 unknown_data[next_offset - $] [[sealed]];
} else {
$ = next_offset;
}
} [[format("format_box_type")]];
fn format_box_type(ref auto box) {
return box.box_type;
};
// ftyp
struct FileTypeBox : Box {
char major_brand[4];
u32 minor_version;
char minor_brands[contents_size(addressof(this), box_size)] [[format("format_minor_brands")]];
} [[format("format_ftyp")]];
fn string_trim_end(ref str string, u128 amount) {
u128 length = std::string::length(string);
return std::string::substr(string, 0, length - amount);
};
fn format_minor_brands(ref auto minor_brands) {
str result = "";
u128 i;
for (i = 0, i < sizeof(minor_brands), i += 4) {
result = result + minor_brands[i] + minor_brands[i + 1] + minor_brands[i + 2] + minor_brands[i + 3] + ", ";
}
return string_trim_end(result, 2);
};
fn format_ftyp(ref auto ftyp) {
return std::format("ftyp (major={})", ftyp.major_brand);
};
// meta
using HandlerBox;
using PrimaryItemBox;
using ItemLocationBox;
using ItemInfoBox;
using ItemReferenceBox;
using ItemPropertiesBox;
using DataInformationBox;
using ItemKeysAtom;
using ItemListAtom;
struct FullBox : Box {
u8 version;
u24 flags;
};
struct MetaChildBoxSelector {
// It'd be nice to inherit the skipping behavior and just have the if statement here
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "hdlr") {
HandlerBox hdlr;
} else if (box_header.box_type == "pitm") {
PrimaryItemBox pitm;
} else if (box_header.box_type == "iloc") {
ItemLocationBox iloc;
} else if (box_header.box_type == "iinf") {
ItemInfoBox iinf;
} else if (box_header.box_type == "iref") {
ItemReferenceBox iref;
} else if (box_header.box_type == "iprp") {
ItemPropertiesBox iprp;
} else if (box_header.box_type == "dinf") {
DataInformationBox dinf;
} else if (box_header.box_type == "keys") {
ItemKeysAtom keys;
} else if (box_header.box_type == "ilst") {
ItemListAtom ilst;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
} else {
padding[std::mem::size() - $];
}
} [[inline]];
fn is_hdlr(u128 offset) {
u32 fourcc = be u32(std::mem::read_unsigned(offset, 4));
const u32 hdlr_fourcc = ('h' << 24) | ('d' << 16) | ('l' << 8) | 'r';
return fourcc == hdlr_fourcc;
};
struct MetaBox : Box {
// QuickTime didn't include the version and flags, but must have a handler.
if (!is_hdlr($ + sizeof(u32))) {
u8 version;
u24 flags;
}
MetaChildBoxSelector contents[while(contents_size(addressof(this), box_size) > MIN_BOX_SIZE)] [[format("format_box_array")]];
$ += contents_size(addressof(this), box_size);
} [[format("format_meta")]];
fn format_box_array(ref auto box_array) {
str result = "[ ";
u64 i;
for (i = 0, i < std::core::member_count(box_array), i += 1) {
result = result + box_array[i].box_header.box_type + ", ";
}
return string_trim_end(result, 2) + " ]";
};
fn format_meta(ref auto meta) {
return std::format("meta {}", format_box_array(meta.contents));
};
// (mdia|meta) -> hdlr
struct HandlerBox : FullBox {
if (std::mem::read_unsigned($, 4) != 0x0) {
char component_type[4];
char component_subtype[4];
current_handler = "none";
} else {
padding[sizeof(u32)];
char handler_type[4];
current_handler = handler_type;
}
if (std::mem::read_unsigned($, 4) != 0x0) {
char component_manufacturer[4];
u32 component_flags;
u32 component_flags_mask;
} else {
padding[sizeof(u32) * 3];
}
if (contents_size(addressof(this), box_size) > 0) {
char name[];
}
$ += contents_size(addressof(this), box_size);
} [[format("format_hdlr")]];
fn format_hdlr(ref auto hdlr) {
if (std::core::has_member(hdlr, "name")) {
return std::format("hdlr (type={}, name={})", hdlr.handler_type, string_trim_end(hdlr.name, 1));
}
return std::format("hdlr (type={})", hdlr.handler_type);
};
// meta -> pitm
struct PrimaryItemBox : FullBox {
if (version == 0) {
u16 item_id;
} else {
u32 item_id;
}
$ += contents_size(addressof(this), box_size);
} [[format("format_pitm")]];
fn format_pitm(ref auto pitm) {
return std::format("pitm (id={})", pitm.item_id);
};
// meta -> iloc
bitfield ConstructionMethod {
padding : 12;
value : 4;
} [[inline]];
struct Extent {
if (parent.parent.version == 1 || parent.parent.version == 2) {
if (parent.parent.sizes.index_size == 4) {
u32 index;
} else if (parent.parent.sizes.index_size == 8) {
u64 index;
}
}
if (parent.parent.sizes.offset_size == 4) {
type::Size32 offset;
} else if (parent.parent.sizes.offset_size == 8) {
type::Size64 offset;
}
if (parent.parent.sizes.length_size == 4) {
type::Size32 length;
} else if (parent.parent.sizes.length_size == 8) {
type::Size64 length;
}
} [[format("format_extent")]];
fn format_extent(ref auto extent) {
u64 offset = 0;
if (std::core::has_member(extent, "offset")) {
offset = extent.offset;
}
u64 length = 0;
if (std::core::has_member(extent, "length")) {
length = extent.length;
}
return std::format("[{}..{}] ({})", offset, offset + length, type::impl::size_formatter(length));
};
struct ItemLocation {
if (parent.version < 2) {
u16 item_id;
} else {
u32 item_id;
}
if (parent.version == 1 || parent.version == 2) {
le ConstructionMethod construction_method;
}
u16 data_reference_index;
if (parent.sizes.base_offset_size == 4) {
u8* base_offset : u32;
} else if (parent.sizes.base_offset_size == 8) {
u8* base_offset : u64;
}
u16 extent_count;
Extent extents[extent_count] [[format("format_array")]];
};
fn format_array(ref auto array) {
str result = "[ ";
u64 i;
for (i = 0, i < std::core::member_count(array), i += 1) {
result = result + std::format("{}, ", array[i], ", ");
}
return string_trim_end(result, 2) + " ]";
};
bitfield ItemLocationSizes {
offset_size : 4;
length_size : 4;
base_offset_size : 4;
index_size : 4;
} [[inline,left_to_right]];
struct ItemLocationBox : FullBox {
ItemLocationSizes sizes;
if (version < 2) {
u16 item_count;
} else {
u32 item_count;
}
ItemLocation locations[item_count];
$ += contents_size(addressof(this), box_size);
} [[format("format_iloc")]];
fn format_iloc(ref auto iloc) {
str result = "iloc { ";
u32 i;
for (i = 0, i < iloc.item_count, i += 1) {
result = result + std::format("{} = {}, ", iloc.locations[i].item_id, iloc.locations[i].extents);
}
return string_trim_end(result, 2) + " }";
};
// meta -> iinf
using ItemInfoEntry;
struct ItemInfoEntrySelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "infe") {
ItemInfoEntry infe;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct ItemInfoBox : FullBox {
if (version == 0) {
u16 entry_count;
} else {
u32 entry_count;
}
ItemInfoEntrySelector entries[entry_count];
};
// meta -> iinf -> infe
struct ItemInfoEntry : FullBox {
if (version <= 1) {
u16 item_id;
u16 item_protection_index;
char item_name[];
char content_type[];
char content_encoding[];
if (version == 1) {
char extension_type[4];
if (extension_type == "fdel") {
std::print("TODO: Implement FileDeliveryItemInfoExtension ('fdel')");
}
}
} else {
if (version == 2) {
u16 item_id;
} else {
u32 item_id;
}
u16 item_protection_index;
char item_type[4];
char item_name[];
padding[1];
if (item_type == "mime") {
char content_type[];
char content_encoding[];
} else if (item_type == "uri ") {
char item_uri_type[];
}
}
$ += contents_size(addressof(this), box_size);
} [[format("format_infe")]];
fn format_infe(ref auto infe) {
str type;
if (std::core::has_member(infe, "item_type")) {
type = infe.item_type;
} else {
type = infe.content_type;
}
return std::format("infe {{ id={}, type=\"{}\", name=\"{}\" }}", infe.item_id, type, string_trim_end(infe.item_name, 1));
};
// meta -> iref
struct SingleItemTypeReferenceBox<SizedType> {
u32 box_size;
char reference_type[4];
SizedType from_item_id;
u16 reference_count;
u16 to_item_ids[reference_count];
$ += contents_size(addressof(this), box_size);
};
struct SingleItemTypeReferenceBoxWrapper<SizedType> {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
SingleItemTypeReferenceBox<SizedType> box [[name(box_header.box_type)]];
}
} [[inline]];
struct ItemReferenceBox : FullBox {
if (version == 0) {
SingleItemTypeReferenceBoxWrapper<u16> references[while (contents_size(addressof(this), box_size) > 0)];
} else if (version == 1) {
SingleItemTypeReferenceBoxWrapper<u32> references[while (contents_size(addressof(this), box_size) > 0)];
}
$ += contents_size(addressof(this), box_size);
};
// meta -> iprp
using ItemPropertyContainerBox;
using ItemPropertyAssociationBox;
struct ItemPropertiesChildBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "ipco") {
ItemPropertyContainerBox ipco;
} else if (box_header.box_type == "ipma") {
ItemPropertyAssociationBox ipma;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct ItemPropertiesBox : Box {
ItemPropertiesChildBoxSelector contents[while(contents_size(addressof(this), box_size) > MIN_BOX_SIZE)] [[format("format_box_array")]];
$ += contents_size(addressof(this), box_size);
};
// meta -> iprp -> ipco
using ImageSpatialExtentsProperty;
using PixelInformationBox;
using AuxiliaryTypeProperty;
using ColourInformationBox;
using AV1CodecConfigurationBox;
struct ItemPropertyContainerSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "ispe") {
ImageSpatialExtentsProperty ispe;
} else if (box_header.box_type == "pixi") {
PixelInformationBox pixi;
} else if (box_header.box_type == "av1C") {
AV1CodecConfigurationBox av1C;
} else if (box_header.box_type == "colr") {
ColourInformationBox colr;
} else if (box_header.box_type == "auxC") {
AuxiliaryTypeProperty auxC;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct ItemPropertyContainerBox : Box {
ItemPropertyContainerSelector contents[while(contents_size(addressof(this), box_size) > MIN_BOX_SIZE)] [[format("format_box_array")]];
$ += contents_size(addressof(this), box_size);
};
// meta -> iprp -> ipma
bitfield PropertyIndex8 {
essential : 1;
property_index : 7;
};
bitfield PropertyIndex16 {
essential : 1;
property_index : 15;
};
struct ItemPropertyAssociations<auto ipma_version, auto ipma_flags> {
if (ipma_version == 0) {
u16 item_id;
} else {
u32 item_id;
}
u8 association_count;
if ((ipma_flags & 1) == 1) {
PropertyIndex16 properties[association_count];
} else {
PropertyIndex8 properties[association_count];
}
};
struct ItemPropertyAssociationBox : FullBox {
u32 entry_count;
ItemPropertyAssociations<version, flags> associations[entry_count];
$ += contents_size(addressof(this), box_size);
};
// meta -> keys
struct ItemKey {
u32 size;
char namespace_[4] [[name("namespace")]];
char name[contents_size(addressof(this), size)];
} [[format("format_item_key")]];
fn format_item_key(ref auto item_key) {
return std::format("{}:{}", item_key.namespace_, item_key.name);
};
struct ItemKeysAtom : FullBox {
u32 entry_count;
ItemKey entries[entry_count];
};
// meta -> ilst
// https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/Metadata/Metadata.html
enum WellKnownType : u32 {
Reserved = 0,
UTF8 = 1,
UTF16 = 2,
SJIS = 3,
UTF8Sort = 4,
UTF16Sort = 5,
JPEG = 13,
PNG = 14,
BESignedInt = 21,
BE_UnsignedInt = 22,
BEFloat32 = 23,
BEFloat64 = 24,
BMP = 27,
QTMetadataAtom = 28,
EightBitSignedInt = 65,
BE16BitSignedInt = 66,
BE32BitSignedInt = 67,
BEPointF32 = 70,
BEDimensionsF32 = 71,
BERectF32 = 72,
BE64BitSignedInt = 74,
EightBitUnsignedInt = 75,
BE16BitUnsignedInt = 76,
BE32BitUnsignedInt = 77,
BE64BitUnsignedInt = 78,
AffineTransformF64 = 79,
};
struct DataAtom : Box {
WellKnownType type_indicator;
u32 locale_indicator;
if (type_indicator == WellKnownType::UTF8) {
char value[contents_size(addressof(this), box_size)];
} else if (type_indicator == WellKnownType::UTF16) {
char16 value[contents_size(addressof(this), box_size) / sizeof(char16)];
} else {
u8 value[contents_size(addressof(this), box_size)];
}
} [[format("format_data_atom")]];
fn format_data_atom(ref auto data_atom) {
if (data_atom.type_indicator == WellKnownType::UTF8
|| data_atom.type_indicator == WellKnownType::UTF16) {
return std::format("\"{}\"", data_atom.value);
}
return data_atom.value;
};
struct NameAtom : FullBox {
char value[contents_size(addressof(this), box_size)];
} [[format("format_unwrap_value")]];
struct ItemAtomChildSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "data") {
DataAtom data;
} else if (box_header.box_type == "data") {
NameAtom name;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct ItemAtom {
u32 box_size;
if (current_handler == "mdir") {
char key[4];
} else {
u32 key_index;
}
ItemAtomChildSelector contents[while(contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
$ += contents_size(addressof(this), box_size);
};
struct ItemListAtomChildSelector {
u64 box_size = get_box_size();
if (current_handler == "mdir") {
str box_type = get_box_type();
} else {
u32 box_type = be u32(std::mem::read_unsigned($ + sizeof(u32), 4));
}
$ = addressof(this);
if ($ + contents_size(addressof(this), box_size) <= std::mem::size()) {
ItemAtom data [[name(box_type)]];
}
$ += contents_size(addressof(this), box_size);
} [[inline]];
struct ItemListAtom : Box {
ItemListAtomChildSelector contents[while(contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
$ += contents_size(addressof(this), box_size);
};
// moov
using MovieHeaderBox;
using MovieExtendsBox;
using ObjectDescriptorBox;
using TrackBox;
using UserDataBox;
struct MovieChildBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "mvhd") {
MovieHeaderBox mvhd;
} else if (box_header.box_type == "mvex") {
MovieExtendsBox mvex;
} else if (box_header.box_type == "meta") {
MetaBox meta;
} else if (box_header.box_type == "iods") {
ObjectDescriptorBox iods;
} else if (box_header.box_type == "trak") {
TrackBox trak;
} else if (box_header.box_type == "udta") {
UserDataBox udta;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct MovieBox : Box {
MovieChildBoxSelector children[while(contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
};
// moov -> mvhd
fn to_float(auto value) {
return std::string::parse_float(std::string::to_string(value));
};
fn format_fixed(u32 value, u32 precision) {
// double cast is broken it seems
return to_float(value) / to_float(1 << precision);
};
using fixed_s32 = s32 [[format("format_fixed_32")]];
using fixed_u32 = u32 [[format("format_fixed_32")]];
fn format_fixed_32(u32 value) {
return format_fixed(value, 16);
};
using fixed_s16 = s16 [[format("format_fixed_16")]];
fn format_fixed_16(u16 value) {
return format_fixed(value, 8);
};
using normal_s32 = s32 [[format("format_normal_32")]];
fn format_normal_32(ref auto value) {
return format_fixed(value, 30);
};
struct Matrix {
fixed_s32 matrix_00;
fixed_s32 matrix_01;
fixed_s32 matrix_02;
fixed_s32 matrix_10;
fixed_s32 matrix_11;
fixed_s32 matrix_12;
normal_s32 matrix_20;
normal_s32 matrix_21;
normal_s32 matrix_22;
} [[format("format_matrix")]];
fn format_matrix(ref auto matrix) {
return std::format("[ [ {}, {}, {} ], [ {}, {}, {} ], [ {}, {}, {} ] ]",
format_fixed_32(matrix.matrix_00), format_fixed_32(matrix.matrix_01), format_fixed_32(matrix.matrix_02),
format_fixed_32(matrix.matrix_10), format_fixed_32(matrix.matrix_11), format_fixed_32(matrix.matrix_12),
format_normal_32(matrix.matrix_20), format_normal_32(matrix.matrix_21), format_normal_32(matrix.matrix_22));
};
using datetime<type> = type [[format("format_datetime")]];
fn format_datetime(ref auto value) {
return std::time::format(std::time::to_utc(value - 2082844800));
};
struct MovieHeaderBox : FullBox {
if (version < 2) {
if (version == 1) {
datetime<u64> creation_time;
datetime<u64> modification_time;
u32 timescale;
u64 duration;
} else if (version == 0) {
datetime<u32> creation_time;
datetime<u32> modification_time;
u32 timescale;
u32 duration;
}
fixed_s32 rate;
fixed_s16 volume;
padding[sizeof(u16) + (sizeof(u32) * 2)];
Matrix matrix;
padding[sizeof(u32) * 6];
u32 next_track_id;
} else {
print("Unsupported movie header box version {}", version);
}
$ += contents_size(addressof(this), box_size);
} [[format("format_mvhd")]];
fn format_duration(ref auto duration, ref auto timescale) {
float duration_f = duration;
float timescale_f = timescale;
float total_seconds = duration_f / timescale_f;
u128 minutes = std::math::floor(total_seconds / 60);
float seconds = total_seconds - (minutes * 60);
if (minutes > 0) {
return std::format("{:02d}:{:06.3f}", minutes, seconds);
} else {
return std::format("{:.3f}s", seconds);
}
};
fn format_mvhd(ref auto mvhd) {
return "mvhd { duration = " + format_duration(mvhd.duration, mvhd.timescale) + " }";
};
// moov -> mvex
using MovieExtendsHeaderBox;
using TrackExtendsBox;
struct MovieExtendsChildBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "mehd") {
MovieExtendsHeaderBox mehd;
} else if (box_header.box_type == "trex") {
TrackExtendsBox trex;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct MovieExtendsBox : Box {
MovieExtendsChildBoxSelector children[while(contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
};
// moov -> mvex -> mehd
struct MovieExtendsHeaderBox : FullBox {
if (version < 2) {
if (version == 1) {
u64 fragment_duration;
} else {
u32 fragment_duration;
}
}
$ += contents_size(addressof(this), box_size);
};
// moov -> mvex -> trex
bitfield FragmentSampleFlags {
reserved : 4;
is_leading : 2;
sample_depends_on : 2;
sample_is_depended_on : 2;
sample_has_redundancy : 2;
sample_padding_value : 3;
sample_is_non_sync : 1;
sample_degradation_priority : 16;
} [[left_to_right]];
struct TrackExtendsBox : FullBox {
u32 track_id;
u32 default_sample_description_index;
u32 default_sample_duration;
u32 default_sample_size;
FragmentSampleFlags default_sample_flags;
$ += contents_size(addressof(this), box_size);
};
// moov -> iods
using InitialObjectDescriptor;
struct ObjectDescriptorBox : FullBox {
InitialObjectDescriptor initial;
$ += contents_size(addressof(this), box_size);
};
// moov -> iods -> *
// ISO IEC 14496-1 MPEG-4 System Standard
struct VLQ128 {
u8 array[while ($ < std::mem::size() && ($ == addressof(this) || std::mem::read_unsigned($ - 1, 1) & 0x80 != 0))] [[hidden]];
} [[sealed,format("transform_vlq128"),transform("transform_vlq128")]];
fn transform_vlq128(ref auto vlq128) {
u128 result = 0;
for (u8 i = 0, i < std::core::member_count(vlq128.array), i += 1) {
result = (result << 7) | (vlq128.array[i] & 0x7f);
}
return result;
};
struct Descriptor {
u8 tag;
VLQ128 instance_size;
};
struct UnknownDescriptor : Descriptor {
$ += contents_size(addressof(this), instance_size) + sizeof(Descriptor);
};
bitfield InitialObjectDescriptorInitialBits {
object_descriptor_id : 10;
url_flag : 1;
include_inline_profile_level_flag : 1;
padding : 4;
// These should appear in the order they are declared in, left_to_right reverses them.
} [[inline,left_to_right]];
// moov -> iods -> MP4_IOD
using ElementalStreamIDDescriptor;
struct ObjectDescriptorSelector {
u8 tag [[hidden]];
$ = addressof(this);
if (tag == 0x0E) {
ElementalStreamIDDescriptor es_id;
} else {
UnknownDescriptor unknown;
}
} [[inline]];
struct InitialObjectDescriptor : Descriptor {
if (tag != 0x10) {
std::print("esds child was not an ES_Desc.");
}
InitialObjectDescriptorInitialBits initial_data;
if (initial_data.url_flag) {
u8 url_length;
char url[url_length];
} else {
u8 od_profile_level_indication;
u8 scene_profile_level_indication;
u8 audio_profile_level_indication;
u8 visual_profile_level_indication;
u8 graphics_profile_level_indication;
}
ObjectDescriptorSelector children[while (contents_size(addressof(initial_data), instance_size) > 2)];
$ += contents_size(addressof(initial_data), instance_size);
};
// moov -> iods -> ES_ID
struct ElementalStreamIDDescriptor : Descriptor {
u32 track_id;
$ += contents_size(addressof(track_id), instance_size);
};
// moov -> trak
using TrackHeaderBox;
using TrackReferenceBox;
using EditBox;
using MediaBox;
struct TrackChildBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "tkhd") {
TrackHeaderBox tkhd;
} else if (box_header.box_type == "meta") {
MetaBox meta;
} else if (box_header.box_type == "tref") {
TrackReferenceBox tref;
} else if (box_header.box_type == "edts") {
EditBox edts;
} else if (box_header.box_type == "mdia") {
MediaBox mdia;
} else if (box_header.box_type == "udta") {
UserDataBox udta;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct TrackBox : Box {
TrackChildBoxSelector children[while(contents_size(addressof(this), box_size) > 0)];
};
// moov -> trak -> tref
struct TrackReferenceTypeBox : Box {
u32 track_ids[contents_size(addressof(this), box_size) / sizeof(u32)];
$ += contents_size(addressof(this), box_size);
};
struct TrackReferenceTypeBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
TrackReferenceTypeBox child [[name(box_header.box_type)]];
}
} [[inline]];
struct TrackReferenceBox : Box {
TrackReferenceTypeBoxSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
};
// moov -> trak -> tkhd
struct TrackHeaderBox : FullBox {
if (version < 2) {
if (version == 1) {
datetime<u64> creation_time;
datetime<u64> modification_time;
u32 track_id;
padding[sizeof(u32)];
u64 duration;
} else {
datetime<u32> creation_time;
datetime<u32> modification_time;
u32 track_id;
padding[sizeof(u32)];
u32 duration;
}
padding[sizeof(u32) * 2];
s16 layer;
u16 alternate_group;
fixed_s16 volume;
padding[sizeof(u16)];
Matrix matrix;
fixed_u32 width;
fixed_u32 height;
}
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> edts
using EditListBox;
struct EditBox : Box {
EditListBox edits[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> edts -> elst
struct EditListEntry<DurationT, TimeT> {
DurationT segment_duration;
TimeT media_time;
s16 media_rate_integer;
s16 media_rate_fraction;
};
struct EditListBox : FullBox {
if (version < 2) {
u32 entry_count;
if (version == 1) {
EditListEntry<u64, s64> entries[entry_count];
} else {
EditListEntry<u32, s32> entries[entry_count];
}
}
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia
using MediaHeaderBox;
using MediaInformationBox;
struct MediaChildBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "mdhd") {
MediaHeaderBox mdhd;
} else if (box_header.box_type == "hdlr") {
HandlerBox hdlr;
} else if (box_header.box_type == "minf") {
MediaInformationBox minf;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct MediaBox : Box {
MediaChildBoxSelector children[while (contents_size(addressof(this), box_size) > 0)];
};
// moov -> trak -> mdia -> mdhd
bitfield ISO639LanguageCode {
// Reversed
pad : 1;
a : 5;
b : 5;
c : 5;
} [[sealed,format("format_iso639"),left_to_right]];
fn format_iso639(ref auto iso639) {
if (iso639.pad != 0) {
return "invalid";
}
const u8 base = 0x60;
return std::format("\"{:c}{:c}{:c}\"", base + iso639.a, base + iso639.b, base + iso639.c);
};
struct MediaHeaderBox : FullBox {
if (version < 2) {
if (version == 1) {
datetime<u64> creation_time;
datetime<u64> modification_time;
u32 timescale;
u64 duration;
} else {
datetime<u32> creation_time;
datetime<u32> modification_time;
u32 timescale;
u32 duration;
}
ISO639LanguageCode language;
padding[sizeof(u16)];
}
$ += contents_size(addressof(this), box_size);
} [[format("format_mdhd")]];
fn format_mdhd(ref auto mdhd) {
return std::format("mdhd {{ duration = {}, language = {} }}",
format_duration(mdhd.duration, mdhd.timescale),
format_iso639(mdhd.language));
};
// moov -> trak -> mdia -> minf
using NullMediaHeaderBox;
using VideoMediaHeaderBox;
using SoundMediaHeaderBox;
using DataInformationBox;
using SampleTableBox;
struct MediaInformationChildBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "nmhd") {
NullMediaHeaderBox nmhd;
} else if (box_header.box_type == "vmhd") {
VideoMediaHeaderBox vmhd;
} else if (box_header.box_type == "smhd") {
SoundMediaHeaderBox smhd;
} else if (box_header.box_type == "hdlr") {
// This is non-standard.
HandlerBox hdlr;
} else if (box_header.box_type == "dinf") {
DataInformationBox dinf;
} else if (box_header.box_type == "stbl") {
SampleTableBox stbl;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct MediaInformationBox : Box {
MediaInformationChildBoxSelector children[while(contents_size(addressof(this), box_size) > 0)];
};
// moov -> trak -> mdia -> minf -> nmhd
struct NullMediaHeaderBox : FullBox {
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> vmhd
struct VideoMediaHeaderBox : FullBox {
if (version == 0) {
u16 graphicsmode;
u16 opcolor[3];
}
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> dinf
using DataReferenceBox;
struct DataInformationChildBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "dref") {
DataReferenceBox dref;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct DataInformationBox : Box {
DataInformationChildBoxSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
};
// moov -> trak -> mdia -> minf -> smhd
struct SoundMediaHeaderBox : FullBox {
if (version == 0) {
fixed_s16 balance;
padding[sizeof(u16)];
}
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> dinf -> dref
using DataEntryUrlBox;
using DataEntryUrnBox;
struct DataEntryBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "url ") {
DataEntryUrlBox url;
} else if (box_header.box_type == "urn ") {
DataEntryUrnBox urn;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct DataReferenceBox : FullBox {
if (version == 0) {
u32 entry_count;
DataEntryBoxSelector children[entry_count];
}
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> dinf -> dref -> url/urn
struct DataEntryUrlBox : FullBox {
if (version == 0 && flags == 0) {
char location[];
}
$ += contents_size(addressof(this), box_size);
};
struct DataEntryUrnBox : FullBox {
if (version == 0 && flags == 0) {
char name[];
char location[];
}
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl
using SampleDescriptionBox;
using TimeToSampleBox;
using CompositionOffsetBox;
using SyncSampleBox;
using SampleToChunkBox;
using SampleSizeBox;
using CompactSampleSizeBox;
using ChunkOffsetBox;
using ChunkLargeOffsetBox;
using SampleGroupDescriptionBox;
struct SampleTableChildBox {
type::Size32 size [[hidden]];
char type[4] [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), size) <= std::mem::size()) {
if (type == "stsd") {
SampleDescriptionBox stsd;
} else if (type == "stts") {
TimeToSampleBox stts;
} else if (type == "ctts") {
CompositionOffsetBox ctts;
} else if (type == "stss") {
SyncSampleBox stss;
} else if (type == "stsc") {
SampleToChunkBox stsc;
} else if (type == "stsz") {
SampleSizeBox stsz;
} else if (type == "stz2") {
CompactSampleSizeBox stz2;
} else if (type == "stco") {
ChunkOffsetBox stco;
} else if (type == "co64") {
ChunkLargeOffsetBox co64;
} else if (type == "sgpd") {
SampleGroupDescriptionBox sgpd;
} else {
UnknownBox unknown [[name(type)]];
}
}
} [[inline]];
struct SampleTableBox : Box {
SampleTableChildBox children[while(contents_size(addressof(this), box_size) > 0)];
};
// moov -> trak -> mdia -> minf -> stbl -> stsd
using VisualSampleEntry;
using AudioSampleEntry;
using UnknownSampleEntry;
struct SampleEntrySelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (current_handler == "vide") {
VisualSampleEntry visual [[name(box_header.box_type)]];
} else if (current_handler == "soun") {
AudioSampleEntry audio [[name(box_header.box_type)]];
} else {
UnknownSampleEntry unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct SampleDescriptionBox : FullBox {
u32 entry_count;
SampleEntrySelector children[entry_count];
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> *
struct SampleEntry : Box {
padding[sizeof(u8) * 6];
u16 data_reference_index;
};
using ElementaryStreamDescriptionBox;
struct UnknownSampleEntryChildSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "esds") {
ElementaryStreamDescriptionBox esds;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct UnknownSampleEntry : SampleEntry {
if (appears_to_contain_boxes($, contents_size(addressof(this), box_size))) {
UnknownSampleEntryChildSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
}
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> (visual)
enum VisualSampleDepth : u16 {
ColourNoAlpha = 0x0018,
};
using VisualSampleEntryChildSelector;
struct VisualSampleEntry : SampleEntry {
padding[sizeof(u16) + sizeof(u16) + (sizeof(u32) * 3)];
u16 width;
u16 height;
fixed_u32 horizresolution;
fixed_u32 vertresolution;
padding[sizeof(u32)];
u16 frame_count_per_sample;
u8 compressorname_size [[hidden]];
char compressorname[compressorname_size];
$ = addressof(compressorname_size) + 32;
VisualSampleDepth depth;
padding[sizeof(s16)];
VisualSampleEntryChildSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
$ += contents_size(addressof(this), box_size);
};
bitfield CodingConstraintsBitField {
all_ref_pics_intra : 1;
intra_pred_used : 1;
max_ref_per_pic : 4;
padding : 2;
} [[inline,left_to_right]];
struct CodingConstraintsBox : FullBox {
CodingConstraintsBitField fields;
padding[sizeof(u24)];
$ += contents_size(addressof(this), box_size);
};
using AVCConfigurationBox;
using PixelAspectRatioBox;
using BitRateBox;
using MasteringDisplayColourVolumeBox;
using FieldHandlingBox;
struct VisualSampleEntryChildSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "avcC") {
AVCConfigurationBox avcC;
} else if (box_header.box_type == "av1C") {
AV1CodecConfigurationBox av1C;
} else if (box_header.box_type == "colr") {
ColourInformationBox colr;
} else if (box_header.box_type == "pasp") {
PixelAspectRatioBox pasp;
} else if (box_header.box_type == "btrt") {
BitRateBox btrt;
} else if (box_header.box_type == "mdcv") {
MasteringDisplayColourVolumeBox mdcv;
} else if (box_header.box_type == "ccst") {
CodingConstraintsBox ccst;
} else if (box_header.box_type == "auxi") {
AuxiliaryTypeProperty auxi;
} else if (box_header.box_type == "esds") {
ElementaryStreamDescriptionBox esds;
} else if (box_header.box_type == "fiel") {
FieldHandlingBox fiel;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
// moov -> trak -> mdia -> minf -> stbl -> stsd -> avc1 -> avcC
bitfield LengthSize {
padding : 6;
value_minus_1 : 2;
} [[sealed,left_to_right,format("transform_length_size"),transform("transform_length_size")]];
fn transform_length_size(ref auto length_size) {
return length_size.value_minus_1 + 1;
};
bitfield PaddedBitDepth {
padding : 5;
value_minus_8 : 3;
} [[sealed,left_to_right,format("transform_padded_bit_depth"),transform("transform_padded_bit_depth")]];
fn transform_padded_bit_depth(ref auto padded_bit_depth) {
return padded_bit_depth.value_minus_8 + 8;
};
bitfield Padded2Bits {
padding : 6;
value : 2;
} [[sealed,left_to_right,format("transform_padded_value"),transform("transform_padded_value")]];
bitfield Padded5Bits {
padding : 3;
value : 5;
} [[sealed,left_to_right,format("transform_padded_value"),transform("transform_padded_value")]];
fn transform_padded_value(ref auto padded_value) {
return padded_value.value;
};
struct ParameterSet {
u16 length;
u8 data[length] [[sealed]];
};
struct AVCConfigurationBox : Box {
u8 configuration_version;
u8 profile;
u8 profile_compatibility;
u8 level_indication;
LengthSize length_size;
Padded5Bits sequence_parameter_sets_count;
ParameterSet sequence_parameter_sets[sequence_parameter_sets_count];
u8 picture_parameter_sets_count;
ParameterSet picture_parameter_sets[picture_parameter_sets_count];
if ((profile == 100 || profile == 110 || profile == 144) && contents_size(addressof(this), box_size) > 0) {
Padded2Bits chroma_format;
PaddedBitDepth bit_depth_luma;
PaddedBitDepth bit_depth_chroma;
}
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> av01 -> av1C
bitfield AV1CodecMarkerAndVersion {
marker : 1;
version : 7;
} [[inline,left_to_right]];
bitfield AV1CodecProfileAndLevel {
seq_profile : 3;
seq_level_idx_0 : 5;
} [[inline,left_to_right]];
bitfield AV1CodecTierAndColorInfo {
seq_tier_0 : 1;
high_bitdepth : 1;
twelve_bit : 1;
monochrome : 1;
chroma_subsampling_x : 1;
chroma_subsampling_y : 1;
chroma_sample_position: 2;
} [[inline,left_to_right]];
bitfield AV1CodecPresentationDelay {
padding : 3;
initial_presentation_delay_present : 1;
initial_presentation_delay_minus_1 : 4;
} [[inline,left_to_right]];
struct AV1CodecConfigurationBox : Box {
// FIXME: Each of these has its fields' orders reversed.
// I can't get it to put marker before version while
// keeping them both equal to 1.
AV1CodecMarkerAndVersion marker_and_version;
AV1CodecProfileAndLevel profile_and_level;
AV1CodecTierAndColorInfo tier_and_color_info;
AV1CodecPresentationDelay presentation_delay;
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> (audio)
struct AudioSampleEntryChildSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "esds") {
ElementaryStreamDescriptionBox esds;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct AudioSampleEntry : SampleEntry {
u16 entry_version; // reserved = 0 in V0
padding[sizeof(u16) * 3];
u16 channel_count;
u16 sample_size;
u16 pre_defined;
padding[sizeof(u16)];
fixed_u32 sample_rate;
AudioSampleEntryChildSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> (visual) -> ispe
struct ImageSpatialExtentsProperty : FullBox {
if (version == 0) {
u32 image_width;
u32 image_height;
}
$ += contents_size(addressof(this), box_size);
} [[format("format_ispe")]];
fn format_ispe(ref auto ispe) {
if (ispe.version == 0) {
return std::format("ispe ({}x{})", ispe.image_width, ispe.image_height);
}
return "ispe (unknown version)";
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> (visual) -> pixi
struct PixelInformationBox : FullBox {
if (version == 0) {
u8 channel_count;
u8 bits_per_channel[channel_count];
}
$ += contents_size(addressof(this), box_size);
} [[format("format_pixi")]];
fn format_pixi(ref auto pixi) {
if (pixi.version == 0) {
str result = "pixi (";
for (u8 i = 0, i < pixi.channel_count, i += 1) {
result += std::format("{}bit, ", pixi.bits_per_channel[i]);
}
return string_trim_end(result, 2) + ")";
}
return "pixi (unknown version)";
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> (visual) -> colr
bitfield ColourFullRangeFlag {
full_range_flag : 1;
} [[inline]];
struct ColourInformationBox : Box {
char colour_type[4];
if (colour_type == "nclx") {
u16 colour_primaries;
u16 transfer_characteristics;
u16 matrix_coefficients;
ColourFullRangeFlag full_range_flag;
} else if (colour_type == "rICC" || colour_type == "prof") {
u8 icc_profile_data[contents_size(addressof(this), box_size)];
}
$ += contents_size(addressof(this), box_size);
} [[format("format_colr")]];
fn format_colr(ref auto colr) {
return std::format("colr ({})", colr.colour_type);
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> (visual) -> mdcv
using ChromaCoordinate = u16 [[format("format_hack"),transform("transform_chroma_coordinate")]];
fn transform_chroma_coordinate(u16 coordinate) {
return coordinate / 50000.0f;
};
fn format_hack(ref auto coordinate) {
return std::format("{}", coordinate);
};
using LumaValue = u32 [[format("format_hack"),transform("transform_luma_value")]];
fn transform_luma_value(u32 coordinate) {
return coordinate / 10000.0f;
};
struct ColorCoordinates {
ChromaCoordinate x;
ChromaCoordinate y;
} [[format("format_color_coordinates")]];
fn format_color_coordinates(ref auto coordinates) {
return std::format("{{ x = {}, y = {} }}", coordinates.x, coordinates.y);
};
struct MasteringDisplayColourVolumeBox : Box {
ColorCoordinates green;
ColorCoordinates blue;
ColorCoordinates red;
ColorCoordinates white_point;
LumaValue max_luminance;
LumaValue min_luminance;
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> (visual) -> pasp
struct PixelAspectRatioBox : Box {
u32 horizontal_spacing;
u32 vertical_spacing;
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> * -> btrt
struct BitRateBox : Box {
u32 decoding_buffer_size;
u32 max_bitrate;
u32 avg_bitrate;
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> * -> auxi
struct AuxiliaryTypeProperty : FullBox {
char type[];
if (contents_size(addressof(this), box_size) > 0) {
char subtype[];
}
$ += contents_size(addressof(this), box_size);
} [[format("format_auxi")]];
fn format_auxi(ref auto auxi) {
return std::format("{} ({})", auxi.box_type, string_trim_end(auxi.type, 1));
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> * -> esds
using ElementaryStreamDescriptor;
struct ElementaryStreamDescriptionBox : FullBox {
ElementaryStreamDescriptor es_desc;
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> * -> esds -> ES_Descriptor
// ISO IEC 14496-1 MPEG-4 System Standard
bitfield ElementaryStreamDescriptorFlags {
depends_on_es : 1;
has_url : 1;
has_ocr_es : 1;
stream_priority : 5;
} [[inline,left_to_right]];
using DecoderConfigDescriptor;
using SyncLayerConfigDescriptor;
struct ElementaryStreamDescriptorChildSelector {
u8 tag [[hidden]];
$ = addressof(this);
if (tag == 0x04) {
DecoderConfigDescriptor dc_desc;
} else if (tag == 0x06) {
SyncLayerConfigDescriptor sl_config;
} else {
UnknownDescriptor unknown;
}
} [[inline]];
struct ElementaryStreamDescriptor : Descriptor {
if (tag != 0x03) {
std::print("esds child was not an ES_Desc.");
}
u16 es_id;
ElementaryStreamDescriptorFlags flags;
if (flags.depends_on_es) {
u16 depends_on_es_id;
}
if (flags.has_url) {
u8 url_length;
char url[url_length];
}
if (flags.has_ocr_es) {
u16 ocr_es_id;
}
ElementaryStreamDescriptorChildSelector children[while (contents_size(addressof(es_id), instance_size) > 2)];
$ += contents_size(addressof(es_id), instance_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> * -> esds -> ES_Descriptor -> DecoderConfigDescriptor
bitfield DecoderConfigDescriptorFlags {
stream_type : 6;
up_stream : 1;
padding : 1;
} [[inline,left_to_right]];
// https://mp4ra.org/#/object_types
enum ObjectTypeIndication : u8 {
Forbidden = 0x00,
Systems = 0x01,
MPEG_4_Visual = 0x20,
AVC = 0x21,
MP4A_LATM = 0x40,
AAC_Main = 0x66,
AAC_LC = 0x67,
MPEG_2_Audio = 0x69, // MP3
MPEG_1_Audio = 0x6B, // MP3
};
using DecoderSpecificInfo;
using AudioSpecificConfig;
using ProfileLevelIndicationIndexDescriptor;
struct DecoderConfigDescriptorChildSelector<auto type_indication> {
u8 tag [[hidden]];
$ = addressof(this);
if (tag == 0x05) {
if (type_indication == ObjectTypeIndication::MP4A_LATM) {
AudioSpecificConfig dec_specific;
} else {
DecoderSpecificInfo dec_specific;
}
} else if (tag == 0x14) {
ProfileLevelIndicationIndexDescriptor profile_level_desc;
} else {
UnknownDescriptor unknown;
}
} [[inline]];
struct DecoderConfigDescriptor : Descriptor {
ObjectTypeIndication object_type_indication;
DecoderConfigDescriptorFlags flags;
u24 buffer_size_db;
u32 max_bit_rate;
u32 average_bit_rate;
DecoderConfigDescriptorChildSelector<object_type_indication> children[while (contents_size(addressof(object_type_indication), instance_size) > 2)];
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> * -> esds -> ES_Descriptor -> DecoderConfigDescriptor -> DecoderSpecificInfo
struct DecoderSpecificInfo : Descriptor {
u8 data[contents_size($, instance_size)] [[sealed]];
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> * -> esds -> ES_Descriptor -> DecoderConfigDescriptor -> AudioSpecificConfig
bitfield AudioSpecificConfigBitfield {
// This needs to read from the big end first, [[left_to_right]] doesn't work.
audio_object_type : 5;
if (audio_object_type == 31) {
audio_object_type_ext : 6;
}
sampling_frequency_index : 4;
if (sampling_frequency_index == 0xf) {
sampling_frequency : 24;
}
// TODO: Match based on audio_object_type, spec has plenty of options.
};
struct AudioSpecificConfig : Descriptor {
AudioSpecificConfigBitfield object_type;
$ += contents_size(addressof(object_type), instance_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> * -> esds -> ES_Descriptor -> DecoderConfigDescriptor -> ProfileLevelIndicationIndexDescriptor
struct ProfileLevelIndicationIndexDescriptor : Descriptor {
u8 index;
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> * -> esds -> ES_Desc -> SLConfigDescriptor
bitfield SyncLayerConfigDescriptorFlags {
use_access_unit_start : 1;
use_access_unit_end : 1;
use_random_access_point : 1;
has_random_access_units_only : 1;
use_padding : 1;
use_timestamps : 1;
use_idle : 1;
duration_present : 1;
} [[inline,left_to_right]];
bitfield SyncLayerConfigDescriptorLengths {
degradation_priority_length : 4;
au_seq_num_length : 5;
packet_seq_num_length : 5;
padding : 2;
} [[inline,left_to_right]];
struct SyncLayerConfigDescriptor : Descriptor {
u8 predefined;
if (predefined == 0) {
SyncLayerConfigDescriptorFlags flags;
u32 timestamp_resolution;
u32 ocr_resolution;
u8 timestamp_length;
u8 ocr_length;
u8 au_length;
u8 instant_bitrate_length;
SyncLayerConfigDescriptorLengths other_lengths;
if (flags.duration_present) {
u32 time_scale;
u16 access_unit_duration;
u16 composition_unit_duration;
}
if (use_timestamps) {
// start_decoding_time_stamp : timestamp_length;
// start_composition_time_stamp : timestamp_length;
padding[((timestamp_length * 2) + 7) / 8];
}
}
};
// moov -> trak -> mdia -> minf -> stbl -> stsd -> (visual) -> fiel
struct FieldHandlingBox : Box {
u8 scan_count;
u8 scan_order;
};
// moov -> trak -> mdia -> minf -> stbl -> stts
struct TimeToSampleEntry {
u32 sample_count;
u32 sample_delta;
} [[format("format_stts_entry")]];
fn format_stts_entry(ref auto stts_entry) {
return std::format("count = {}, delta = {}", stts_entry.sample_count, stts_entry.sample_delta);
};
struct TimeToSampleBox : FullBox {
u32 entry_count;
TimeToSampleEntry entries[entry_count] [[format("count_samples")]];
$ += contents_size(addressof(this), box_size);
};
fn count_samples(ref auto entries) {
u128 count = 0;
for (u32 i = 0, i < std::core::member_count(entries), i += 1) {
count += entries[i].sample_count;
}
return std::format("{} samples total", count);
};
// moov -> trak -> mdia -> minf -> stbl -> ctts
struct CompositionOffsetEntry {
u32 sample_count;
u32 sample_offset;
} [[format("format_ctts_entry")]];
fn format_ctts_entry(ref auto stts_entry) {
return std::format("count = {}, offset = {}", stts_entry.sample_count, stts_entry.sample_offset);
};
struct CompositionOffsetBox : FullBox {
u32 entry_count;
CompositionOffsetEntry entries[entry_count] [[format("count_samples")]];
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stss
struct SyncSampleBox : FullBox {
u32 entry_count;
u32 sample_numbers[entry_count];
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stsc
struct SampleToChunkBoxEntry {
u32 first_chunk;
u32 samples_per_chunk;
u32 sample_description_index;
} [[format("format_stsc_entry")]];
fn format_stsc_entry(ref auto stsc_entry) {
return std::format("first_chunk = {}, samples_per_chunk = {}, sample_description_index = {}",
stsc_entry.first_chunk, stsc_entry.samples_per_chunk, stsc_entry.sample_description_index);
};
struct SampleToChunkBox : FullBox {
u32 entry_count;
SampleToChunkBoxEntry entries[entry_count];
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stsz/stz2
struct SampleSizeBox : FullBox {
u32 sample_size;
u32 sample_count;
if (sample_size == 0) {
u32 entry_size[sample_count];
}
$ += contents_size(addressof(this), box_size);
};
struct CompactSampleSizeBox : FullBox {
padding[sizeof(u24)];
u8 field_size;
u32 sample_count;
if (field_size == 4) {
type::Nibbles entries[(sample_count + 1) / 2];
} else if (field_size == 8) {
u8 entries[sample_count];
} else if (field_size == 16) {
u16 entries[sample_count];
}
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl -> stco/co64
struct DataPointer32 {
u8* pointer : u32;
} [[inline]];
struct DataPointer64 {
u8* pointer : u64;
} [[inline]];
struct ChunkOffsetBox : FullBox {
u32 entry_count;
DataPointer32 chunk_offset[entry_count];
$ += contents_size(addressof(this), box_size);
};
struct ChunkLargeOffsetBox : FullBox {
u32 entry_count;
DataPointer64 chunk_offset[entry_count];
$ += contents_size(addressof(this), box_size);
};
// moov -> trak -> mdia -> minf -> stbl -> sgpd -> *
const u32 SGPD_NO_LENGTH = 0xFFFFFFFF;
struct SampleGroupDescriptionEntry<auto sgpd_default_length> {
u32 length = sgpd_default_length;
if (length == 0 && length != SGPD_NO_LENGTH) {
u32 description_length;
length = description_length;
}
} [[inline]];
struct UnknownSampleGroupDescriptionEntry<auto sgpd_default_length> {
SampleGroupDescriptionEntry<sgpd_default_length> inherited;
if (inherited.length != SGPD_NO_LENGTH) {
$ += contents_size($, inherited.length);
}
};
// moov -> trak -> mdia -> minf -> stbl -> sgpd -> (roll|prol)
struct RollEntry<auto sgpd_default_length> {
SampleGroupDescriptionEntry<sgpd_default_length> inherited;
u16 roll_distance;
} [[format("format_roll")]];
fn format_roll(ref auto roll) {
return std::format("roll_distance = {}", roll.roll_distance);
};
// moov -> trak -> mdia -> minf -> stbl -> sgpd
struct SampleGroupDescriptionBox : FullBox {
char grouping_type[4];
if (version == 1) {
u32 default_length;
}
if (version >= 2) {
u32 default_sample_description_index;
}
u32 entry_count;
u32 the_default_length = version == 1 ? default_length : (contents_size(addressof(this), box_size) / entry_count);
if (grouping_type == "roll" || grouping_type == "prol") {
RollEntry<the_default_length> entries[entry_count];
} else {
UnknownSampleGroupDescriptionEntry<the_default_length> entries[entry_count];
}
$ += contents_size(addressof(this), box_size);
};
// moov -> udta
struct UserDataChildBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "meta") {
MetaBox meta;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct UserDataBox : Box {
UserDataChildBoxSelector children[while (contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
$ += contents_size(addressof(this), box_size);
};
// sidx
bitfield SegmentReferenceTypeAndSize {
reference_type : 1;
referenced_size : 31;
} [[inline]];
bitfield SegmentReferenceSAP {
starts_with_sap : 1;
sap_type : 3;
sap_delta_time : 28;
} [[inline]];
struct SegmentReference {
SegmentReferenceTypeAndSize reference_type_and_size;
u32 subsegment_duration;
SegmentReferenceSAP sap;
};
struct SegmentIndexBox : FullBox {
u32 reference_id;
u32 timescale;
if (version == 0) {
u32 earliest_presentation_time;
u32 first_offset;
} else {
u64 earliest_presentation_time;
u64 first_offset;
}
padding[sizeof(u16)];
u16 reference_count;
SegmentReference references[reference_count];
};
// moof
using MovieFragmentHeaderBox;
using TrackFragmentBox;
struct MovieFragmentChildBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "mfhd") {
MovieFragmentHeaderBox mfhd;
} else if (box_header.box_type == "traf") {
TrackFragmentBox traf;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct MovieFragmentBox : Box {
MovieFragmentChildBoxSelector children[while(contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
};
// moof -> mfhd
struct MovieFragmentHeaderBox : FullBox {
u32 sequence_number;
};
// moof -> traf
using TrackFragmentHeaderBox;
using TrackRunBox;
using TrackFragmentBaseMediaDecodeTimeBox;
struct TrackFragmentChildBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "tfhd") {
TrackFragmentHeaderBox tfhd;
} else if (box_header.box_type == "trun") {
TrackRunBox trun;
} else if (box_header.box_type == "tfdt") {
TrackFragmentBaseMediaDecodeTimeBox tfdt;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
}
} [[inline]];
struct TrackFragmentBox : Box {
TrackFragmentChildBoxSelector children[while(contents_size(addressof(this), box_size) > MIN_BOX_SIZE)];
};
// moof -> traf -> tfhd
bitfield TrackFragmentHeaderFlags {
base_data_offset_present : 1;
sample_description_index_present : 1;
padding : 1;
default_sample_duration_present : 1;
default_sample_size_present : 1;
default_sample_flags_present : 1;
padding : 10;
duration_is_empty : 1;
default_base_is_moof : 1;
padding : 6;
} [[right_to_left]];
struct TrackFragmentHeaderBox : Box {
// FullBox fields
u8 version;
TrackFragmentHeaderFlags flags;
// traf fields
if (version == 0) {
u32 track_id;
if (flags.base_data_offset_present) {
u64 base_data_offset;
}
if (flags.sample_description_index_present) {
u32 sample_description_index;
}
if (flags.default_sample_duration_present) {
u32 default_sample_duration;
}
if (flags.default_sample_size_present) {
u32 default_sample_size;
}
if (flags.default_sample_flags_present) {
u32 default_sample_flags;
}
}
$ += contents_size(addressof(this), box_size);
};
// moof -> traf -> trun
bitfield TrackRunFlags {
data_offset_present : 1;
padding : 2;
first_sample_flags_present : 1;
padding : 4;
sample_duration_present : 1;
sample_size_present : 1;
sample_flags_present : 1;
sample_composition_time_offset_present : 1;
padding : 12;
} [[right_to_left]];
struct TrackRunSample<auto trun_version, auto trun_flags>
{
if (trun_flags.sample_duration_present) {
u32 sample_duration;
}
if (trun_flags.sample_size_present) {
u32 sample_size;
}
if (trun_flags.sample_flags_present) {
FragmentSampleFlags sample_flags;
}
if (trun_flags.sample_composition_time_offset_present) {
if (trun_version == 0) {
u32 sample_composition_time_offset;
} else {
s32 sample_composition_time_offset;
}
}
};
struct TrackRunBox : Box {
// FullBox
u8 version;
TrackRunFlags flags;
// trun
u32 sample_count;
if (flags.data_offset_present) {
s32 data_offset;
}
if (flags.first_sample_flags_present) {
FragmentSampleFlags first_sample_flags;
}
TrackRunSample<version, flags> samples[sample_count];
$ += contents_size(addressof(this), box_size);
};
// moof -> traf -> tfdt
struct TrackFragmentBaseMediaDecodeTimeBox : FullBox {
if (version < 2) {
if (version == 1) {
u64 base_media_decode_time;
} else {
u32 base_media_decode_time;
}
}
$ += contents_size(addressof(this), box_size);
};
// mdat
struct MediaDataBox : Box {
u8 data[contents_size(addressof(this), box_size)] [[sealed]];
};
// top level
struct TopLevelBoxSelector {
Box box_header [[hidden]];
$ = addressof(this);
if ($ + contents_size(addressof(this), box_header.box_size) <= std::mem::size()) {
if (box_header.box_type == "ftyp") {
FileTypeBox ftyp;
} else if (box_header.box_type == "meta") {
MetaBox meta;
} else if (box_header.box_type == "moov") {
MovieBox moov;
} else if (box_header.box_type == "sidx") {
SegmentIndexBox sidx;
} else if (box_header.box_type == "moof") {
MovieFragmentBox moof;
} else if (box_header.box_type == "mdat") {
MediaDataBox mdat;
} else {
UnknownBox unknown [[name(box_header.box_type)]];
}
} else {
$ = std::mem::size();
}
} [[inline]];
// top level
TopLevelBoxSelector boxes[while(std::mem::size() - $ > MIN_BOX_SIZE)] @ 0x00 [[format("format_box_array")]];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment