+Atom.constructorMap['mehd'] = MovieExtendsHeaderBox.bind(null);
+
+
+class MovieFragmentHeaderBox extends FullBox {
+ constructor(parent) {
+ super(parent);
+ this.description = 'Movie Fragment Header Box';
+ this.sequenceNumber = 0;
+ };
+
+ parse(buffer, offset) {
+ var headerOffset = super.parse(buffer, offset);
+ var view = new DataView(buffer, offset);
+
+ this.sequenceNumber = view.getUint32(headerOffset);
+ headerOffset += 4;
+ };
+};
+
+Atom.constructorMap['mfhd'] = MovieFragmentHeaderBox.bind(null);
+
+class TrackFragmentHeaderBox extends FullBox {
+ constructor(parent) {
+ super(parent);
+ this.description = 'Track Fragment Header Box';
+ this.baseDataOffsetPresent = false;
+ this.sampleDescriptionIndexPresent = false;
+ this.defaultSampleDurationPresent = false;
+ this.defaultSampleSizePresent = false;
+ this.defaultSampleFlagsPresent = false;
+ this.durationIsEmpty = false;
+ this.defaultBaseIsMoof = false;
+ this.trackID = 0;
+ };
+
+ parse(buffer, offset) {
+ var headerOffset = super.parse(buffer, offset);
+
+ this.baseDataOffsetPresent = this.flags & 0x00001 ? true : false;
+ this.sampleDescriptionIndexPresent = this.flags & 0x00002 ? true : false;
+ this.defaultSampleDurationPresent = this.flags & 0x00008 ? true : false;
+ this.defaultSampleSizePresent = this.flags & 0x00010 ? true : false;
+ this.defaultSampleFlagsPresent = this.flags & 0x00020 ? true : false;
+ this.durationIsEmpty = this.flags & 0x10000 ? true : false;
+ this.defaultBaseIsMoof = this.flags & 0x20000 ? true : false;
+
+ var view = new DataView(buffer, offset);
+
+ this.trackID = view.getUint32(headerOffset);
+ headerOffset += 4;
+
+ if (this.baseDataOffsetPresent) {
+ var upper = view.getUint32(headerOffset);
+ var lower = view.getUint32(headerOffset + 4);
+ headerOffset += 8;
+
+ this.baseDataOffset = (upper << 32) + lower;
+ }
+
+ if (this.sampleDescriptionIndexPresent) {
+ this.sampleDescriptionIndex = view.getUint32(headerOffset);
+ headerOffset += 4;
+ }
+
+ if (this.defaultSampleDurationPresent) {
+ this.defaultSampleDuration = view.getUint32(headerOffset);
+ headerOffset += 4;
+ }
+
+ if (this.defaultSampleSizePresent) {
+ this.defaultSampleSize = view.getUint32(headerOffset);
+ headerOffset += 4;
+ }
+
+ if (this.defaultSampleFlagsPresent) {
+ this.defaultSampleFlags = view.getUint32(headerOffset);
+ headerOffset += 4;
+ }
+
+ return headerOffset;
+ };
+};
+
+Atom.constructorMap['tfhd'] = TrackFragmentHeaderBox.bind(null);
+
+class TrackFragmentRunBox extends FullBox {
+ constructor(parent) {
+ super(parent);
+ this.description = 'Track Fragment Run Box';
+ this.dataOffsetPresent = false;
+ this.firstSampleFlagsPresent = false;
+ this.sampleDurationPresent = false;
+ this.sampleSizePresent = false;
+ this.sampleFlagsPresent = false;
+ this.sampleCompositionTimeOffsetsPresent = false;
+ this.dataOffset;
+ this.samples = [];
+ this.duration = 0;
+ };
+
+ parse(buffer, offset) {
+ var headerOffset = super.parse(buffer, offset);
+ this.dataOffsetPresent = this.flags & 0x00001 ? true : false;
+ this.firstSampleFlagsPresent = this.flags & 0x00004 ? true : false;
+ this.sampleDurationPresent = this.flags & 0x00100 ? true : false;
+ this.sampleSizePresent = this.flags & 0x00200 ? true : false;
+ this.sampleFlagsPresent = this.flags & 0x00400 ? true : false;
+ this.sampleCompositionTimeOffsetsPresent = this.flags & 0x00800 ? true : false;
+
+ var view = new DataView(buffer, offset);
+
+ var sampleCount = view.getUint32(headerOffset);
+ headerOffset += 4;
+
+ if (this.dataOffsetPresent) {
+ this.dataOffset = view.getUint32(headerOffset);
+ headerOffset += 4;
+ }
+
+ if (this.firstSampleFlagsPresent) {
+ this.firstSampleFlags = view.getUint32(headerOffset);
+ headerOffset += 4;
+ }
+
+ for (var index = 0; index < sampleCount; ++index) {
+ var sample = {}
+ if (this.sampleDurationPresent) {
+ sample.sampleDuration = view.getUint32(headerOffset);
+ this.duration += sample.sampleDuration;
+ headerOffset += 4;
+ }
+
+ if (this.sampleSizePresent) {
+ sample.sampleSize = view.getUint32(headerOffset);
+ headerOffset += 4;
+ }
+
+ if (this.sampleFlagsPresent) {
+ var sampleFlags = view.getUint32(headerOffset);
+ this.sampleFlags = {
+ isLeading: (sampleFlags & 0x0030) >> 4,
+ sampleDependsOn: (sampleFlags & 0x00C0) >> 6,
+ sampleIsDependedOn: (sampleFlags & 0x0300) >> 8,
+ sampleHasRedundency: (sampleFlags & 0x0C00) >> 10,
+ samplePaddingValue: (sampleFlags & 0x7000) >> 12,
+ sampleIsNonSyncSample: (sampleFlags & 0x8000) >> 15,
+ sampleDegredationPriority: (sampleFlags & 0xFFFF0000) >> 16,
+ }
+ headerOffset += 4;
+ }
+
+ if (this.sampleCompositionTimeOffsetsPresent) {
+ sample.sampleCompositionTimeOffsets = !this.version ? view.getUint32(headerOffset) : view.getInt32(headerOffset);
+ headerOffset += 4;
+ }
+ this.samples.push(sample);
+ }
+
+ return headerOffset;
+ };
+};
+
+Atom.constructorMap['trun'] = TrackFragmentRunBox.bind(null);
+
+class TrackFragmentBaseMediaDecodeTimeBox extends FullBox {
+ constructor(parent) {
+ super(parent);
+ this.description = "Track Fragment Decode Time";
+ this.baseMediaDecodeTime = 0;
+ };
+
+ parse(buffer, offset) {
+ var headerOffset = super.parse(buffer, offset);
+ var view = new DataView(buffer, offset);
+
+ if (this.version === 1) {
+ var upper = view.getUint32(headerOffset);
+ var lower = view.getUint32(headerOffset + 4);
+ var sign = 1;
+ if (upper & (1 << 32)) {
+ sign = -1
+ upper = ~upper;
+ lower = ~lower + 1;
+ }
+
+ this.baseMediaDecodeTime = sign * ((upper << 32) + lower);
+ headerOffset += 8;
+ } else {
+ this.baseMediaDecodeTime = view.getUint32(headerOffset);
+ headerOffset += 4;
+ }
+
+ return headerOffset;
+ };
+};