+}
+
+var TkhdAtom = function(buffer, offset) {
+ return Atom.prototype.constructor.call(this, buffer, offset);
+}
+
+TkhdAtom.prototype = Object.create(Atom.prototype);
+
+TkhdAtom.prototype.setDefaults = function() {
+ Atom.prototype.setDefaults.call(this);
+
+ this.version = 0;
+ this.flags = 0;
+ this.creationTime = 0;
+ this.modificationTime = 0;
+ this.trackID = 0;
+ this.duration = 0;
+ this.layer = 0;
+ this.alternateGroup = 0;
+ this.volume = 0.0;
+ this.trackMatrix = [];
+ this.width = 0;
+ this.height = 0;
+}
+
+TkhdAtom.prototype.parse = function(buffer, offset)
+{
+ if (!Atom.prototype.parse.call(this, buffer, offset))
+ return false;
+
+ offset += this.is64bit ? 16 : 8;
+
+ var headerOffset = 0;
+ var view = new DataView(buffer, offset);
+
+ this.version = view.getUint8(headerOffset);
+ headerOffset += 1;
+
+ // 'flags' is a 3-byte field, so retrieve from one extra byte and concatenate
+ this.flags = (view.getUint8(headerOffset) << 8) + view.getUint16(headerOffset + 1);
+ headerOffset += 3;
+
+ this.creationTime = new Date(view.getUint32(headerOffset)*1000 + Date.UTC(1904, 0, 1));
+ headerOffset += 4;
+
+ this.modificationTime = new Date(view.getUint32(headerOffset)*1000 + Date.UTC(1904, 0, 1));
+ headerOffset += 4;
+
+ this.trackID = view.getUint32(headerOffset);
+ headerOffset += 4;
+
+ // Reserved
+ // A 32-bit integer that is reserved for use by Apple. Set this field to 0.
+ headerOffset += 4;
+
+ this.duration = view.getUint32(headerOffset);
+ headerOffset += 4;
+
+ // Reserved
+ // An 8-byte value that is reserved for use by Apple. Set this field to 0.
+ headerOffset += 8;
+
+ this.layer = view.getUint16(headerOffset);
+ headerOffset += 2;
+
+ this.alternateGroup = view.getUint16(headerOffset);
+ headerOffset += 2;
+
+ this.volume = view.getUint16(headerOffset) / (1 << 8);
+ headerOffset += 2;
+
+ // Reserved
+ // A 16-bit integer that is reserved for use by Apple. Set this field to 0.
+ headerOffset += 2;
+
+ this.trackMatrix = new Array(3);
+ // a, b, u:
+ this.trackMatrix[0] = new Array(3);
+ this.trackMatrix[0][0] = view.getUint32(headerOffset) / (1 << 16);
+ headerOffset += 4;
+ this.trackMatrix[0][1] = view.getUint32(headerOffset) / (1 << 16);
+ headerOffset += 4;
+ this.trackMatrix[0][2] = view.getUint32(headerOffset) / (1 << 30);
+ headerOffset += 4;
+
+ // c, d, v:
+ this.trackMatrix[1] = new Array(3);
+ this.trackMatrix[1][0] = view.getUint32(headerOffset) / (1 << 16);
+ headerOffset += 4;
+ this.trackMatrix[1][1] = view.getUint32(headerOffset) / (1 << 16);
+ headerOffset += 4;
+ this.trackMatrix[1][2] = view.getUint32(headerOffset) / (1 << 30);
+ headerOffset += 4;
+
+ // x, y, w:
+ this.trackMatrix[2] = new Array(3);
+ this.trackMatrix[2][0] = view.getUint32(headerOffset) / (1 << 16);
+ headerOffset += 4;
+ this.trackMatrix[2][1] = view.getUint32(headerOffset) / (1 << 16);
+ headerOffset += 4;
+ this.trackMatrix[2][2] = view.getUint32(headerOffset) / (1 << 30);
+ headerOffset += 4;
+
+ this.width = view.getUint32(headerOffset) / (1 << 16);
+ headerOffset += 4;
+
+ this.height = view.getUint32(headerOffset) / (1 << 16);
+ headerOffset += 4;
+}
+
+var MdhdAtom = function(buffer, offset) {
+ return Atom.prototype.constructor.call(this, buffer, offset);
+}
+
+MdhdAtom.prototype = Object.create(Atom.prototype);
+
+MdhdAtom.prototype.setDefaults = function() {
+ Atom.prototype.setDefaults.call(this);
+
+ this.version = 0;
+ this.flags = 0;
+ this.creationTime = 0;
+ this.modificationTime = 0;
+ this.timeScale = 0;
+ this.duration = 0;
+ this.language = 0;
+ this.quality = 0;
+}
+
+MdhdAtom.prototype.parse = function(buffer, offset)
+{
+ if (!Atom.prototype.parse.call(this, buffer, offset))
+ return false;
+
+ offset += this.is64bit ? 16 : 8;
+
+ var headerOffset = 0;
+ var view = new DataView(buffer, offset);
+
+ this.version = view.getUint8(headerOffset);
+ headerOffset += 1;
+
+ // 'flags' is a 3-byte field, so retrieve from one extra byte and concatenate
+ this.flags = (view.getUint8(headerOffset) << 8) + view.getUint16(headerOffset + 1);
+ headerOffset += 3;
+
+ this.creationTime = new Date(view.getUint32(headerOffset)*1000 + Date.UTC(1904, 0, 1));
+ headerOffset += 4;
+
+ this.modificationTime = new Date(view.getUint32(headerOffset)*1000 + Date.UTC(1904, 0, 1));
+ headerOffset += 4;
+
+ this.timeScale = view.getUint32(headerOffset);
+ headerOffset += 4;
+
+ this.duration = view.getUint32(headerOffset);
+ headerOffset += 4;
+
+ this.language = view.getUint16(headerOffset);
+ headerOffset += 2;
+
+ this.quality = view.getUint16(headerOffset);
+ headerOffset += 2;