codem-isoboxer
Advanced tools
Comparing version 0.2.10 to 0.3.0
@@ -1,5 +0,10 @@ | ||
## codem-isoboxer 0.2.10 (2016/12/022) ## | ||
## codem-isoboxer 0.3.0 (2016/12/23) ## | ||
* Updated `subs` parser to follow the spec more closely (@2bert, @TobbeEdgeware) | ||
* write support (@bbert) | ||
* encrypted boxes support (encv,enca,frma,pssh,schm,sdtp,tenc) (@nicosang) | ||
## codem-isoboxer 0.2.10 (2016/12/02) ## | ||
* Updated `subs` parser to follow the spec more closely (@bbert, @TobbeEdgeware) | ||
## codem-isoboxer 0.2.9 (2016/11/29) ## | ||
@@ -6,0 +11,0 @@ |
@@ -1,2 +0,2 @@ | ||
/*! codem-isoboxer v0.2.10 https://github.com/madebyhiro/codem-isoboxer/blob/master/LICENSE.txt */ | ||
/*! codem-isoboxer v0.3.0 https://github.com/madebyhiro/codem-isoboxer/blob/master/LICENSE.txt */ | ||
var ISOBoxer = {}; | ||
@@ -8,9 +8,30 @@ | ||
ISOBoxer.addBoxParser = function(type, parser) { | ||
ISOBoxer.addBoxProcessor = function(type, parser) { | ||
if (typeof type !== 'string' || typeof parser !== 'function') { | ||
return; | ||
} | ||
ISOBox.prototype._boxParsers[type] = parser; | ||
ISOBox.prototype._boxProcessors[type] = parser; | ||
}; | ||
ISOBoxer.createFile = function() { | ||
return new ISOFile(); | ||
}; | ||
// See ISOBoxer.append() for 'pos' parameter syntax | ||
ISOBoxer.createBox = function(type, parent, pos) { | ||
var newBox = ISOBox.create(type); | ||
if (parent) { | ||
parent.append(newBox, pos); | ||
} | ||
return newBox; | ||
}; | ||
// See ISOBoxer.append() for 'pos' parameter syntax | ||
ISOBoxer.createFullBox = function(type, parent, pos) { | ||
var newBox = ISOBoxer.createBox(type, parent, pos); | ||
newBox.version = 0; | ||
newBox.flags = 0; | ||
return newBox; | ||
}; | ||
ISOBoxer.Utils = {}; | ||
@@ -60,14 +81,97 @@ ISOBoxer.Utils.dataViewToString = function(dataView, encoding) { | ||
ISOBoxer.Utils.utf8ToByteArray = function(string) { | ||
// Only UTF-8 encoding is supported by TextEncoder | ||
var u, i; | ||
if (typeof TextEncoder !== 'undefined') { | ||
u = new TextEncoder().encode(string); | ||
} else { | ||
u = []; | ||
for (i = 0; i < string.length; ++i) { | ||
var c = string.charCodeAt(i); | ||
if (c < 0x80) { | ||
u.push(c); | ||
} else if (c < 0x800) { | ||
u.push(0xC0 | (c >> 6)); | ||
u.push(0x80 | (63 & c)); | ||
} else if (c < 0x10000) { | ||
u.push(0xE0 | (c >> 12)); | ||
u.push(0x80 | (63 & (c >> 6))); | ||
u.push(0x80 | (63 & c)); | ||
} else { | ||
u.push(0xF0 | (c >> 18)); | ||
u.push(0x80 | (63 & (c >> 12))); | ||
u.push(0x80 | (63 & (c >> 6))); | ||
u.push(0x80 | (63 & c)); | ||
} | ||
} | ||
} | ||
return u; | ||
}; | ||
// Method to append a box in the list of child boxes | ||
// The 'pos' parameter can be either: | ||
// - (number) a position index at which to insert the new box | ||
// - (string) the type of the box after which to insert the new box | ||
// - (object) the box after which to insert the new box | ||
ISOBoxer.Utils.appendBox = function(parent, box, pos) { | ||
box._offset = parent._cursor.offset; | ||
box._root = (parent._root ? parent._root : parent); | ||
box._raw = parent._raw; | ||
box._parent = parent; | ||
if (pos === -1) { | ||
// The new box is a sub-box of the parent but not added in boxes array, | ||
// for example when the new box is set as an entry (see dref and stsd for example) | ||
return; | ||
} | ||
if (pos === undefined || pos === null) { | ||
parent.boxes.push(box); | ||
return; | ||
} | ||
var index = -1, | ||
type; | ||
if (typeof pos === "number") { | ||
index = pos; | ||
} else { | ||
if (typeof pos === "string") { | ||
type = pos; | ||
} else if (typeof pos === "object" && pos.type) { | ||
type = pos.type; | ||
} else { | ||
parent.boxes.push(box); | ||
return; | ||
} | ||
for (var i = 0; i < parent.boxes.length; i++) { | ||
if (type === parent.boxes[i].type) { | ||
index = i + 1; | ||
break; | ||
} | ||
} | ||
} | ||
parent.boxes.splice(index, 0, box); | ||
}; | ||
if (typeof exports !== 'undefined') { | ||
exports.parseBuffer = ISOBoxer.parseBuffer; | ||
exports.addBoxParser = ISOBoxer.addBoxParser; | ||
exports.Utils = ISOBoxer.Utils; | ||
exports.parseBuffer = ISOBoxer.parseBuffer; | ||
exports.addBoxProcessor = ISOBoxer.addBoxProcessor; | ||
exports.createFile = ISOBoxer.createFile; | ||
exports.createBox = ISOBoxer.createBox; | ||
exports.createFullBox = ISOBoxer.createFullBox; | ||
exports.Utils = ISOBoxer.Utils; | ||
} | ||
ISOBoxer.Cursor = function(initialOffset) { | ||
this.offset = (typeof initialOffset == 'undefined' ? 0 : initialOffset); | ||
}; | ||
var ISOFile = function(arrayBuffer) { | ||
this._raw = new DataView(arrayBuffer); | ||
this._cursor = new ISOBoxer.Cursor(); | ||
this.boxes = []; | ||
if (arrayBuffer) { | ||
this._raw = new DataView(arrayBuffer); | ||
} | ||
}; | ||
@@ -107,2 +211,50 @@ | ||
}; | ||
ISOFile.prototype.write = function() { | ||
var length = 0, | ||
i; | ||
for (i = 0; i < this.boxes.length; i++) { | ||
length += this.boxes[i].getLength(false); | ||
} | ||
var bytes = new Uint8Array(length); | ||
this._rawo = new DataView(bytes.buffer); | ||
this.bytes = bytes; | ||
this._cursor.offset = 0; | ||
for (i = 0; i < this.boxes.length; i++) { | ||
this.boxes[i].write(); | ||
} | ||
return bytes.buffer; | ||
}; | ||
ISOFile.prototype.append = function(box, pos) { | ||
ISOBoxer.Utils.appendBox(this, box, pos); | ||
}; | ||
/*ISOFile.prototype.create = function(type, parent, previousType) { | ||
var newBox = ISOBox.create(type, parent), | ||
inserted = false; | ||
if (previousType) { | ||
for (var i = 0; i < parent.boxes.length; i++) { | ||
if (previousType === parent.boxes[i].type) { | ||
parent.boxes.splice(i + 1, 0, newBox); | ||
inserted = true; | ||
break; | ||
} | ||
} | ||
} | ||
if (!inserted) { | ||
parent.boxes.push(newBox); | ||
} | ||
return newBox; | ||
};*/ | ||
var ISOBox = function() { | ||
@@ -123,13 +275,139 @@ this._cursor = new ISOBoxer.Cursor(); | ||
ISOBox.create = function(type) { | ||
var newBox = new ISOBox(); | ||
newBox.type = type; | ||
newBox.boxes = []; | ||
return newBox; | ||
}; | ||
ISOBox.prototype._boxContainers = ['dinf', 'edts', 'mdia', 'meco', 'mfra', 'minf', 'moof', 'moov', 'mvex', 'stbl', 'strk', 'traf', 'trak', 'tref', 'udta', 'vttc', 'sinf', 'schi', 'encv', 'enca']; | ||
ISOBox.prototype._boxProcessors = {}; | ||
/////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// Generic read/write functions | ||
ISOBox.prototype._procField = function (name, type, size) { | ||
if (this._parsing) { | ||
this[name] = this._readField(type, size); | ||
} | ||
else { | ||
this._writeField(type, size, this[name]); | ||
} | ||
}; | ||
ISOBox.prototype._procFieldArray = function (name, length, type, size) { | ||
var i; | ||
if (this._parsing) { | ||
this[name] = []; | ||
for (i = 0; i < length; i++) { | ||
this[name][i] = this._readField(type, size); | ||
} | ||
} | ||
else { | ||
for (i = 0; i < this[name].length; i++) { | ||
this._writeField(type, size, this[name][i]); | ||
} | ||
} | ||
}; | ||
ISOBox.prototype._procFullBox = function() { | ||
this._procField('version', 'uint', 8); | ||
this._procField('flags', 'uint', 24); | ||
}; | ||
ISOBox.prototype._procEntries = function(name, length, fn) { | ||
var i; | ||
if (this._parsing) { | ||
this[name] = []; | ||
for (i = 0; i < length; i++) { | ||
this[name].push({}); | ||
fn.call(this, this[name][i]); | ||
} | ||
} | ||
else { | ||
for (i = 0; i < length; i++) { | ||
fn.call(this, this[name][i]); | ||
} | ||
} | ||
}; | ||
ISOBox.prototype._procSubEntries = function(entry, name, length, fn) { | ||
var i; | ||
if (this._parsing) { | ||
entry[name] = []; | ||
for (i = 0; i < length; i++) { | ||
entry[name].push({}); | ||
fn.call(this, entry[name][i]); | ||
} | ||
} | ||
else { | ||
for (i = 0; i < length; i++) { | ||
fn.call(this, entry[name][i]); | ||
} | ||
} | ||
}; | ||
ISOBox.prototype._procEntryField = function (entry, name, type, size) { | ||
if (this._parsing) { | ||
entry[name] = this._readField(type, size); | ||
} | ||
else { | ||
this._writeField(type, size, entry[name]); | ||
} | ||
}; | ||
ISOBox.prototype._procSubBoxes = function(name, length) { | ||
var i; | ||
if (this._parsing) { | ||
this[name] = []; | ||
for (i = 0; i < length; i++) { | ||
this[name].push(ISOBox.parse(this)); | ||
} | ||
} | ||
else { | ||
for (i = 0; i < length; i++) { | ||
if (this._rawo) { | ||
this[name][i].write(); | ||
} else { | ||
this.size += this[name][i].getLength(); | ||
} | ||
} | ||
} | ||
}; | ||
/////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// Read/parse functions | ||
ISOBox.prototype._readField = function(type, size) { | ||
switch (type) { | ||
case 'uint': | ||
return this._readUint(size); | ||
case 'int': | ||
return this._readInt(size); | ||
case 'template': | ||
return this._readTemplate(size); | ||
case 'string': | ||
return (size === -1) ? this._readTerminatedString() : this._readString(size); | ||
case 'data': | ||
return this._readData(size); | ||
case 'utf8': | ||
return this._readUTF8String(); | ||
default: | ||
return -1; | ||
} | ||
}; | ||
ISOBox.prototype._readInt = function(size) { | ||
var result = null; | ||
var result = null, | ||
offset = this._cursor.offset - this._raw.byteOffset; | ||
switch(size) { | ||
case 8: | ||
result = this._raw.getInt8(this._cursor.offset - this._raw.byteOffset); | ||
result = this._raw.getInt8(offset); | ||
break; | ||
case 16: | ||
result = this._raw.getInt16(this._cursor.offset - this._raw.byteOffset); | ||
result = this._raw.getInt16(offset); | ||
break; | ||
case 32: | ||
result = this._raw.getInt32(this._cursor.offset - this._raw.byteOffset); | ||
result = this._raw.getInt32(offset); | ||
break; | ||
@@ -139,4 +417,4 @@ case 64: | ||
// This will give unexpected results for integers >= 2^53 | ||
var s1 = this._raw.getInt32(this._cursor.offset - this._raw.byteOffset); | ||
var s2 = this._raw.getInt32(this._cursor.offset - this._raw.byteOffset + 4); | ||
var s1 = this._raw.getInt32(offset); | ||
var s2 = this._raw.getInt32(offset + 4); | ||
result = (s1 * Math.pow(2,32)) + s2; | ||
@@ -151,17 +429,18 @@ break; | ||
var result = null, | ||
offset = this._cursor.offset - this._raw.byteOffset, | ||
s1, s2; | ||
switch(size) { | ||
case 8: | ||
result = this._raw.getUint8(this._cursor.offset - this._raw.byteOffset); | ||
result = this._raw.getUint8(offset); | ||
break; | ||
case 16: | ||
result = this._raw.getUint16(this._cursor.offset - this._raw.byteOffset); | ||
result = this._raw.getUint16(offset); | ||
break; | ||
case 24: | ||
s1 = this._raw.getUint16(this._cursor.offset - this._raw.byteOffset); | ||
s2 = this._raw.getUint8(this._cursor.offset - this._raw.byteOffset + 2); | ||
s1 = this._raw.getUint16(offset); | ||
s2 = this._raw.getUint8(offset + 2); | ||
result = (s1 << 8) + s2; | ||
break; | ||
case 32: | ||
result = this._raw.getUint32(this._cursor.offset - this._raw.byteOffset); | ||
result = this._raw.getUint32(offset); | ||
break; | ||
@@ -171,4 +450,4 @@ case 64: | ||
// This will give unexpected results for integers >= 2^53 | ||
s1 = this._raw.getUint32(this._cursor.offset - this._raw.byteOffset); | ||
s2 = this._raw.getUint32(this._cursor.offset - this._raw.byteOffset + 4); | ||
s1 = this._raw.getUint32(offset); | ||
s2 = this._raw.getUint32(offset + 4); | ||
result = (s1 * Math.pow(2,32)) + s2; | ||
@@ -190,2 +469,8 @@ break; | ||
ISOBox.prototype._readTemplate = function(size) { | ||
var pre = this._readUint(size / 2); | ||
var post = this._readUint(size / 2); | ||
return pre + (post / Math.pow(2, size / 2)); | ||
}; | ||
ISOBox.prototype._readTerminatedString = function() { | ||
@@ -201,8 +486,2 @@ var str = ''; | ||
ISOBox.prototype._readTemplate = function(size) { | ||
var pre = this._readUint(size / 2); | ||
var post = this._readUint(size / 2); | ||
return pre + (post / Math.pow(2, size / 2)); | ||
}; | ||
ISOBox.prototype._readData = function(size) { | ||
@@ -215,3 +494,9 @@ var length = (size > 0) ? size : (this._raw.byteLength - (this._cursor.offset - this._offset)); | ||
ISOBox.prototype._readUTF8String = function() { | ||
var data = this._readData(); | ||
return ISOBoxer.Utils.dataViewToString(data); | ||
}; | ||
ISOBox.prototype._parseBox = function() { | ||
this._parsing = true; | ||
this._cursor.offset = this._offset; | ||
@@ -225,7 +510,7 @@ | ||
this.size = this._readUint(32); | ||
this.type = this._readString(4); | ||
this._procField('size', 'uint', 32); | ||
this._procField('type', 'string', 4); | ||
if (this.size == 1) { this.largesize = this._readUint(64); } | ||
if (this.type == 'uuid') { this.usertype = this._readString(16); } | ||
if (this.size === 1) { this._procField('largesize', 'uint', 64); } | ||
if (this.type === 'uuid') { this._procFieldArray('usertype', 16, 'uint', 8); } | ||
@@ -255,6 +540,10 @@ switch(this.size) { | ||
if (!this._incomplete) { | ||
if (this._boxProcessors[this.type]) { | ||
this._boxProcessors[this.type].call(this); | ||
} | ||
if (this._boxContainers.indexOf(this.type) !== -1) { | ||
this._parseContainerBox(); | ||
} else if (this._boxParsers[this.type]) { | ||
this._boxParsers[this.type].call(this); | ||
} else{ | ||
// Unknown box => read and store box content | ||
this._data = this._readData(); | ||
} | ||
@@ -276,456 +565,618 @@ } | ||
ISOBox.prototype._boxContainers = ['dinf', 'edts', 'mdia', 'meco', 'mfra', 'minf', 'moof', 'moov', 'mvex', 'stbl', 'strk', 'traf', 'trak', 'tref', 'udta', 'vttc']; | ||
/////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// Write functions | ||
ISOBox.prototype._boxParsers = {}; | ||
ISOBox.prototype.append = function(box, pos) { | ||
ISOBoxer.Utils.appendBox(this, box, pos); | ||
}; | ||
ISOBox.prototype.getLength = function() { | ||
this._parsing = false; | ||
this._rawo = null; | ||
this.size = 0; | ||
this._procField('size', 'uint', 32); | ||
this._procField('type', 'string', 4); | ||
if (this.size === 1) { this._procField('largesize', 'uint', 64); } | ||
if (this.type === 'uuid') { this._procFieldArray('usertype', 16, 'uint', 8); } | ||
if (this._boxProcessors[this.type]) { | ||
this._boxProcessors[this.type].call(this); | ||
} | ||
if (this._boxContainers.indexOf(this.type) !== -1) { | ||
for (var i = 0; i < this.boxes.length; i++) { | ||
this.size += this.boxes[i].getLength(); | ||
} | ||
} | ||
if (this._data) { | ||
this._writeData(this._data); | ||
} | ||
return this.size; | ||
}; | ||
ISOBox.prototype.write = function() { | ||
this._parsing = false; | ||
this._cursor.offset = this._parent._cursor.offset; | ||
switch(this.size) { | ||
case 0: | ||
this._rawo = new DataView(this._parent._rawo.buffer, this._cursor.offset, (this.parent._rawo.byteLength - this._cursor.offset)); | ||
break; | ||
case 1: | ||
this._rawo = new DataView(this._parent._rawo.buffer, this._cursor.offset, this.largesize); | ||
break; | ||
default: | ||
this._rawo = new DataView(this._parent._rawo.buffer, this._cursor.offset, this.size); | ||
} | ||
this._procField('size', 'uint', 32); | ||
this._procField('type', 'string', 4); | ||
if (this.size === 1) { this._procField('largesize', 'uint', 64); } | ||
if (this.type === 'uuid') { this._procFieldArray('usertype', 16, 'uint', 8); } | ||
if (this._boxProcessors[this.type]) { | ||
this._boxProcessors[this.type].call(this); | ||
} | ||
if (this._boxContainers.indexOf(this.type) !== -1) { | ||
for (var i = 0; i < this.boxes.length; i++) { | ||
this.boxes[i].write(); | ||
} | ||
} | ||
if (this._data) { | ||
this._writeData(this._data); | ||
} | ||
this._parent._cursor.offset += this.size; | ||
return this.size; | ||
}; | ||
ISOBox.prototype._writeInt = function(size, value) { | ||
if (this._rawo) { | ||
var offset = this._cursor.offset - this._rawo.byteOffset; | ||
switch(size) { | ||
case 8: | ||
this._rawo.setInt8(offset, value); | ||
break; | ||
case 16: | ||
this._rawo.setInt16(offset, value); | ||
break; | ||
case 32: | ||
this._rawo.setInt32(offset, value); | ||
break; | ||
case 64: | ||
// Warning: JavaScript cannot handle 64-bit integers natively. | ||
// This will give unexpected results for integers >= 2^53 | ||
var s1 = Math.round(value / Math.pow(2,32)); | ||
var s2 = value - (s1 * Math.pow(2,32)); | ||
this._rawo.setUint32(offset, s1); | ||
this._rawo.setUint32(offset + 4, s2); | ||
break; | ||
} | ||
this._cursor.offset += (size >> 3); | ||
} else { | ||
this.size += (size >> 3); | ||
} | ||
}; | ||
ISOBox.prototype._writeUint = function(size, value) { | ||
if (this._rawo) { | ||
var offset = this._cursor.offset - this._rawo.byteOffset, | ||
s1, s2; | ||
switch(size) { | ||
case 8: | ||
this._rawo.setUint8(offset, value); | ||
break; | ||
case 16: | ||
this._rawo.setUint16(offset, value); | ||
break; | ||
case 24: | ||
s1 = (value & 0xFFFF00) >> 8; | ||
s2 = (value & 0x0000FF); | ||
this._rawo.setUint16(offset, s1); | ||
this._rawo.setUint8(offset + 2, s2); | ||
break; | ||
case 32: | ||
this._rawo.setUint32(offset, value); | ||
break; | ||
case 64: | ||
// Warning: JavaScript cannot handle 64-bit integers natively. | ||
// This will give unexpected results for integers >= 2^53 | ||
s1 = Math.round(value / Math.pow(2,32)); | ||
s2 = value - (s1 * Math.pow(2,32)); | ||
this._rawo.setUint32(offset, s1); | ||
this._rawo.setUint32(offset + 4, s2); | ||
break; | ||
} | ||
this._cursor.offset += (size >> 3); | ||
} else { | ||
this.size += (size >> 3); | ||
} | ||
}; | ||
ISOBox.prototype._writeString = function(size, str) { | ||
for (var c = 0; c < size; c++) { | ||
this._writeUint(8, str.charCodeAt(c)); | ||
} | ||
}; | ||
ISOBox.prototype._writeTerminatedString = function(str) { | ||
if (str.length === 0) { | ||
return; | ||
} | ||
for (var c = 0; c < str.length; c++) { | ||
this._writeUint(8, str.charCodeAt(c)); | ||
} | ||
this._writeUint(8, 0); | ||
}; | ||
ISOBox.prototype._writeTemplate = function(size, value) { | ||
var pre = Math.round(value); | ||
var post = (value - pre) * Math.pow(2, size / 2); | ||
this._writeUint(size / 2, pre); | ||
this._writeUint(size / 2, post); | ||
}; | ||
ISOBox.prototype._writeData = function(data) { | ||
if (data instanceof Array) { | ||
data = new DataView(Uint8Array.from(data).buffer); | ||
} | ||
if (data instanceof Uint8Array) { | ||
data = new DataView(data.buffer); | ||
} | ||
if (this._rawo) { | ||
var offset = this._cursor.offset - this._rawo.byteOffset; | ||
for (var i = 0; i < data.byteLength; i++) { | ||
this._rawo.setUint8(offset + i, data.getUint8(i)); | ||
} | ||
this._cursor.offset += data.byteLength; | ||
} else { | ||
this.size += data.byteLength; | ||
} | ||
}; | ||
ISOBox.prototype._writeUTF8String = function(string) { | ||
var u = ISOBoxer.Utils.utf8ToByteArray(string); | ||
if (this._rawo) { | ||
var dataView = new DataView(this._rawo.buffer, this._cursor.offset, u.length); | ||
for (var i = 0; i < u.length; i++) { | ||
dataView.setUint8(i, u[i]); | ||
} | ||
} else { | ||
this.size += u.length; | ||
} | ||
}; | ||
ISOBox.prototype._writeField = function(type, size, value) { | ||
switch (type) { | ||
case 'uint': | ||
this._writeUint(size, value); | ||
break; | ||
case 'int': | ||
this._writeInt(size, value); | ||
break; | ||
case 'template': | ||
this._writeTemplate(size, value); | ||
break; | ||
case 'string': | ||
if (size == -1) { | ||
this._writeTerminatedString(value); | ||
} else { | ||
this._writeString(size, value); | ||
} | ||
break; | ||
case 'data': | ||
this._writeData(value); | ||
break; | ||
case 'utf8': | ||
this._writeUTF8String(value); | ||
break; | ||
default: | ||
break; | ||
} | ||
}; | ||
// ISO/IEC 14496-15:2014 - avc1 box | ||
ISOBox.prototype._boxParsers['avc1'] = function() { | ||
ISOBox.prototype._boxProcessors['avc1'] = ISOBox.prototype._boxProcessors['encv'] = function() { | ||
// SampleEntry fields | ||
this.reserved1 = [ | ||
this._readUint(8), | ||
this._readUint(8), | ||
this._readUint(8), | ||
this._readUint(8), | ||
this._readUint(8), | ||
this._readUint(8) | ||
]; | ||
this.data_reference_index = this._readUint(16); | ||
this._procFieldArray('reserved1', 6, 'uint', 8); | ||
this._procField('data_reference_index', 'uint', 16); | ||
// VisualSampleEntry fields | ||
this.pre_defined1 = this._readUint(16); | ||
this.reserved2 = this._readUint(16); | ||
this.pre_defined2 = [ | ||
this._readUint(32), | ||
this._readUint(32), | ||
this._readUint(32) | ||
]; | ||
this.width = this._readUint(16); | ||
this.height = this._readUint(16); | ||
this.horizresolution = this._readTemplate(32); | ||
this.vertresolution = this._readTemplate(32); | ||
this.reserved3 = this._readUint(32); | ||
this.frame_count = this._readUint(16); | ||
var length = this._readUint(8); | ||
this.compressorname = this._readString(length); | ||
for (var i = 0; i < (31 - length); i++) { | ||
this._readUint(8); | ||
} | ||
this.depth = this._readUint(16); | ||
this.pre_defined3 = this._readInt(16); | ||
this._procField('pre_defined1', 'uint', 16); | ||
this._procField('reserved2', 'uint', 16); | ||
this._procFieldArray('pre_defined2', 3, 'uint', 32); | ||
this._procField('width', 'uint', 16); | ||
this._procField('height', 'uint', 16); | ||
this._procField('horizresolution', 'template', 32); | ||
this._procField('vertresolution', 'template', 32); | ||
this._procField('reserved3', 'uint', 32); | ||
this._procField('frame_count', 'uint', 16); | ||
this._procFieldArray('compressorname', 32,'uint', 8); | ||
this._procField('depth', 'uint', 16); | ||
this._procField('pre_defined3', 'int', 16); | ||
// AVCSampleEntry fields | ||
this.config = this._readData(); | ||
this._procField('config', 'data', -1); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.7.2 Data Reference Box | ||
ISOBox.prototype._boxParsers['dref'] = function() { | ||
this._parseFullBox(); | ||
this.entry_count = this._readUint(32); | ||
this.entries = []; | ||
for (var i = 0; i < this.entry_count ; i++){ | ||
this.entries.push(ISOBox.parse(this)); | ||
} | ||
ISOBox.prototype._boxProcessors['dref'] = function() { | ||
this._procFullBox(); | ||
this._procField('entry_count', 'uint', 32); | ||
this._procSubBoxes('entries', this.entry_count); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.6.6 Edit List Box | ||
ISOBox.prototype._boxParsers['elst'] = function() { | ||
this._parseFullBox(); | ||
this.entry_count = this._readUint(32); | ||
this.entries = []; | ||
ISOBox.prototype._boxProcessors['elst'] = function() { | ||
this._procFullBox(); | ||
this._procField('entry_count', 'uint', 32); | ||
this._procEntries('entries', this.entry_count, function(entry) { | ||
this._procEntryField(entry, 'segment_duration', 'uint', (this.version === 1) ? 64 : 32); | ||
this._procEntryField(entry, 'media_time', 'int', (this.version === 1) ? 64 : 32); | ||
this._procEntryField(entry, 'media_rate_integer', 'int', 16); | ||
this._procEntryField(entry, 'media_rate_fraction', 'int', 16); | ||
}); | ||
}; | ||
for (var i=1; i <= this.entry_count; i++) { | ||
var entry = {}; | ||
if (this.version == 1) { | ||
entry.segment_duration = this._readUint(64); | ||
entry.media_time = this._readInt(64); | ||
} else { | ||
entry.segment_duration = this._readUint(32); | ||
entry.media_time = this._readInt(32); | ||
} | ||
entry.media_rate_integer = this._readInt(16); | ||
entry.media_rate_fraction = this._readInt(16); | ||
this.entries.push(entry); | ||
} | ||
}; | ||
// ISO/IEC 23009-1:2014 - 5.10.3.3 Event Message Box | ||
ISOBox.prototype._boxParsers['emsg'] = function() { | ||
this._parseFullBox(); | ||
this.scheme_id_uri = this._readTerminatedString(); | ||
this.value = this._readTerminatedString(); | ||
this.timescale = this._readUint(32); | ||
this.presentation_time_delta = this._readUint(32); | ||
this.event_duration = this._readUint(32); | ||
this.id = this._readUint(32); | ||
this.message_data = new DataView(this._raw.buffer, this._cursor.offset, this._raw.byteLength - (this._cursor.offset - this._offset)); | ||
ISOBox.prototype._boxProcessors['emsg'] = function() { | ||
this._procFullBox(); | ||
this._procField('scheme_id_uri', 'string', -1); | ||
this._procField('value', 'string', -1); | ||
this._procField('timescale', 'uint', 32); | ||
this._procField('presentation_time_delta', 'uint', 32); | ||
this._procField('event_duration', 'uint', 32); | ||
this._procField('id', 'uint', 32); | ||
this._procField('message_data', 'data', -1); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.1.2 Free Space Box | ||
ISOBox.prototype._boxParsers['free'] = ISOBox.prototype._boxParsers['skip'] = function() { | ||
this.data = new DataView(this._raw.buffer, this._cursor.offset, this._raw.byteLength - (this._cursor.offset - this._offset)); | ||
ISOBox.prototype._boxProcessors['free'] = ISOBox.prototype._boxProcessors['skip'] = function() { | ||
this._procField('data', 'data', -1); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.12.2 Original Format Box | ||
ISOBox.prototype._boxProcessors['frma'] = function() { | ||
this._procField('data_format', 'uint', 32); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 4.3 File Type Box / 8.16.2 Segment Type Box | ||
ISOBox.prototype._boxParsers['ftyp'] = ISOBox.prototype._boxParsers['styp'] = function() { | ||
this.major_brand = this._readString(4); | ||
this.minor_version = this._readUint(32); | ||
this.compatible_brands = []; | ||
while (this._cursor.offset - this._raw.byteOffset < this._raw.byteLength) { | ||
this.compatible_brands.push(this._readString(4)); | ||
ISOBox.prototype._boxProcessors['ftyp'] = | ||
ISOBox.prototype._boxProcessors['styp'] = function() { | ||
this._procField('major_brand', 'string', 4); | ||
this._procField('minor_version', 'uint', 32); | ||
var nbCompatibleBrands = -1; | ||
if (this._parsing) { | ||
nbCompatibleBrands = (this._raw.byteLength - (this._cursor.offset - this._raw.byteOffset)) / 4; | ||
} | ||
this._procFieldArray('compatible_brands', nbCompatibleBrands, 'string', 4); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.4.3 Handler Reference Box | ||
ISOBox.prototype._boxParsers['hdlr'] = function() { | ||
this._parseFullBox(); | ||
this.pre_defined = this._readUint(32); | ||
this.handler_type = this._readString(4); | ||
this.reserved = [this._readUint(32), this._readUint(32), this._readUint(32)]; | ||
this.name = this._readTerminatedString(); | ||
ISOBox.prototype._boxProcessors['hdlr'] = function() { | ||
this._procFullBox(); | ||
this._procField('pre_defined', 'uint', 32); | ||
this._procField('handler_type', 'string', 4); | ||
this._procFieldArray('reserved', 3, 'uint', 32); | ||
this._procField('name', 'string', -1); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.1.1 Media Data Box | ||
ISOBox.prototype._boxParsers['mdat'] = function() { | ||
this.data = this._readData(); | ||
ISOBox.prototype._boxProcessors['mdat'] = function() { | ||
this._procField('data', 'data', -1); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.4.2 Media Header Box | ||
ISOBox.prototype._boxParsers['mdhd'] = function() { | ||
this._parseFullBox(); | ||
if (this.version == 1) { | ||
this.creation_time = this._readUint(64); | ||
this.modification_time = this._readUint(64); | ||
this.timescale = this._readUint(32); | ||
this.duration = this._readUint(64); | ||
} else { | ||
this.creation_time = this._readUint(32); | ||
this.modification_time = this._readUint(32); | ||
this.timescale = this._readUint(32); | ||
this.duration = this._readUint(32); | ||
ISOBox.prototype._boxProcessors['mdhd'] = function() { | ||
this._procFullBox(); | ||
this._procField('creation_time', 'uint', (this.version == 1) ? 64 : 32); | ||
this._procField('modification_time', 'uint', (this.version == 1) ? 64 : 32); | ||
this._procField('timescale', 'uint', 32); | ||
this._procField('duration', 'uint', (this.version == 1) ? 64 : 32); | ||
if (!this._parsing && typeof this.language === 'string') { | ||
// In case of writing and language has been set as a string, then convert it into char codes array | ||
this.language = ((this.language.charCodeAt(0) - 0x60) << 10) | | ||
((this.language.charCodeAt(1) - 0x60) << 5) | | ||
((this.language.charCodeAt(2) - 0x60)); | ||
} | ||
var language = this._readUint(16); | ||
this.pad = (language >> 15); | ||
this.language = String.fromCharCode( | ||
((language >> 10) & 0x1F) + 0x60, | ||
((language >> 5) & 0x1F) + 0x60, | ||
(language & 0x1F) + 0x60 | ||
); | ||
this.pre_defined = this._readUint(16); | ||
this._procField('language', 'uint', 16); | ||
if (this._parsing) { | ||
this.language = String.fromCharCode(((this.language >> 10) & 0x1F) + 0x60, | ||
((this.language >> 5) & 0x1F) + 0x60, | ||
(this.language & 0x1F) + 0x60); | ||
} | ||
this._procField('pre_defined', 'uint', 16); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.8.2 Movie Extends Header Box | ||
ISOBox.prototype._boxParsers['mehd'] = function() { | ||
this._parseFullBox(); | ||
ISOBox.prototype._boxProcessors['mehd'] = function() { | ||
this._procFullBox(); | ||
this._procField('fragment_duration', 'uint', (this.version == 1) ? 64 : 32); | ||
}; | ||
if (this.version == 1) { | ||
this.fragment_duration = this._readUint(64); | ||
} else { // version==0 | ||
this.fragment_duration = this._readUint(32); | ||
} | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.8.5 Movie Fragment Header Box | ||
ISOBox.prototype._boxParsers['mfhd'] = function() { | ||
this._parseFullBox(); | ||
this.sequence_number = this._readUint(32); | ||
ISOBox.prototype._boxProcessors['mfhd'] = function() { | ||
this._procFullBox(); | ||
this._procField('sequence_number', 'uint', 32); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.8.11 Movie Fragment Random Access Box | ||
ISOBox.prototype._boxParsers['mfro'] = function() { | ||
this._parseFullBox(); | ||
this.mfra_size = this._readUint(32); // Called mfra_size to distinguish from the normal "size" attribute of a box | ||
ISOBox.prototype._boxProcessors['mfro'] = function() { | ||
this._procFullBox(); | ||
this._procField('mfra_size', 'uint', 32); // Called mfra_size to distinguish from the normal "size" attribute of a box | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.5.2.2 mp4a box (use AudioSampleEntry definition and naming) | ||
ISOBox.prototype._boxParsers['mp4a'] = function() { | ||
ISOBox.prototype._boxProcessors['mp4a'] = ISOBox.prototype._boxProcessors['enca'] = function() { | ||
// SampleEntry fields | ||
this.reserved1 = [ | ||
this._readUint(8), | ||
this._readUint(8), | ||
this._readUint(8), | ||
this._readUint(8), | ||
this._readUint(8), | ||
this._readUint(8) | ||
]; | ||
this.data_reference_index = this._readUint(16); | ||
this._procFieldArray('reserved1', 6, 'uint', 8); | ||
this._procField('data_reference_index', 'uint', 16); | ||
// AudioSampleEntry fields | ||
this.reserved2 = [this._readUint(32), this._readUint(32)]; | ||
this.channelcount = this._readUint(16); | ||
this.samplesize = this._readUint(16); | ||
this.pre_defined = this._readUint(16); | ||
this.reserved3 = this._readUint(16); | ||
this.samplerate = this._readTemplate(32); | ||
this._procFieldArray('reserved2', 2, 'uint', 32); | ||
this._procField('channelcount', 'uint', 16); | ||
this._procField('samplesize', 'uint', 16); | ||
this._procField('pre_defined', 'uint', 16); | ||
this._procField('reserved3', 'uint', 16); | ||
this._procField('samplerate', 'template', 32); | ||
// ESDescriptor fields | ||
this.esds = this._readData(); | ||
this._procField('esds', 'data', -1); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.2.2 Movie Header Box | ||
ISOBox.prototype._boxParsers['mvhd'] = function() { | ||
this._parseFullBox(); | ||
var i; | ||
ISOBox.prototype._boxProcessors['mvhd'] = function() { | ||
this._procFullBox(); | ||
this._procField('creation_time', 'uint', (this.version == 1) ? 64 : 32); | ||
this._procField('modification_time', 'uint', (this.version == 1) ? 64 : 32); | ||
this._procField('timescale', 'uint', 32); | ||
this._procField('duration', 'uint', (this.version == 1) ? 64 : 32); | ||
this._procField('rate', 'template', 32); | ||
this._procField('volume', 'template', 16); | ||
this._procField('reserved1', 'uint', 16); | ||
this._procFieldArray('reserved2', 2, 'uint', 32); | ||
this._procFieldArray('matrix', 9, 'template', 32); | ||
this._procFieldArray('pre_defined', 6,'uint', 32); | ||
this._procField('next_track_ID', 'uint', 32); | ||
}; | ||
if (this.version == 1) { | ||
this.creation_time = this._readUint(64); | ||
this.modification_time = this._readUint(64); | ||
this.timescale = this._readUint(32); | ||
this.duration = this._readUint(64); | ||
} else { | ||
this.creation_time = this._readUint(32); | ||
this.modification_time = this._readUint(32); | ||
this.timescale = this._readUint(32); | ||
this.duration = this._readUint(32); | ||
} | ||
this.rate = this._readTemplate(32); | ||
this.volume = this._readTemplate(16); | ||
this.reserved1 = this._readUint(16); | ||
this.reserved2 = [ this._readUint(32), this._readUint(32) ]; | ||
this.matrix = []; | ||
for (i=0; i<9; i++) { | ||
this.matrix.push(this._readTemplate(32)); | ||
} | ||
this.pre_defined = []; | ||
for (i=0; i<6; i++) { | ||
this.pre_defined.push(this._readUint(32)); | ||
} | ||
this.next_track_ID = this._readUint(32); | ||
}; | ||
// ISO/IEC 14496-30:2014 - WebVTT Cue Payload Box. | ||
ISOBox.prototype._boxParsers['payl'] = function() { | ||
var cue_text_raw = new DataView(this._raw.buffer, this._cursor.offset, this._raw.byteLength - (this._cursor.offset - this._offset)); | ||
this.cue_text = ISOBoxer.Utils.dataViewToString(cue_text_raw); | ||
ISOBox.prototype._boxProcessors['payl'] = function() { | ||
this._procField('cue_text', 'utf8'); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.16.3 Segment Index Box | ||
ISOBox.prototype._boxParsers['sidx'] = function() { | ||
this._parseFullBox(); | ||
this.reference_ID = this._readUint(32); | ||
this.timescale = this._readUint(32); | ||
if (this.version === 0) { | ||
this.earliest_presentation_time = this._readUint(32); | ||
this.first_offset = this._readUint(32); | ||
} else { | ||
this.earliest_presentation_time = this._readUint(64); | ||
this.first_offset = this._readUint(64); | ||
} | ||
this.reserved = this._readUint(16); | ||
this.reference_count = this._readUint(16); | ||
this.references = []; | ||
for (var i=0; i<this.reference_count; i++) { | ||
var ref = {}; | ||
var reference = this._readUint(32); | ||
ref.reference_type = (reference >> 31) & 0x1; | ||
ref.referenced_size = reference & 0x7FFFFFFF; | ||
ref.subsegment_duration = this._readUint(32); | ||
var sap = this._readUint(32); | ||
ref.starts_with_SAP = (sap >> 31) & 0x1; | ||
ref.SAP_type = (sap >> 28) & 0x7; | ||
ref.SAP_delta_time = sap & 0xFFFFFFF; | ||
this.references.push(ref); | ||
} | ||
//ISO/IEC 23001-7:2011 - 8.1 Protection System Specific Header Box | ||
ISOBox.prototype._boxProcessors['pssh'] = function() { | ||
this._procFullBox(); | ||
this._procFieldArray('SystemID', 16, 'uint', 8); | ||
this._procField('DataSize', 'uint', 32); | ||
this._procFieldArray('Data', this.DataSize, 'uint', 8); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.4.5.3 Sound Media Header Box | ||
ISOBox.prototype._boxParsers['smhd'] = function() { | ||
this._parseFullBox(); | ||
// ISO/IEC 14496-12:2012 - 8.12.5 Scheme Type Box | ||
ISOBox.prototype._boxProcessors['schm'] = function() { | ||
this._procFullBox(); | ||
this._procField('scheme_type', 'uint', 32); | ||
this._procField('scheme_version', 'uint', 32); | ||
this.balance = this._readTemplate(16); | ||
this.reserved = this._readUint(16); | ||
if (this.flags & 0x000001) { | ||
this._procField('scheme_uri', 'string', -1); | ||
} | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.6.4.1 sdtp box | ||
ISOBox.prototype._boxProcessors['sdtp'] = function() { | ||
this._procFullBox(); | ||
// ISO/IEC 14496-12:2012 - 8.16.4 Subsegment Index Box | ||
ISOBox.prototype._boxParsers['ssix'] = function() { | ||
this._parseFullBox(); | ||
this.subsegment_count = this._readUint(32); | ||
this.subsegments = []; | ||
var sample_count = -1; | ||
if (this._parsing) { | ||
sample_count = (this._raw.byteLength - (this._cursor.offset - this._raw.byteOffset)); | ||
} | ||
for (var i=0; i<this.subsegment_count; i++) { | ||
var subsegment = {}; | ||
subsegment.ranges_count = this._readUint(32); | ||
subsegment.ranges = []; | ||
this._procFieldArray('sample_dependency_table', sample_count, 'uint', 8); | ||
}; | ||
for (var j=0; j<subsegment.ranges_count; j++) { | ||
var range = {}; | ||
range.level = this._readUint(8); | ||
range.range_size = this._readUint(24); | ||
subsegment.ranges.push(range); | ||
// ISO/IEC 14496-12:2012 - 8.16.3 Segment Index Box | ||
ISOBox.prototype._boxProcessors['sidx'] = function() { | ||
this._procFullBox(); | ||
this._procField('reference_ID', 'uint', 32); | ||
this._procField('timescale', 'uint', 32); | ||
this._procField('earliest_presentation_time', 'uint', (this.version == 1) ? 64 : 32); | ||
this._procField('first_offset', 'uint', (this.version == 1) ? 64 : 32); | ||
this._procField('reserved', 'uint', 16); | ||
this._procField('reference_count', 'uint', 16); | ||
this._procEntries('references', this.reference_count, function(entry) { | ||
if (!this._parsing) { | ||
entry.reference = (entry.reference_type & 0x00000001) << 31; | ||
entry.reference |= (entry.referenced_size & 0x7FFFFFFF); | ||
entry.sap = (entry.starts_with_SAP & 0x00000001) << 31; | ||
entry.sap |= (entry.SAP_type & 0x00000003) << 28; | ||
entry.sap |= (entry.SAP_delta_time & 0x0FFFFFFF); | ||
} | ||
this.subsegments.push(subsegment); | ||
} | ||
this._procEntryField(entry, 'reference', 'uint', 32); | ||
this._procEntryField(entry, 'subsegment_duration', 'uint', 32); | ||
this._procEntryField(entry, 'sap', 'uint', 32); | ||
if (this._parsing) { | ||
entry.reference_type = (entry.reference >> 31) & 0x00000001; | ||
entry.referenced_size = entry.reference & 0x7FFFFFFF; | ||
entry.starts_with_SAP = (entry.sap >> 31) & 0x00000001; | ||
entry.SAP_type = (entry.sap >> 28) & 0x00000007; | ||
entry.SAP_delta_time = (entry.sap & 0x0FFFFFFF); | ||
} | ||
}); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.5.2 Sample Description Box | ||
ISOBox.prototype._boxParsers['stsd'] = function() { | ||
this._parseFullBox(); | ||
this.entry_count = this._readUint(32); | ||
this.entries = []; | ||
for (var i = 0; i < this.entry_count ; i++){ | ||
this.entries.push(ISOBox.parse(this)); | ||
} | ||
// ISO/IEC 14496-12:2012 - 8.4.5.3 Sound Media Header Box | ||
ISOBox.prototype._boxProcessors['smhd'] = function() { | ||
this._procFullBox(); | ||
this._procField('balance', 'uint', 16); | ||
this._procField('reserved', 'uint', 16); | ||
}; | ||
// ISO/IEC 14496-12:2015 - 8.7.7 Sub-Sample Information Box | ||
ISOBox.prototype._boxParsers['subs'] = function () { | ||
this._parseFullBox(); | ||
this.entry_count = this._readUint(32); | ||
this.entries = []; | ||
for (var i = 0; i < this.entry_count; i++) { | ||
var entry = {}; | ||
entry.sample_delta = this._readUint(32); | ||
entry.subsample_count = this._readUint(16); | ||
entry.subsamples = []; | ||
for (var j = 0; j < entry.subsample_count; j++) { | ||
var subsample = {}; | ||
if (this.version & 0x1) { | ||
subsample.subsample_size = this._readUint(32); | ||
} else { | ||
subsample.subsample_size = this._readUint(16); | ||
} | ||
subsample.subsample_priority = this._readUint(8); | ||
subsample.discardable = this._readUint(8); | ||
subsample.codec_specific_parameters = this._readUint(32); | ||
entry.subsamples.push(subsample); | ||
} | ||
this.entries.push(entry); | ||
} | ||
// ISO/IEC 14496-12:2012 - 8.16.4 Subsegment Index Box | ||
ISOBox.prototype._boxProcessors['ssix'] = function() { | ||
this._procFullBox(); | ||
this._procField('subsegment_count', 'uint', 32); | ||
this._procEntries('subsegments', this.subsegment_count, function(subsegment) { | ||
this._procEntryField(subsegment, 'ranges_count', 'uint', 32); | ||
this._procSubEntries(subsegment, 'ranges', subsegment.ranges_count, function(range) { | ||
this._procEntryField(range, 'level', 'uint', 8); | ||
this._procEntryField(range, 'range_size', 'uint', 24); | ||
}); | ||
}); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.8.12 Track Fragmnent Decode Time | ||
ISOBox.prototype._boxParsers['tfdt'] = function() { | ||
this._parseFullBox(); | ||
if (this.version == 1) { | ||
this.baseMediaDecodeTime = this._readUint(64); | ||
} else { | ||
this.baseMediaDecodeTime = this._readUint(32); | ||
} | ||
// ISO/IEC 14496-12:2012 - 8.5.2 Sample Description Box | ||
ISOBox.prototype._boxProcessors['stsd'] = function() { | ||
this._procFullBox(); | ||
this._procField('entry_count', 'uint', 32); | ||
this._procSubBoxes('entries', this.entry_count); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.8.7 Track Fragment Header Box | ||
ISOBox.prototype._boxParsers['tfhd'] = function() { | ||
this._parseFullBox(); | ||
this.track_ID = this._readUint(32); | ||
if (this.flags & 0x1) this.base_data_offset = this._readUint(64); | ||
if (this.flags & 0x2) this.sample_description_offset = this._readUint(32); | ||
if (this.flags & 0x8) this.default_sample_duration = this._readUint(32); | ||
if (this.flags & 0x10) this.default_sample_size = this._readUint(32); | ||
if (this.flags & 0x20) this.default_sample_flags = this._readUint(32); | ||
// ISO/IEC 14496-12:2015 - 8.7.7 Sub-Sample Information Box | ||
ISOBox.prototype._boxProcessors['subs'] = function () { | ||
this._procFullBox(); | ||
this._procField('entry_count', 'uint', 32); | ||
this._procEntries('entries', this.entry_count, function(entry) { | ||
this._procEntryField(entry, 'sample_delta', 'uint', 32); | ||
this._procEntryField(entry, 'subsample_count', 'uint', 16); | ||
this._procSubEntries(entry, 'subsamples', entry.subsample_count, function(subsample) { | ||
this._procEntryField(subsample, 'subsample_size', 'uint', (this.version === 1) ? 32 : 16); | ||
this._procEntryField(subsample, 'subsample_priority', 'uint', 8); | ||
this._procEntryField(subsample, 'discardable', 'uint', 8); | ||
this._procEntryField(subsample, 'codec_specific_parameters', 'uint', 32); | ||
}); | ||
}); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.8.10 Track Fragment Random Access Box | ||
ISOBox.prototype._boxParsers['tfra'] = function() { | ||
this._parseFullBox(); | ||
this.track_ID = this._readUint(32); | ||
this._packed = this._readUint(32); | ||
this.reserved = this._packed >>> 6; | ||
//ISO/IEC 23001-7:2011 - 8.2 Track Encryption Box | ||
ISOBox.prototype._boxProcessors['tenc'] = function() { | ||
this._procFullBox(); | ||
this.length_size_of_traf_num = (this._packed && 0xFFFF00000000) >>> 4; | ||
this.length_size_of_trun_num = (this._packed && 0xFFFF0000) >>> 2; | ||
this.length_size_of_sample_num = this._packed && 0xFF; | ||
this._procField('default_IsEncrypted', 'uint', 24); | ||
this._procField('default_IV_size', 'uint', 8); | ||
this._procFieldArray('default_KID', 16, 'uint', 8); | ||
}; | ||
this.number_of_entry = this._readUint(32); | ||
// ISO/IEC 14496-12:2012 - 8.8.12 Track Fragmnent Decode Time | ||
ISOBox.prototype._boxProcessors['tfdt'] = function() { | ||
this._procFullBox(); | ||
this._procField('baseMediaDecodeTime', 'uint', (this.version == 1) ? 64 : 32); | ||
}; | ||
this.entries = []; | ||
// ISO/IEC 14496-12:2012 - 8.8.7 Track Fragment Header Box | ||
ISOBox.prototype._boxProcessors['tfhd'] = function() { | ||
this._procFullBox(); | ||
this._procField('track_ID', 'uint', 32); | ||
if (this.flags & 0x01) this._procField('base_data_offset', 'uint', 64); | ||
if (this.flags & 0x02) this._procField('sample_description_offset', 'uint', 32); | ||
if (this.flags & 0x08) this._procField('default_sample_duration', 'uint', 32); | ||
if (this.flags & 0x10) this._procField('default_sample_size', 'uint', 32); | ||
if (this.flags & 0x20) this._procField('default_sample_flags', 'uint', 32); | ||
}; | ||
for (var i = 0; i < this.number_of_entry ; i++){ | ||
var entry = {}; | ||
if(this.version==1){ | ||
entry.time = this._readUint(64); | ||
entry.moof_offset = this._readUint(64); | ||
}else{ | ||
entry.time = this._readUint(32); | ||
entry.moof_offset = this._readUint(32); | ||
} | ||
entry.traf_number = this._readUint((this.length_size_of_traf_num + 1) * 8); | ||
entry.trun_number = this._readUint((this.length_size_of_trun_num + 1) * 8); | ||
entry.sample_number = this._readUint((this.length_size_of_sample_num + 1) * 8); | ||
this.entries.push(entry); | ||
// ISO/IEC 14496-12:2012 - 8.8.10 Track Fragment Random Access Box | ||
ISOBox.prototype._boxProcessors['tfra'] = function() { | ||
this._procFullBox(); | ||
this._procField('track_ID', 'uint', 32); | ||
if (!this._parsing) { | ||
this.reserved = 0; | ||
this.reserved |= (this.length_size_of_traf_num & 0x00000030) << 4; | ||
this.reserved |= (this.length_size_of_trun_num & 0x0000000C) << 2; | ||
this.reserved |= (this.length_size_of_sample_num & 0x00000003); | ||
} | ||
this._procField('reserved', 'uint', 32); | ||
if (this._parsing) { | ||
this.length_size_of_traf_num = (this.reserved & 0x00000030) >> 4; | ||
this.length_size_of_trun_num = (this.reserved & 0x0000000C) >> 2; | ||
this.length_size_of_sample_num = (this.reserved & 0x00000003); | ||
} | ||
this._procField('number_of_entry', 'uint', 32); | ||
this._procEntries('entries', this.number_of_entry, function(entry) { | ||
this._procEntryField(entry, 'time', 'uint', (this.version === 1) ? 64 : 32); | ||
this._procEntryField(entry, 'moof_offset', 'uint', (this.version === 1) ? 64 : 32); | ||
this._procEntryField(entry, 'traf_number', 'uint', (this.length_size_of_traf_num + 1) * 8); | ||
this._procEntryField(entry, 'trun_number', 'uint', (this.length_size_of_trun_num + 1) * 8); | ||
this._procEntryField(entry, 'sample_number', 'uint', (this.length_size_of_sample_num + 1) * 8); | ||
}); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.3.2 Track Header Box | ||
ISOBox.prototype._boxParsers['tkhd'] = function() { | ||
this._parseFullBox(); | ||
ISOBox.prototype._boxProcessors['tkhd'] = function() { | ||
this._procFullBox(); | ||
this._procField('creation_time', 'uint', (this.version == 1) ? 64 : 32); | ||
this._procField('modification_time', 'uint', (this.version == 1) ? 64 : 32); | ||
this._procField('track_ID', 'uint', 32); | ||
this._procField('reserved1', 'uint', 32); | ||
this._procField('duration', 'uint', (this.version == 1) ? 64 : 32); | ||
this._procFieldArray('reserved2', 2, 'uint', 32); | ||
this._procField('layer', 'uint', 16); | ||
this._procField('alternate_group', 'uint', 16); | ||
this._procField('volume', 'template', 16); | ||
this._procField('reserved3', 'uint', 16); | ||
this._procFieldArray('matrix', 9, 'template', 32); | ||
this._procField('width', 'template', 32); | ||
this._procField('height', 'template', 32); | ||
}; | ||
if (this.version == 1) { | ||
this.creation_time = this._readUint(64); | ||
this.modification_time = this._readUint(64); | ||
this.track_ID = this._readUint(32); | ||
this.reserved1 = this._readUint(32); | ||
this.duration = this._readUint(64); | ||
} else { | ||
this.creation_time = this._readUint(32); | ||
this.modification_time = this._readUint(32); | ||
this.track_ID = this._readUint(32); | ||
this.reserved1 = this._readUint(32); | ||
this.duration = this._readUint(32); | ||
} | ||
this.reserved2 = [ | ||
this._readUint(32), | ||
this._readUint(32) | ||
]; | ||
this.layer = this._readUint(16); | ||
this.alternate_group = this._readUint(16); | ||
this.volume = this._readTemplate(16); | ||
this.reserved3 = this._readUint(16); | ||
this.matrix = []; | ||
for (var i=0; i<9; i++) { | ||
this.matrix.push(this._readTemplate(32)); | ||
} | ||
this.width = this._readTemplate(32); | ||
this.height = this._readTemplate(32); | ||
// ISO/IEC 14496-12:2012 - 8.8.3 Track Extends Box | ||
ISOBox.prototype._boxProcessors['trex'] = function() { | ||
this._procFullBox(); | ||
this._procField('track_ID', 'uint', 32); | ||
this._procField('default_sample_description_index', 'uint', 32); | ||
this._procField('default_sample_duration', 'uint', 32); | ||
this._procField('default_sample_size', 'uint', 32); | ||
this._procField('default_sample_flags', 'uint', 32); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.8.3 Track Extends Box | ||
ISOBox.prototype._boxParsers['trex'] = function() { | ||
this._parseFullBox(); | ||
this.track_ID = this._readUint(32); | ||
this.default_sample_description_index = this._readUint(32); | ||
this.default_sample_duration = this._readUint(32); | ||
this.default_sample_size = this._readUint(32); | ||
this.default_sample_flags = this._readUint(32); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.8.8 Track Run Box | ||
// Note: the 'trun' box has a direct relation to the 'tfhd' box for defaults. | ||
// These defaults are not set explicitly here, but are left to resolve for the user. | ||
ISOBox.prototype._boxParsers['trun'] = function() { | ||
this._parseFullBox(); | ||
this.sample_count = this._readUint(32); | ||
if (this.flags & 0x1) this.data_offset = this._readInt(32); | ||
if (this.flags & 0x4) this.first_sample_flags = this._readUint(32); | ||
this.samples = []; | ||
for (var i=0; i<this.sample_count; i++) { | ||
var sample = {}; | ||
if (this.flags & 0x100) sample.sample_duration = this._readUint(32); | ||
if (this.flags & 0x200) sample.sample_size = this._readUint(32); | ||
if (this.flags & 0x400) sample.sample_flags = this._readUint(32); | ||
if (this.flags & 0x800) { | ||
if (this.version === 0) { | ||
sample.sample_composition_time_offset = this._readUint(32); | ||
} else { | ||
sample.sample_composition_time_offset = this._readInt(32); | ||
} | ||
} | ||
this.samples.push(sample); | ||
} | ||
ISOBox.prototype._boxProcessors['trun'] = function() { | ||
this._procFullBox(); | ||
this._procField('sample_count', 'uint', 32); | ||
if (this.flags & 0x1) this._procField('data_offset', 'int', 32); | ||
if (this.flags & 0x4) this._procField('first_sample_flags', 'uint', 32); | ||
this._procEntries('samples', this.sample_count, function(sample) { | ||
if (this.flags & 0x100) this._procEntryField(sample, 'sample_duration', 'uint', 32); | ||
if (this.flags & 0x200) this._procEntryField(sample, 'sample_size', 'uint', 32); | ||
if (this.flags & 0x400) this._procEntryField(sample, 'sample_flags', 'uint', 32); | ||
if (this.flags & 0x800) this._procEntryField(sample, 'sample_composition_time_offset', (this.version === 1) ? 'int' : 'uint', 32); | ||
}); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.7.2 Data Reference Box | ||
ISOBox.prototype._boxParsers['url '] = ISOBox.prototype._boxParsers['urn '] = function() { | ||
this._parseFullBox(); | ||
ISOBox.prototype._boxProcessors['url '] = ISOBox.prototype._boxProcessors['urn '] = function() { | ||
this._procFullBox(); | ||
if (this.type === 'urn ') { | ||
this.name = this._readTerminatedString(); | ||
this._procField('name', 'string', -1); | ||
} | ||
this.location = this._readTerminatedString(); | ||
this._procField('location', 'string', -1); | ||
}; | ||
// ISO/IEC 14496-30:2014 - WebVTT Source Label Box | ||
ISOBox.prototype._boxParsers['vlab'] = function() { | ||
var source_label_raw = new DataView(this._raw.buffer, this._cursor.offset, this._raw.byteLength - (this._cursor.offset - this._offset)); | ||
this.source_label = ISOBoxer.Utils.dataViewToString(source_label_raw); | ||
ISOBox.prototype._boxProcessors['vlab'] = function() { | ||
this._procField('source_label', 'utf8'); | ||
}; | ||
// ISO/IEC 14496-12:2012 - 8.4.5.2 Video Media Header Box | ||
ISOBox.prototype._boxParsers['vmhd'] = function() { | ||
this._parseFullBox(); | ||
this.graphicsmode = this._readUint(16); | ||
this.opcolor = [this._readUint(16), this._readUint(16), this._readUint(16)]; | ||
ISOBox.prototype._boxProcessors['vmhd'] = function() { | ||
this._procFullBox(); | ||
this._procField('graphicsmode', 'uint', 16); | ||
this._procFieldArray('opcolor', 3, 'uint', 16); | ||
}; | ||
// ISO/IEC 14496-30:2014 - WebVTT Configuration Box | ||
ISOBox.prototype._boxParsers['vttC'] = function() { | ||
var config_raw = new DataView(this._raw.buffer, this._cursor.offset, this._raw.byteLength - (this._cursor.offset - this._offset)); | ||
this.config = ISOBoxer.Utils.dataViewToString(config_raw); | ||
ISOBox.prototype._boxProcessors['vttC'] = function() { | ||
this._procField('config', 'utf8'); | ||
}; | ||
// ISO/IEC 14496-30:2014 - WebVTT Empty Sample Box | ||
ISOBox.prototype._boxParsers['vtte'] = function() { | ||
ISOBox.prototype._boxProcessors['vtte'] = function() { | ||
// Nothing should happen here. | ||
}; |
@@ -1,2 +0,2 @@ | ||
/*! codem-isoboxer v0.2.10 https://github.com/madebyhiro/codem-isoboxer/blob/master/LICENSE.txt */ | ||
var ISOBoxer={};ISOBoxer.parseBuffer=function(a){return new ISOFile(a).parse()},ISOBoxer.addBoxParser=function(a,b){"string"==typeof a&&"function"==typeof b&&(ISOBox.prototype._boxParsers[a]=b)},ISOBoxer.Utils={},ISOBoxer.Utils.dataViewToString=function(a,b){var c=b||"utf-8";if("undefined"!=typeof TextDecoder)return new TextDecoder(c).decode(a);var d=[],e=0;if("utf-8"===c)for(;e<a.byteLength;){var f=a.getUint8(e++);f<128||(f<224?(f=(31&f)<<6,f|=63&a.getUint8(e++)):f<240?(f=(15&f)<<12,f|=(63&a.getUint8(e++))<<6,f|=63&a.getUint8(e++)):(f=(7&f)<<18,f|=(63&a.getUint8(e++))<<12,f|=(63&a.getUint8(e++))<<6,f|=63&a.getUint8(e++))),d.push(String.fromCharCode(f))}else for(;e<a.byteLength;)d.push(String.fromCharCode(a.getUint8(e++)));return d.join("")},"undefined"!=typeof exports&&(exports.parseBuffer=ISOBoxer.parseBuffer,exports.addBoxParser=ISOBoxer.addBoxParser,exports.Utils=ISOBoxer.Utils),ISOBoxer.Cursor=function(a){this.offset="undefined"==typeof a?0:a};var ISOFile=function(a){this._raw=new DataView(a),this._cursor=new ISOBoxer.Cursor,this.boxes=[]};ISOFile.prototype.fetch=function(a){var b=this.fetchAll(a,!0);return b.length?b[0]:null},ISOFile.prototype.fetchAll=function(a,b){var c=[];return ISOFile._sweep.call(this,a,c,b),c},ISOFile.prototype.parse=function(){for(this._cursor.offset=0,this.boxes=[];this._cursor.offset<this._raw.byteLength;){var a=ISOBox.parse(this);if("undefined"==typeof a.type)break;this.boxes.push(a)}return this},ISOFile._sweep=function(a,b,c){this.type&&this.type==a&&b.push(this);for(var d in this.boxes){if(b.length&&c)return;ISOFile._sweep.call(this.boxes[d],a,b,c)}};var ISOBox=function(){this._cursor=new ISOBoxer.Cursor};ISOBox.parse=function(a){var b=new ISOBox;return b._offset=a._cursor.offset,b._root=a._root?a._root:a,b._raw=a._raw,b._parent=a,b._parseBox(),a._cursor.offset=b._raw.byteOffset+b._raw.byteLength,b},ISOBox.prototype._readInt=function(a){var b=null;switch(a){case 8:b=this._raw.getInt8(this._cursor.offset-this._raw.byteOffset);break;case 16:b=this._raw.getInt16(this._cursor.offset-this._raw.byteOffset);break;case 32:b=this._raw.getInt32(this._cursor.offset-this._raw.byteOffset);break;case 64:var c=this._raw.getInt32(this._cursor.offset-this._raw.byteOffset),d=this._raw.getInt32(this._cursor.offset-this._raw.byteOffset+4);b=c*Math.pow(2,32)+d}return this._cursor.offset+=a>>3,b},ISOBox.prototype._readUint=function(a){var b,c,d=null;switch(a){case 8:d=this._raw.getUint8(this._cursor.offset-this._raw.byteOffset);break;case 16:d=this._raw.getUint16(this._cursor.offset-this._raw.byteOffset);break;case 24:b=this._raw.getUint16(this._cursor.offset-this._raw.byteOffset),c=this._raw.getUint8(this._cursor.offset-this._raw.byteOffset+2),d=(b<<8)+c;break;case 32:d=this._raw.getUint32(this._cursor.offset-this._raw.byteOffset);break;case 64:b=this._raw.getUint32(this._cursor.offset-this._raw.byteOffset),c=this._raw.getUint32(this._cursor.offset-this._raw.byteOffset+4),d=b*Math.pow(2,32)+c}return this._cursor.offset+=a>>3,d},ISOBox.prototype._readString=function(a){for(var b="",c=0;c<a;c++){var d=this._readUint(8);b+=String.fromCharCode(d)}return b},ISOBox.prototype._readTerminatedString=function(){for(var a="";this._cursor.offset-this._offset<this._raw.byteLength;){var b=this._readUint(8);if(0===b)break;a+=String.fromCharCode(b)}return a},ISOBox.prototype._readTemplate=function(a){var b=this._readUint(a/2),c=this._readUint(a/2);return b+c/Math.pow(2,a/2)},ISOBox.prototype._readData=function(a){var b=a>0?a:this._raw.byteLength-(this._cursor.offset-this._offset),c=new DataView(this._raw.buffer,this._cursor.offset,b);return this._cursor.offset+=b,c},ISOBox.prototype._parseBox=function(){if(this._cursor.offset=this._offset,this._offset+8>this._raw.buffer.byteLength)return void(this._root._incomplete=!0);switch(this.size=this._readUint(32),this.type=this._readString(4),1==this.size&&(this.largesize=this._readUint(64)),"uuid"==this.type&&(this.usertype=this._readString(16)),this.size){case 0:this._raw=new DataView(this._raw.buffer,this._offset,this._raw.byteLength-this._cursor.offset);break;case 1:this._offset+this.size>this._raw.buffer.byteLength?(this._incomplete=!0,this._root._incomplete=!0):this._raw=new DataView(this._raw.buffer,this._offset,this.largesize);break;default:this._offset+this.size>this._raw.buffer.byteLength?(this._incomplete=!0,this._root._incomplete=!0):this._raw=new DataView(this._raw.buffer,this._offset,this.size)}this._incomplete||(this._boxContainers.indexOf(this.type)!==-1?this._parseContainerBox():this._boxParsers[this.type]&&this._boxParsers[this.type].call(this))},ISOBox.prototype._parseFullBox=function(){this.version=this._readUint(8),this.flags=this._readUint(24)},ISOBox.prototype._parseContainerBox=function(){for(this.boxes=[];this._cursor.offset-this._raw.byteOffset<this._raw.byteLength;)this.boxes.push(ISOBox.parse(this))},ISOBox.prototype._boxContainers=["dinf","edts","mdia","meco","mfra","minf","moof","moov","mvex","stbl","strk","traf","trak","tref","udta","vttc"],ISOBox.prototype._boxParsers={},ISOBox.prototype._boxParsers.avc1=function(){this.reserved1=[this._readUint(8),this._readUint(8),this._readUint(8),this._readUint(8),this._readUint(8),this._readUint(8)],this.data_reference_index=this._readUint(16),this.pre_defined1=this._readUint(16),this.reserved2=this._readUint(16),this.pre_defined2=[this._readUint(32),this._readUint(32),this._readUint(32)],this.width=this._readUint(16),this.height=this._readUint(16),this.horizresolution=this._readTemplate(32),this.vertresolution=this._readTemplate(32),this.reserved3=this._readUint(32),this.frame_count=this._readUint(16);var a=this._readUint(8);this.compressorname=this._readString(a);for(var b=0;b<31-a;b++)this._readUint(8);this.depth=this._readUint(16),this.pre_defined3=this._readInt(16),this.config=this._readData()},ISOBox.prototype._boxParsers.dref=function(){this._parseFullBox(),this.entry_count=this._readUint(32),this.entries=[];for(var a=0;a<this.entry_count;a++)this.entries.push(ISOBox.parse(this))},ISOBox.prototype._boxParsers.elst=function(){this._parseFullBox(),this.entry_count=this._readUint(32),this.entries=[];for(var a=1;a<=this.entry_count;a++){var b={};1==this.version?(b.segment_duration=this._readUint(64),b.media_time=this._readInt(64)):(b.segment_duration=this._readUint(32),b.media_time=this._readInt(32)),b.media_rate_integer=this._readInt(16),b.media_rate_fraction=this._readInt(16),this.entries.push(b)}},ISOBox.prototype._boxParsers.emsg=function(){this._parseFullBox(),this.scheme_id_uri=this._readTerminatedString(),this.value=this._readTerminatedString(),this.timescale=this._readUint(32),this.presentation_time_delta=this._readUint(32),this.event_duration=this._readUint(32),this.id=this._readUint(32),this.message_data=new DataView(this._raw.buffer,this._cursor.offset,this._raw.byteLength-(this._cursor.offset-this._offset))},ISOBox.prototype._boxParsers.free=ISOBox.prototype._boxParsers.skip=function(){this.data=new DataView(this._raw.buffer,this._cursor.offset,this._raw.byteLength-(this._cursor.offset-this._offset))},ISOBox.prototype._boxParsers.ftyp=ISOBox.prototype._boxParsers.styp=function(){for(this.major_brand=this._readString(4),this.minor_version=this._readUint(32),this.compatible_brands=[];this._cursor.offset-this._raw.byteOffset<this._raw.byteLength;)this.compatible_brands.push(this._readString(4))},ISOBox.prototype._boxParsers.hdlr=function(){this._parseFullBox(),this.pre_defined=this._readUint(32),this.handler_type=this._readString(4),this.reserved=[this._readUint(32),this._readUint(32),this._readUint(32)],this.name=this._readTerminatedString()},ISOBox.prototype._boxParsers.mdat=function(){this.data=this._readData()},ISOBox.prototype._boxParsers.mdhd=function(){this._parseFullBox(),1==this.version?(this.creation_time=this._readUint(64),this.modification_time=this._readUint(64),this.timescale=this._readUint(32),this.duration=this._readUint(64)):(this.creation_time=this._readUint(32),this.modification_time=this._readUint(32),this.timescale=this._readUint(32),this.duration=this._readUint(32));var a=this._readUint(16);this.pad=a>>15,this.language=String.fromCharCode((a>>10&31)+96,(a>>5&31)+96,(31&a)+96),this.pre_defined=this._readUint(16)},ISOBox.prototype._boxParsers.mehd=function(){this._parseFullBox(),1==this.version?this.fragment_duration=this._readUint(64):this.fragment_duration=this._readUint(32)},ISOBox.prototype._boxParsers.mfhd=function(){this._parseFullBox(),this.sequence_number=this._readUint(32)},ISOBox.prototype._boxParsers.mfro=function(){this._parseFullBox(),this.mfra_size=this._readUint(32)},ISOBox.prototype._boxParsers.mp4a=function(){this.reserved1=[this._readUint(8),this._readUint(8),this._readUint(8),this._readUint(8),this._readUint(8),this._readUint(8)],this.data_reference_index=this._readUint(16),this.reserved2=[this._readUint(32),this._readUint(32)],this.channelcount=this._readUint(16),this.samplesize=this._readUint(16),this.pre_defined=this._readUint(16),this.reserved3=this._readUint(16),this.samplerate=this._readTemplate(32),this.esds=this._readData()},ISOBox.prototype._boxParsers.mvhd=function(){this._parseFullBox();var a;for(1==this.version?(this.creation_time=this._readUint(64),this.modification_time=this._readUint(64),this.timescale=this._readUint(32),this.duration=this._readUint(64)):(this.creation_time=this._readUint(32),this.modification_time=this._readUint(32),this.timescale=this._readUint(32),this.duration=this._readUint(32)),this.rate=this._readTemplate(32),this.volume=this._readTemplate(16),this.reserved1=this._readUint(16),this.reserved2=[this._readUint(32),this._readUint(32)],this.matrix=[],a=0;a<9;a++)this.matrix.push(this._readTemplate(32));for(this.pre_defined=[],a=0;a<6;a++)this.pre_defined.push(this._readUint(32));this.next_track_ID=this._readUint(32)},ISOBox.prototype._boxParsers.payl=function(){var a=new DataView(this._raw.buffer,this._cursor.offset,this._raw.byteLength-(this._cursor.offset-this._offset));this.cue_text=ISOBoxer.Utils.dataViewToString(a)},ISOBox.prototype._boxParsers.sidx=function(){this._parseFullBox(),this.reference_ID=this._readUint(32),this.timescale=this._readUint(32),0===this.version?(this.earliest_presentation_time=this._readUint(32),this.first_offset=this._readUint(32)):(this.earliest_presentation_time=this._readUint(64),this.first_offset=this._readUint(64)),this.reserved=this._readUint(16),this.reference_count=this._readUint(16),this.references=[];for(var a=0;a<this.reference_count;a++){var b={},c=this._readUint(32);b.reference_type=c>>31&1,b.referenced_size=2147483647&c,b.subsegment_duration=this._readUint(32);var d=this._readUint(32);b.starts_with_SAP=d>>31&1,b.SAP_type=d>>28&7,b.SAP_delta_time=268435455&d,this.references.push(b)}},ISOBox.prototype._boxParsers.smhd=function(){this._parseFullBox(),this.balance=this._readTemplate(16),this.reserved=this._readUint(16)},ISOBox.prototype._boxParsers.ssix=function(){this._parseFullBox(),this.subsegment_count=this._readUint(32),this.subsegments=[];for(var a=0;a<this.subsegment_count;a++){var b={};b.ranges_count=this._readUint(32),b.ranges=[];for(var c=0;c<b.ranges_count;c++){var d={};d.level=this._readUint(8),d.range_size=this._readUint(24),b.ranges.push(d)}this.subsegments.push(b)}},ISOBox.prototype._boxParsers.stsd=function(){this._parseFullBox(),this.entry_count=this._readUint(32),this.entries=[];for(var a=0;a<this.entry_count;a++)this.entries.push(ISOBox.parse(this))},ISOBox.prototype._boxParsers.subs=function(){this._parseFullBox(),this.entry_count=this._readUint(32),this.entries=[];for(var a=0;a<this.entry_count;a++){var b={};b.sample_delta=this._readUint(32),b.subsample_count=this._readUint(16),b.subsamples=[];for(var c=0;c<b.subsample_count;c++){var d={};1&this.version?d.subsample_size=this._readUint(32):d.subsample_size=this._readUint(16),d.subsample_priority=this._readUint(8),d.discardable=this._readUint(8),d.codec_specific_parameters=this._readUint(32),b.subsamples.push(d)}this.entries.push(b)}},ISOBox.prototype._boxParsers.tfdt=function(){this._parseFullBox(),1==this.version?this.baseMediaDecodeTime=this._readUint(64):this.baseMediaDecodeTime=this._readUint(32)},ISOBox.prototype._boxParsers.tfhd=function(){this._parseFullBox(),this.track_ID=this._readUint(32),1&this.flags&&(this.base_data_offset=this._readUint(64)),2&this.flags&&(this.sample_description_offset=this._readUint(32)),8&this.flags&&(this.default_sample_duration=this._readUint(32)),16&this.flags&&(this.default_sample_size=this._readUint(32)),32&this.flags&&(this.default_sample_flags=this._readUint(32))},ISOBox.prototype._boxParsers.tfra=function(){this._parseFullBox(),this.track_ID=this._readUint(32),this._packed=this._readUint(32),this.reserved=this._packed>>>6,this.length_size_of_traf_num=(this._packed&&0xffff00000000)>>>4,this.length_size_of_trun_num=(this._packed&&4294901760)>>>2,this.length_size_of_sample_num=this._packed&&255,this.number_of_entry=this._readUint(32),this.entries=[];for(var a=0;a<this.number_of_entry;a++){var b={};1==this.version?(b.time=this._readUint(64),b.moof_offset=this._readUint(64)):(b.time=this._readUint(32),b.moof_offset=this._readUint(32)),b.traf_number=this._readUint(8*(this.length_size_of_traf_num+1)),b.trun_number=this._readUint(8*(this.length_size_of_trun_num+1)),b.sample_number=this._readUint(8*(this.length_size_of_sample_num+1)),this.entries.push(b)}},ISOBox.prototype._boxParsers.tkhd=function(){this._parseFullBox(),1==this.version?(this.creation_time=this._readUint(64),this.modification_time=this._readUint(64),this.track_ID=this._readUint(32),this.reserved1=this._readUint(32),this.duration=this._readUint(64)):(this.creation_time=this._readUint(32),this.modification_time=this._readUint(32),this.track_ID=this._readUint(32),this.reserved1=this._readUint(32),this.duration=this._readUint(32)),this.reserved2=[this._readUint(32),this._readUint(32)],this.layer=this._readUint(16),this.alternate_group=this._readUint(16),this.volume=this._readTemplate(16),this.reserved3=this._readUint(16),this.matrix=[];for(var a=0;a<9;a++)this.matrix.push(this._readTemplate(32));this.width=this._readTemplate(32),this.height=this._readTemplate(32)},ISOBox.prototype._boxParsers.trex=function(){this._parseFullBox(),this.track_ID=this._readUint(32),this.default_sample_description_index=this._readUint(32),this.default_sample_duration=this._readUint(32),this.default_sample_size=this._readUint(32),this.default_sample_flags=this._readUint(32)},ISOBox.prototype._boxParsers.trun=function(){this._parseFullBox(),this.sample_count=this._readUint(32),1&this.flags&&(this.data_offset=this._readInt(32)),4&this.flags&&(this.first_sample_flags=this._readUint(32)),this.samples=[];for(var a=0;a<this.sample_count;a++){var b={};256&this.flags&&(b.sample_duration=this._readUint(32)),512&this.flags&&(b.sample_size=this._readUint(32)),1024&this.flags&&(b.sample_flags=this._readUint(32)),2048&this.flags&&(0===this.version?b.sample_composition_time_offset=this._readUint(32):b.sample_composition_time_offset=this._readInt(32)),this.samples.push(b)}},ISOBox.prototype._boxParsers["url "]=ISOBox.prototype._boxParsers["urn "]=function(){this._parseFullBox(),"urn "===this.type&&(this.name=this._readTerminatedString()),this.location=this._readTerminatedString()},ISOBox.prototype._boxParsers.vlab=function(){var a=new DataView(this._raw.buffer,this._cursor.offset,this._raw.byteLength-(this._cursor.offset-this._offset));this.source_label=ISOBoxer.Utils.dataViewToString(a)},ISOBox.prototype._boxParsers.vmhd=function(){this._parseFullBox(),this.graphicsmode=this._readUint(16),this.opcolor=[this._readUint(16),this._readUint(16),this._readUint(16)]},ISOBox.prototype._boxParsers.vttC=function(){var a=new DataView(this._raw.buffer,this._cursor.offset,this._raw.byteLength-(this._cursor.offset-this._offset));this.config=ISOBoxer.Utils.dataViewToString(a)},ISOBox.prototype._boxParsers.vtte=function(){}; | ||
/*! codem-isoboxer v0.3.0 https://github.com/madebyhiro/codem-isoboxer/blob/master/LICENSE.txt */ | ||
var ISOBoxer={};ISOBoxer.parseBuffer=function(a){return new ISOFile(a).parse()},ISOBoxer.addBoxProcessor=function(a,b){"string"==typeof a&&"function"==typeof b&&(ISOBox.prototype._boxProcessors[a]=b)},ISOBoxer.createFile=function(){return new ISOFile},ISOBoxer.createBox=function(a,b,c){var d=ISOBox.create(a);return b&&b.append(d,c),d},ISOBoxer.createFullBox=function(a,b,c){var d=ISOBoxer.createBox(a,b,c);return d.version=0,d.flags=0,d},ISOBoxer.Utils={},ISOBoxer.Utils.dataViewToString=function(a,b){var c=b||"utf-8";if("undefined"!=typeof TextDecoder)return new TextDecoder(c).decode(a);var d=[],e=0;if("utf-8"===c)for(;e<a.byteLength;){var f=a.getUint8(e++);f<128||(f<224?(f=(31&f)<<6,f|=63&a.getUint8(e++)):f<240?(f=(15&f)<<12,f|=(63&a.getUint8(e++))<<6,f|=63&a.getUint8(e++)):(f=(7&f)<<18,f|=(63&a.getUint8(e++))<<12,f|=(63&a.getUint8(e++))<<6,f|=63&a.getUint8(e++))),d.push(String.fromCharCode(f))}else for(;e<a.byteLength;)d.push(String.fromCharCode(a.getUint8(e++)));return d.join("")},ISOBoxer.Utils.utf8ToByteArray=function(a){var b,c;if("undefined"!=typeof TextEncoder)b=(new TextEncoder).encode(a);else for(b=[],c=0;c<a.length;++c){var d=a.charCodeAt(c);d<128?b.push(d):d<2048?(b.push(192|d>>6),b.push(128|63&d)):d<65536?(b.push(224|d>>12),b.push(128|63&d>>6),b.push(128|63&d)):(b.push(240|d>>18),b.push(128|63&d>>12),b.push(128|63&d>>6),b.push(128|63&d))}return b},ISOBoxer.Utils.appendBox=function(a,b,c){if(b._offset=a._cursor.offset,b._root=a._root?a._root:a,b._raw=a._raw,b._parent=a,c!==-1){if(void 0===c||null===c)return void a.boxes.push(b);var d,e=-1;if("number"==typeof c)e=c;else{if("string"==typeof c)d=c;else{if("object"!=typeof c||!c.type)return void a.boxes.push(b);d=c.type}for(var f=0;f<a.boxes.length;f++)if(d===a.boxes[f].type){e=f+1;break}}a.boxes.splice(e,0,b)}},"undefined"!=typeof exports&&(exports.parseBuffer=ISOBoxer.parseBuffer,exports.addBoxProcessor=ISOBoxer.addBoxProcessor,exports.createFile=ISOBoxer.createFile,exports.createBox=ISOBoxer.createBox,exports.createFullBox=ISOBoxer.createFullBox,exports.Utils=ISOBoxer.Utils),ISOBoxer.Cursor=function(a){this.offset="undefined"==typeof a?0:a};var ISOFile=function(a){this._cursor=new ISOBoxer.Cursor,this.boxes=[],a&&(this._raw=new DataView(a))};ISOFile.prototype.fetch=function(a){var b=this.fetchAll(a,!0);return b.length?b[0]:null},ISOFile.prototype.fetchAll=function(a,b){var c=[];return ISOFile._sweep.call(this,a,c,b),c},ISOFile.prototype.parse=function(){for(this._cursor.offset=0,this.boxes=[];this._cursor.offset<this._raw.byteLength;){var a=ISOBox.parse(this);if("undefined"==typeof a.type)break;this.boxes.push(a)}return this},ISOFile._sweep=function(a,b,c){this.type&&this.type==a&&b.push(this);for(var d in this.boxes){if(b.length&&c)return;ISOFile._sweep.call(this.boxes[d],a,b,c)}},ISOFile.prototype.write=function(){var a,b=0;for(a=0;a<this.boxes.length;a++)b+=this.boxes[a].getLength(!1);var c=new Uint8Array(b);for(this._rawo=new DataView(c.buffer),this.bytes=c,this._cursor.offset=0,a=0;a<this.boxes.length;a++)this.boxes[a].write();return c.buffer},ISOFile.prototype.append=function(a,b){ISOBoxer.Utils.appendBox(this,a,b)};var ISOBox=function(){this._cursor=new ISOBoxer.Cursor};ISOBox.parse=function(a){var b=new ISOBox;return b._offset=a._cursor.offset,b._root=a._root?a._root:a,b._raw=a._raw,b._parent=a,b._parseBox(),a._cursor.offset=b._raw.byteOffset+b._raw.byteLength,b},ISOBox.create=function(a){var b=new ISOBox;return b.type=a,b.boxes=[],b},ISOBox.prototype._boxContainers=["dinf","edts","mdia","meco","mfra","minf","moof","moov","mvex","stbl","strk","traf","trak","tref","udta","vttc","sinf","schi","encv","enca"],ISOBox.prototype._boxProcessors={},ISOBox.prototype._procField=function(a,b,c){this._parsing?this[a]=this._readField(b,c):this._writeField(b,c,this[a])},ISOBox.prototype._procFieldArray=function(a,b,c,d){var e;if(this._parsing)for(this[a]=[],e=0;e<b;e++)this[a][e]=this._readField(c,d);else for(e=0;e<this[a].length;e++)this._writeField(c,d,this[a][e])},ISOBox.prototype._procFullBox=function(){this._procField("version","uint",8),this._procField("flags","uint",24)},ISOBox.prototype._procEntries=function(a,b,c){var d;if(this._parsing)for(this[a]=[],d=0;d<b;d++)this[a].push({}),c.call(this,this[a][d]);else for(d=0;d<b;d++)c.call(this,this[a][d])},ISOBox.prototype._procSubEntries=function(a,b,c,d){var e;if(this._parsing)for(a[b]=[],e=0;e<c;e++)a[b].push({}),d.call(this,a[b][e]);else for(e=0;e<c;e++)d.call(this,a[b][e])},ISOBox.prototype._procEntryField=function(a,b,c,d){this._parsing?a[b]=this._readField(c,d):this._writeField(c,d,a[b])},ISOBox.prototype._procSubBoxes=function(a,b){var c;if(this._parsing)for(this[a]=[],c=0;c<b;c++)this[a].push(ISOBox.parse(this));else for(c=0;c<b;c++)this._rawo?this[a][c].write():this.size+=this[a][c].getLength()},ISOBox.prototype._readField=function(a,b){switch(a){case"uint":return this._readUint(b);case"int":return this._readInt(b);case"template":return this._readTemplate(b);case"string":return b===-1?this._readTerminatedString():this._readString(b);case"data":return this._readData(b);case"utf8":return this._readUTF8String();default:return-1}},ISOBox.prototype._readInt=function(a){var b=null,c=this._cursor.offset-this._raw.byteOffset;switch(a){case 8:b=this._raw.getInt8(c);break;case 16:b=this._raw.getInt16(c);break;case 32:b=this._raw.getInt32(c);break;case 64:var d=this._raw.getInt32(c),e=this._raw.getInt32(c+4);b=d*Math.pow(2,32)+e}return this._cursor.offset+=a>>3,b},ISOBox.prototype._readUint=function(a){var b,c,d=null,e=this._cursor.offset-this._raw.byteOffset;switch(a){case 8:d=this._raw.getUint8(e);break;case 16:d=this._raw.getUint16(e);break;case 24:b=this._raw.getUint16(e),c=this._raw.getUint8(e+2),d=(b<<8)+c;break;case 32:d=this._raw.getUint32(e);break;case 64:b=this._raw.getUint32(e),c=this._raw.getUint32(e+4),d=b*Math.pow(2,32)+c}return this._cursor.offset+=a>>3,d},ISOBox.prototype._readString=function(a){for(var b="",c=0;c<a;c++){var d=this._readUint(8);b+=String.fromCharCode(d)}return b},ISOBox.prototype._readTemplate=function(a){var b=this._readUint(a/2),c=this._readUint(a/2);return b+c/Math.pow(2,a/2)},ISOBox.prototype._readTerminatedString=function(){for(var a="";this._cursor.offset-this._offset<this._raw.byteLength;){var b=this._readUint(8);if(0===b)break;a+=String.fromCharCode(b)}return a},ISOBox.prototype._readData=function(a){var b=a>0?a:this._raw.byteLength-(this._cursor.offset-this._offset),c=new DataView(this._raw.buffer,this._cursor.offset,b);return this._cursor.offset+=b,c},ISOBox.prototype._readUTF8String=function(){var a=this._readData();return ISOBoxer.Utils.dataViewToString(a)},ISOBox.prototype._parseBox=function(){if(this._parsing=!0,this._cursor.offset=this._offset,this._offset+8>this._raw.buffer.byteLength)return void(this._root._incomplete=!0);switch(this._procField("size","uint",32),this._procField("type","string",4),1===this.size&&this._procField("largesize","uint",64),"uuid"===this.type&&this._procFieldArray("usertype",16,"uint",8),this.size){case 0:this._raw=new DataView(this._raw.buffer,this._offset,this._raw.byteLength-this._cursor.offset);break;case 1:this._offset+this.size>this._raw.buffer.byteLength?(this._incomplete=!0,this._root._incomplete=!0):this._raw=new DataView(this._raw.buffer,this._offset,this.largesize);break;default:this._offset+this.size>this._raw.buffer.byteLength?(this._incomplete=!0,this._root._incomplete=!0):this._raw=new DataView(this._raw.buffer,this._offset,this.size)}this._incomplete||(this._boxProcessors[this.type]&&this._boxProcessors[this.type].call(this),this._boxContainers.indexOf(this.type)!==-1?this._parseContainerBox():this._data=this._readData())},ISOBox.prototype._parseFullBox=function(){this.version=this._readUint(8),this.flags=this._readUint(24)},ISOBox.prototype._parseContainerBox=function(){for(this.boxes=[];this._cursor.offset-this._raw.byteOffset<this._raw.byteLength;)this.boxes.push(ISOBox.parse(this))},ISOBox.prototype.append=function(a,b){ISOBoxer.Utils.appendBox(this,a,b)},ISOBox.prototype.getLength=function(){if(this._parsing=!1,this._rawo=null,this.size=0,this._procField("size","uint",32),this._procField("type","string",4),1===this.size&&this._procField("largesize","uint",64),"uuid"===this.type&&this._procFieldArray("usertype",16,"uint",8),this._boxProcessors[this.type]&&this._boxProcessors[this.type].call(this),this._boxContainers.indexOf(this.type)!==-1)for(var a=0;a<this.boxes.length;a++)this.size+=this.boxes[a].getLength();return this._data&&this._writeData(this._data),this.size},ISOBox.prototype.write=function(){switch(this._parsing=!1,this._cursor.offset=this._parent._cursor.offset,this.size){case 0:this._rawo=new DataView(this._parent._rawo.buffer,this._cursor.offset,this.parent._rawo.byteLength-this._cursor.offset);break;case 1:this._rawo=new DataView(this._parent._rawo.buffer,this._cursor.offset,this.largesize);break;default:this._rawo=new DataView(this._parent._rawo.buffer,this._cursor.offset,this.size)}if(this._procField("size","uint",32),this._procField("type","string",4),1===this.size&&this._procField("largesize","uint",64),"uuid"===this.type&&this._procFieldArray("usertype",16,"uint",8),this._boxProcessors[this.type]&&this._boxProcessors[this.type].call(this),this._boxContainers.indexOf(this.type)!==-1)for(var a=0;a<this.boxes.length;a++)this.boxes[a].write();return this._data&&this._writeData(this._data),this._parent._cursor.offset+=this.size,this.size},ISOBox.prototype._writeInt=function(a,b){if(this._rawo){var c=this._cursor.offset-this._rawo.byteOffset;switch(a){case 8:this._rawo.setInt8(c,b);break;case 16:this._rawo.setInt16(c,b);break;case 32:this._rawo.setInt32(c,b);break;case 64:var d=Math.round(b/Math.pow(2,32)),e=b-d*Math.pow(2,32);this._rawo.setUint32(c,d),this._rawo.setUint32(c+4,e)}this._cursor.offset+=a>>3}else this.size+=a>>3},ISOBox.prototype._writeUint=function(a,b){if(this._rawo){var c,d,e=this._cursor.offset-this._rawo.byteOffset;switch(a){case 8:this._rawo.setUint8(e,b);break;case 16:this._rawo.setUint16(e,b);break;case 24:c=(16776960&b)>>8,d=255&b,this._rawo.setUint16(e,c),this._rawo.setUint8(e+2,d);break;case 32:this._rawo.setUint32(e,b);break;case 64:c=Math.round(b/Math.pow(2,32)),d=b-c*Math.pow(2,32),this._rawo.setUint32(e,c),this._rawo.setUint32(e+4,d)}this._cursor.offset+=a>>3}else this.size+=a>>3},ISOBox.prototype._writeString=function(a,b){for(var c=0;c<a;c++)this._writeUint(8,b.charCodeAt(c))},ISOBox.prototype._writeTerminatedString=function(a){if(0!==a.length){for(var b=0;b<a.length;b++)this._writeUint(8,a.charCodeAt(b));this._writeUint(8,0)}},ISOBox.prototype._writeTemplate=function(a,b){var c=Math.round(b),d=(b-c)*Math.pow(2,a/2);this._writeUint(a/2,c),this._writeUint(a/2,d)},ISOBox.prototype._writeData=function(a){if(a instanceof Array&&(a=new DataView(Uint8Array.from(a).buffer)),a instanceof Uint8Array&&(a=new DataView(a.buffer)),this._rawo){for(var b=this._cursor.offset-this._rawo.byteOffset,c=0;c<a.byteLength;c++)this._rawo.setUint8(b+c,a.getUint8(c));this._cursor.offset+=a.byteLength}else this.size+=a.byteLength},ISOBox.prototype._writeUTF8String=function(a){var b=ISOBoxer.Utils.utf8ToByteArray(a);if(this._rawo)for(var c=new DataView(this._rawo.buffer,this._cursor.offset,b.length),d=0;d<b.length;d++)c.setUint8(d,b[d]);else this.size+=b.length},ISOBox.prototype._writeField=function(a,b,c){switch(a){case"uint":this._writeUint(b,c);break;case"int":this._writeInt(b,c);break;case"template":this._writeTemplate(b,c);break;case"string":b==-1?this._writeTerminatedString(c):this._writeString(b,c);break;case"data":this._writeData(c);break;case"utf8":this._writeUTF8String(c)}},ISOBox.prototype._boxProcessors.avc1=ISOBox.prototype._boxProcessors.encv=function(){this._procFieldArray("reserved1",6,"uint",8),this._procField("data_reference_index","uint",16),this._procField("pre_defined1","uint",16),this._procField("reserved2","uint",16),this._procFieldArray("pre_defined2",3,"uint",32),this._procField("width","uint",16),this._procField("height","uint",16),this._procField("horizresolution","template",32),this._procField("vertresolution","template",32),this._procField("reserved3","uint",32),this._procField("frame_count","uint",16),this._procFieldArray("compressorname",32,"uint",8),this._procField("depth","uint",16),this._procField("pre_defined3","int",16),this._procField("config","data",-1)},ISOBox.prototype._boxProcessors.dref=function(){this._procFullBox(),this._procField("entry_count","uint",32),this._procSubBoxes("entries",this.entry_count)},ISOBox.prototype._boxProcessors.elst=function(){this._procFullBox(),this._procField("entry_count","uint",32),this._procEntries("entries",this.entry_count,function(a){this._procEntryField(a,"segment_duration","uint",1===this.version?64:32),this._procEntryField(a,"media_time","int",1===this.version?64:32),this._procEntryField(a,"media_rate_integer","int",16),this._procEntryField(a,"media_rate_fraction","int",16)})},ISOBox.prototype._boxProcessors.emsg=function(){this._procFullBox(),this._procField("scheme_id_uri","string",-1),this._procField("value","string",-1),this._procField("timescale","uint",32),this._procField("presentation_time_delta","uint",32),this._procField("event_duration","uint",32),this._procField("id","uint",32),this._procField("message_data","data",-1)},ISOBox.prototype._boxProcessors.free=ISOBox.prototype._boxProcessors.skip=function(){this._procField("data","data",-1)},ISOBox.prototype._boxProcessors.frma=function(){this._procField("data_format","uint",32)},ISOBox.prototype._boxProcessors.ftyp=ISOBox.prototype._boxProcessors.styp=function(){this._procField("major_brand","string",4),this._procField("minor_version","uint",32);var a=-1;this._parsing&&(a=(this._raw.byteLength-(this._cursor.offset-this._raw.byteOffset))/4),this._procFieldArray("compatible_brands",a,"string",4)},ISOBox.prototype._boxProcessors.hdlr=function(){this._procFullBox(),this._procField("pre_defined","uint",32),this._procField("handler_type","string",4),this._procFieldArray("reserved",3,"uint",32),this._procField("name","string",-1)},ISOBox.prototype._boxProcessors.mdat=function(){this._procField("data","data",-1)},ISOBox.prototype._boxProcessors.mdhd=function(){this._procFullBox(),this._procField("creation_time","uint",1==this.version?64:32),this._procField("modification_time","uint",1==this.version?64:32),this._procField("timescale","uint",32),this._procField("duration","uint",1==this.version?64:32),this._parsing||"string"!=typeof this.language||(this.language=this.language.charCodeAt(0)-96<<10|this.language.charCodeAt(1)-96<<5|this.language.charCodeAt(2)-96),this._procField("language","uint",16),this._parsing&&(this.language=String.fromCharCode((this.language>>10&31)+96,(this.language>>5&31)+96,(31&this.language)+96)),this._procField("pre_defined","uint",16)},ISOBox.prototype._boxProcessors.mehd=function(){this._procFullBox(),this._procField("fragment_duration","uint",1==this.version?64:32)},ISOBox.prototype._boxProcessors.mfhd=function(){this._procFullBox(),this._procField("sequence_number","uint",32)},ISOBox.prototype._boxProcessors.mfro=function(){this._procFullBox(),this._procField("mfra_size","uint",32)},ISOBox.prototype._boxProcessors.mp4a=ISOBox.prototype._boxProcessors.enca=function(){this._procFieldArray("reserved1",6,"uint",8),this._procField("data_reference_index","uint",16),this._procFieldArray("reserved2",2,"uint",32),this._procField("channelcount","uint",16),this._procField("samplesize","uint",16),this._procField("pre_defined","uint",16),this._procField("reserved3","uint",16),this._procField("samplerate","template",32),this._procField("esds","data",-1)},ISOBox.prototype._boxProcessors.mvhd=function(){this._procFullBox(),this._procField("creation_time","uint",1==this.version?64:32),this._procField("modification_time","uint",1==this.version?64:32),this._procField("timescale","uint",32),this._procField("duration","uint",1==this.version?64:32),this._procField("rate","template",32),this._procField("volume","template",16),this._procField("reserved1","uint",16),this._procFieldArray("reserved2",2,"uint",32),this._procFieldArray("matrix",9,"template",32),this._procFieldArray("pre_defined",6,"uint",32),this._procField("next_track_ID","uint",32)},ISOBox.prototype._boxProcessors.payl=function(){this._procField("cue_text","utf8")},ISOBox.prototype._boxProcessors.pssh=function(){this._procFullBox(),this._procFieldArray("SystemID",16,"uint",8),this._procField("DataSize","uint",32),this._procFieldArray("Data",this.DataSize,"uint",8)},ISOBox.prototype._boxProcessors.schm=function(){this._procFullBox(),this._procField("scheme_type","uint",32),this._procField("scheme_version","uint",32),1&this.flags&&this._procField("scheme_uri","string",-1)},ISOBox.prototype._boxProcessors.sdtp=function(){this._procFullBox();var a=-1;this._parsing&&(a=this._raw.byteLength-(this._cursor.offset-this._raw.byteOffset)),this._procFieldArray("sample_dependency_table",a,"uint",8)},ISOBox.prototype._boxProcessors.sidx=function(){this._procFullBox(),this._procField("reference_ID","uint",32),this._procField("timescale","uint",32),this._procField("earliest_presentation_time","uint",1==this.version?64:32),this._procField("first_offset","uint",1==this.version?64:32),this._procField("reserved","uint",16),this._procField("reference_count","uint",16),this._procEntries("references",this.reference_count,function(a){this._parsing||(a.reference=(1&a.reference_type)<<31,a.reference|=2147483647&a.referenced_size,a.sap=(1&a.starts_with_SAP)<<31,a.sap|=(3&a.SAP_type)<<28,a.sap|=268435455&a.SAP_delta_time),this._procEntryField(a,"reference","uint",32),this._procEntryField(a,"subsegment_duration","uint",32),this._procEntryField(a,"sap","uint",32),this._parsing&&(a.reference_type=a.reference>>31&1,a.referenced_size=2147483647&a.reference,a.starts_with_SAP=a.sap>>31&1,a.SAP_type=a.sap>>28&7,a.SAP_delta_time=268435455&a.sap)})},ISOBox.prototype._boxProcessors.smhd=function(){this._procFullBox(),this._procField("balance","uint",16),this._procField("reserved","uint",16)},ISOBox.prototype._boxProcessors.ssix=function(){this._procFullBox(),this._procField("subsegment_count","uint",32),this._procEntries("subsegments",this.subsegment_count,function(a){this._procEntryField(a,"ranges_count","uint",32),this._procSubEntries(a,"ranges",a.ranges_count,function(a){this._procEntryField(a,"level","uint",8),this._procEntryField(a,"range_size","uint",24)})})},ISOBox.prototype._boxProcessors.stsd=function(){this._procFullBox(),this._procField("entry_count","uint",32),this._procSubBoxes("entries",this.entry_count)},ISOBox.prototype._boxProcessors.subs=function(){this._procFullBox(),this._procField("entry_count","uint",32),this._procEntries("entries",this.entry_count,function(a){this._procEntryField(a,"sample_delta","uint",32),this._procEntryField(a,"subsample_count","uint",16),this._procSubEntries(a,"subsamples",a.subsample_count,function(a){this._procEntryField(a,"subsample_size","uint",1===this.version?32:16),this._procEntryField(a,"subsample_priority","uint",8),this._procEntryField(a,"discardable","uint",8),this._procEntryField(a,"codec_specific_parameters","uint",32)})})},ISOBox.prototype._boxProcessors.tenc=function(){this._procFullBox(),this._procField("default_IsEncrypted","uint",24),this._procField("default_IV_size","uint",8),this._procFieldArray("default_KID",16,"uint",8)},ISOBox.prototype._boxProcessors.tfdt=function(){this._procFullBox(),this._procField("baseMediaDecodeTime","uint",1==this.version?64:32)},ISOBox.prototype._boxProcessors.tfhd=function(){this._procFullBox(),this._procField("track_ID","uint",32),1&this.flags&&this._procField("base_data_offset","uint",64),2&this.flags&&this._procField("sample_description_offset","uint",32),8&this.flags&&this._procField("default_sample_duration","uint",32),16&this.flags&&this._procField("default_sample_size","uint",32),32&this.flags&&this._procField("default_sample_flags","uint",32)},ISOBox.prototype._boxProcessors.tfra=function(){this._procFullBox(),this._procField("track_ID","uint",32),this._parsing||(this.reserved=0,this.reserved|=(48&this.length_size_of_traf_num)<<4,this.reserved|=(12&this.length_size_of_trun_num)<<2,this.reserved|=3&this.length_size_of_sample_num),this._procField("reserved","uint",32),this._parsing&&(this.length_size_of_traf_num=(48&this.reserved)>>4,this.length_size_of_trun_num=(12&this.reserved)>>2,this.length_size_of_sample_num=3&this.reserved),this._procField("number_of_entry","uint",32),this._procEntries("entries",this.number_of_entry,function(a){this._procEntryField(a,"time","uint",1===this.version?64:32),this._procEntryField(a,"moof_offset","uint",1===this.version?64:32),this._procEntryField(a,"traf_number","uint",8*(this.length_size_of_traf_num+1)),this._procEntryField(a,"trun_number","uint",8*(this.length_size_of_trun_num+1)),this._procEntryField(a,"sample_number","uint",8*(this.length_size_of_sample_num+1))})},ISOBox.prototype._boxProcessors.tkhd=function(){this._procFullBox(),this._procField("creation_time","uint",1==this.version?64:32),this._procField("modification_time","uint",1==this.version?64:32),this._procField("track_ID","uint",32),this._procField("reserved1","uint",32),this._procField("duration","uint",1==this.version?64:32),this._procFieldArray("reserved2",2,"uint",32),this._procField("layer","uint",16),this._procField("alternate_group","uint",16),this._procField("volume","template",16),this._procField("reserved3","uint",16),this._procFieldArray("matrix",9,"template",32),this._procField("width","template",32),this._procField("height","template",32)},ISOBox.prototype._boxProcessors.trex=function(){this._procFullBox(),this._procField("track_ID","uint",32),this._procField("default_sample_description_index","uint",32),this._procField("default_sample_duration","uint",32),this._procField("default_sample_size","uint",32),this._procField("default_sample_flags","uint",32)},ISOBox.prototype._boxProcessors.trun=function(){this._procFullBox(),this._procField("sample_count","uint",32),1&this.flags&&this._procField("data_offset","int",32),4&this.flags&&this._procField("first_sample_flags","uint",32),this._procEntries("samples",this.sample_count,function(a){256&this.flags&&this._procEntryField(a,"sample_duration","uint",32),512&this.flags&&this._procEntryField(a,"sample_size","uint",32),1024&this.flags&&this._procEntryField(a,"sample_flags","uint",32),2048&this.flags&&this._procEntryField(a,"sample_composition_time_offset",1===this.version?"int":"uint",32)})},ISOBox.prototype._boxProcessors["url "]=ISOBox.prototype._boxProcessors["urn "]=function(){this._procFullBox(),"urn "===this.type&&this._procField("name","string",-1),this._procField("location","string",-1)},ISOBox.prototype._boxProcessors.vlab=function(){this._procField("source_label","utf8")},ISOBox.prototype._boxProcessors.vmhd=function(){this._procFullBox(),this._procField("graphicsmode","uint",16),this._procFieldArray("opcolor",3,"uint",16)},ISOBox.prototype._boxProcessors.vttC=function(){this._procField("config","utf8")},ISOBox.prototype._boxProcessors.vtte=function(){}; |
module.exports = function(grunt) { | ||
var banner = '/*! <%= pkg.name %> v<%= pkg.version %> <%= licenseUrl %> */\n'; | ||
var boxes = grunt.option('boxes'); | ||
function includeWriteFunctions() { | ||
return (grunt.option('write') !== false); | ||
} | ||
function getDestinationFile() { | ||
return (boxes ? 'dist/iso_boxer.' + boxes + '.js' : 'dist/iso_boxer.js'); | ||
} | ||
function getDestinationMinifiedFile() { | ||
if (boxes) { | ||
var minifiedFile = 'dist/iso_boxer.' + boxes + '.min.js'; | ||
return [{ src: '<%= concat.dist.dest %>', dest: minifiedFile }] | ||
return [{ src: '<%= concat.dist.dest %>', dest: minifiedFile }]; | ||
} | ||
return { 'dist/iso_boxer.min.js': ['<%= concat.dist.dest %>'] } | ||
return { 'dist/iso_boxer.min.js': ['<%= concat.dist.dest %>'] }; | ||
} | ||
function getSourceFiles() { | ||
var defaultList = ['src/iso_boxer.js', 'src/cursor.js', 'src/iso_file.js', 'src/iso_box.js']; | ||
if (!boxes) { | ||
return defaultList.concat(['src/parsers/*.js']); | ||
return defaultList.concat(['src/processors/*.js']); | ||
} | ||
var parsers = grunt.file.expand('src/parsers/*.js'); | ||
var processors = grunt.file.expand('src/processors/*.js'); | ||
var boxList = boxes.split(','); | ||
var files = []; | ||
boxList.forEach(function(box) { | ||
var parser = getBoxParserForBox(parsers, box); | ||
if (parser && files.indexOf(parser) == -1) files.push(parser); | ||
}) | ||
var processor = getBoxProcessorForBox(processors, box); | ||
if (processor && files.indexOf(processor) == -1) files.push(processor); | ||
}); | ||
return defaultList.concat(files); | ||
} | ||
function getBoxParserForBox(parsers, box) { | ||
function getBoxProcessorForBox(processors, box) { | ||
var result; | ||
parsers.forEach(function(parser) { | ||
var providers = parser.split('/').pop().replace('.js', '').split(',') | ||
if (providers.indexOf(box) != -1) result = parser; | ||
}) | ||
processors.forEach(function(processor) { | ||
var providers = processor.split('/').pop().replace('.js', '').split(','); | ||
if (providers.indexOf(box) != -1) result = processor; | ||
}); | ||
return result; | ||
} | ||
grunt.initConfig({ | ||
pkg: grunt.file.readJSON('package.json'), | ||
licenseUrl: 'https://github.com/madebyhiro/codem-isoboxer/blob/master/LICENSE.txt', | ||
licenseUrl: 'https://github.com/madebyhiro/codem-isoboxer/blob/master/LICENSE.txt', | ||
preprocess: { | ||
options: { | ||
context : { | ||
WRITE: includeWriteFunctions() | ||
} | ||
}, | ||
inline : { | ||
src : [ getDestinationFile() ], | ||
options: { | ||
inline : true, | ||
context : { | ||
WRITE: includeWriteFunctions() | ||
} | ||
} | ||
} | ||
}, | ||
concat: { | ||
@@ -71,4 +91,5 @@ options: { | ||
grunt.loadNpmTasks('grunt-contrib-watch'); | ||
grunt.loadNpmTasks('grunt-preprocess'); | ||
grunt.registerTask('default', ['concat', 'uglify']); | ||
grunt.registerTask('default', ['concat', 'preprocess', 'uglify']); | ||
}; |
{ | ||
"name": "codem-isoboxer", | ||
"version": "0.2.10", | ||
"version": "0.3.0", | ||
"description": "A lightweight JavaScript MP4 (MPEG-4, ISOBMFF) file/box parser.", | ||
@@ -28,3 +28,5 @@ "keywords": [ | ||
"grunt-contrib-watch": "^1.0.0", | ||
"grunt-preprocess": "^5.1.0", | ||
"jasmine-node": "^1.14.5", | ||
"arraybuffer-equal": "^1.0.4", | ||
"jshint": "^2.9.4" | ||
@@ -31,0 +33,0 @@ }, |
@@ -35,3 +35,3 @@ # codem-isoboxer | ||
* moov / moof | ||
* mp4a | ||
* mp4a / enca | ||
* mvex | ||
@@ -68,3 +68,3 @@ * mvhd / mfhd | ||
* avc1 | ||
* avc1 / encv | ||
@@ -71,0 +71,0 @@ Support for more boxes can easily be added by adding additional box parsers in `src/parsers`. Some utility functions are included to help with reading the various ISOBMFF data types from the raw file. Also, see the [Box Support page on the Wiki](https://github.com/madebyhiro/codem-isoboxer/wiki/Box-support) for a full list. |
ISOBoxer.Cursor = function(initialOffset) { | ||
this.offset = (typeof initialOffset == 'undefined' ? 0 : initialOffset); | ||
}; | ||
}; |
@@ -16,13 +16,151 @@ var ISOBox = function() { | ||
ISOBox.create = function(type) { | ||
var newBox = new ISOBox(); | ||
newBox.type = type; | ||
newBox.boxes = []; | ||
return newBox; | ||
}; | ||
ISOBox.prototype._boxContainers = ['dinf', 'edts', 'mdia', 'meco', 'mfra', 'minf', 'moof', 'moov', 'mvex', 'stbl', 'strk', 'traf', 'trak', 'tref', 'udta', 'vttc', 'sinf', 'schi', 'encv', 'enca']; | ||
ISOBox.prototype._boxProcessors = {}; | ||
/////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// Generic read/write functions | ||
ISOBox.prototype._procField = function (name, type, size) { | ||
if (this._parsing) { | ||
this[name] = this._readField(type, size); | ||
} | ||
// @ifdef WRITE | ||
else { | ||
this._writeField(type, size, this[name]); | ||
} | ||
// @endif | ||
}; | ||
ISOBox.prototype._procFieldArray = function (name, length, type, size) { | ||
var i; | ||
if (this._parsing) { | ||
this[name] = []; | ||
for (i = 0; i < length; i++) { | ||
this[name][i] = this._readField(type, size); | ||
} | ||
} | ||
// @ifdef WRITE | ||
else { | ||
for (i = 0; i < this[name].length; i++) { | ||
this._writeField(type, size, this[name][i]); | ||
} | ||
} | ||
// @endif | ||
}; | ||
ISOBox.prototype._procFullBox = function() { | ||
this._procField('version', 'uint', 8); | ||
this._procField('flags', 'uint', 24); | ||
}; | ||
ISOBox.prototype._procEntries = function(name, length, fn) { | ||
var i; | ||
if (this._parsing) { | ||
this[name] = []; | ||
for (i = 0; i < length; i++) { | ||
this[name].push({}); | ||
fn.call(this, this[name][i]); | ||
} | ||
} | ||
// @ifdef WRITE | ||
else { | ||
for (i = 0; i < length; i++) { | ||
fn.call(this, this[name][i]); | ||
} | ||
} | ||
// @endif | ||
}; | ||
ISOBox.prototype._procSubEntries = function(entry, name, length, fn) { | ||
var i; | ||
if (this._parsing) { | ||
entry[name] = []; | ||
for (i = 0; i < length; i++) { | ||
entry[name].push({}); | ||
fn.call(this, entry[name][i]); | ||
} | ||
} | ||
// @ifdef WRITE | ||
else { | ||
for (i = 0; i < length; i++) { | ||
fn.call(this, entry[name][i]); | ||
} | ||
} | ||
// @endif | ||
}; | ||
ISOBox.prototype._procEntryField = function (entry, name, type, size) { | ||
if (this._parsing) { | ||
entry[name] = this._readField(type, size); | ||
} | ||
// @ifdef WRITE | ||
else { | ||
this._writeField(type, size, entry[name]); | ||
} | ||
// @endif | ||
}; | ||
ISOBox.prototype._procSubBoxes = function(name, length) { | ||
var i; | ||
if (this._parsing) { | ||
this[name] = []; | ||
for (i = 0; i < length; i++) { | ||
this[name].push(ISOBox.parse(this)); | ||
} | ||
} | ||
// @ifdef WRITE | ||
else { | ||
for (i = 0; i < length; i++) { | ||
if (this._rawo) { | ||
this[name][i].write(); | ||
} else { | ||
this.size += this[name][i].getLength(); | ||
} | ||
} | ||
} | ||
// @endif | ||
}; | ||
/////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// Read/parse functions | ||
ISOBox.prototype._readField = function(type, size) { | ||
switch (type) { | ||
case 'uint': | ||
return this._readUint(size); | ||
case 'int': | ||
return this._readInt(size); | ||
case 'template': | ||
return this._readTemplate(size); | ||
case 'string': | ||
return (size === -1) ? this._readTerminatedString() : this._readString(size); | ||
case 'data': | ||
return this._readData(size); | ||
case 'utf8': | ||
return this._readUTF8String(); | ||
default: | ||
return -1; | ||
} | ||
}; | ||
ISOBox.prototype._readInt = function(size) { | ||
var result = null; | ||
var result = null, | ||
offset = this._cursor.offset - this._raw.byteOffset; | ||
switch(size) { | ||
case 8: | ||
result = this._raw.getInt8(this._cursor.offset - this._raw.byteOffset); | ||
result = this._raw.getInt8(offset); | ||
break; | ||
case 16: | ||
result = this._raw.getInt16(this._cursor.offset - this._raw.byteOffset); | ||
result = this._raw.getInt16(offset); | ||
break; | ||
case 32: | ||
result = this._raw.getInt32(this._cursor.offset - this._raw.byteOffset); | ||
result = this._raw.getInt32(offset); | ||
break; | ||
@@ -32,4 +170,4 @@ case 64: | ||
// This will give unexpected results for integers >= 2^53 | ||
var s1 = this._raw.getInt32(this._cursor.offset - this._raw.byteOffset); | ||
var s2 = this._raw.getInt32(this._cursor.offset - this._raw.byteOffset + 4); | ||
var s1 = this._raw.getInt32(offset); | ||
var s2 = this._raw.getInt32(offset + 4); | ||
result = (s1 * Math.pow(2,32)) + s2; | ||
@@ -44,17 +182,18 @@ break; | ||
var result = null, | ||
offset = this._cursor.offset - this._raw.byteOffset, | ||
s1, s2; | ||
switch(size) { | ||
case 8: | ||
result = this._raw.getUint8(this._cursor.offset - this._raw.byteOffset); | ||
result = this._raw.getUint8(offset); | ||
break; | ||
case 16: | ||
result = this._raw.getUint16(this._cursor.offset - this._raw.byteOffset); | ||
result = this._raw.getUint16(offset); | ||
break; | ||
case 24: | ||
s1 = this._raw.getUint16(this._cursor.offset - this._raw.byteOffset); | ||
s2 = this._raw.getUint8(this._cursor.offset - this._raw.byteOffset + 2); | ||
s1 = this._raw.getUint16(offset); | ||
s2 = this._raw.getUint8(offset + 2); | ||
result = (s1 << 8) + s2; | ||
break; | ||
case 32: | ||
result = this._raw.getUint32(this._cursor.offset - this._raw.byteOffset); | ||
result = this._raw.getUint32(offset); | ||
break; | ||
@@ -64,4 +203,4 @@ case 64: | ||
// This will give unexpected results for integers >= 2^53 | ||
s1 = this._raw.getUint32(this._cursor.offset - this._raw.byteOffset); | ||
s2 = this._raw.getUint32(this._cursor.offset - this._raw.byteOffset + 4); | ||
s1 = this._raw.getUint32(offset); | ||
s2 = this._raw.getUint32(offset + 4); | ||
result = (s1 * Math.pow(2,32)) + s2; | ||
@@ -83,2 +222,8 @@ break; | ||
ISOBox.prototype._readTemplate = function(size) { | ||
var pre = this._readUint(size / 2); | ||
var post = this._readUint(size / 2); | ||
return pre + (post / Math.pow(2, size / 2)); | ||
}; | ||
ISOBox.prototype._readTerminatedString = function() { | ||
@@ -94,8 +239,2 @@ var str = ''; | ||
ISOBox.prototype._readTemplate = function(size) { | ||
var pre = this._readUint(size / 2); | ||
var post = this._readUint(size / 2); | ||
return pre + (post / Math.pow(2, size / 2)); | ||
}; | ||
ISOBox.prototype._readData = function(size) { | ||
@@ -108,3 +247,9 @@ var length = (size > 0) ? size : (this._raw.byteLength - (this._cursor.offset - this._offset)); | ||
ISOBox.prototype._readUTF8String = function() { | ||
var data = this._readData(); | ||
return ISOBoxer.Utils.dataViewToString(data); | ||
}; | ||
ISOBox.prototype._parseBox = function() { | ||
this._parsing = true; | ||
this._cursor.offset = this._offset; | ||
@@ -118,7 +263,7 @@ | ||
this.size = this._readUint(32); | ||
this.type = this._readString(4); | ||
this._procField('size', 'uint', 32); | ||
this._procField('type', 'string', 4); | ||
if (this.size == 1) { this.largesize = this._readUint(64); } | ||
if (this.type == 'uuid') { this.usertype = this._readString(16); } | ||
if (this.size === 1) { this._procField('largesize', 'uint', 64); } | ||
if (this.type === 'uuid') { this._procFieldArray('usertype', 16, 'uint', 8); } | ||
@@ -148,6 +293,10 @@ switch(this.size) { | ||
if (!this._incomplete) { | ||
if (this._boxProcessors[this.type]) { | ||
this._boxProcessors[this.type].call(this); | ||
} | ||
if (this._boxContainers.indexOf(this.type) !== -1) { | ||
this._parseContainerBox(); | ||
} else if (this._boxParsers[this.type]) { | ||
this._boxParsers[this.type].call(this); | ||
} else{ | ||
// Unknown box => read and store box content | ||
this._data = this._readData(); | ||
} | ||
@@ -169,4 +318,223 @@ } | ||
ISOBox.prototype._boxContainers = ['dinf', 'edts', 'mdia', 'meco', 'mfra', 'minf', 'moof', 'moov', 'mvex', 'stbl', 'strk', 'traf', 'trak', 'tref', 'udta', 'vttc']; | ||
// @ifdef WRITE | ||
/////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// Write functions | ||
ISOBox.prototype._boxParsers = {}; | ||
ISOBox.prototype.append = function(box, pos) { | ||
ISOBoxer.Utils.appendBox(this, box, pos); | ||
}; | ||
ISOBox.prototype.getLength = function() { | ||
this._parsing = false; | ||
this._rawo = null; | ||
this.size = 0; | ||
this._procField('size', 'uint', 32); | ||
this._procField('type', 'string', 4); | ||
if (this.size === 1) { this._procField('largesize', 'uint', 64); } | ||
if (this.type === 'uuid') { this._procFieldArray('usertype', 16, 'uint', 8); } | ||
if (this._boxProcessors[this.type]) { | ||
this._boxProcessors[this.type].call(this); | ||
} | ||
if (this._boxContainers.indexOf(this.type) !== -1) { | ||
for (var i = 0; i < this.boxes.length; i++) { | ||
this.size += this.boxes[i].getLength(); | ||
} | ||
} | ||
if (this._data) { | ||
this._writeData(this._data); | ||
} | ||
return this.size; | ||
}; | ||
ISOBox.prototype.write = function() { | ||
this._parsing = false; | ||
this._cursor.offset = this._parent._cursor.offset; | ||
switch(this.size) { | ||
case 0: | ||
this._rawo = new DataView(this._parent._rawo.buffer, this._cursor.offset, (this.parent._rawo.byteLength - this._cursor.offset)); | ||
break; | ||
case 1: | ||
this._rawo = new DataView(this._parent._rawo.buffer, this._cursor.offset, this.largesize); | ||
break; | ||
default: | ||
this._rawo = new DataView(this._parent._rawo.buffer, this._cursor.offset, this.size); | ||
} | ||
this._procField('size', 'uint', 32); | ||
this._procField('type', 'string', 4); | ||
if (this.size === 1) { this._procField('largesize', 'uint', 64); } | ||
if (this.type === 'uuid') { this._procFieldArray('usertype', 16, 'uint', 8); } | ||
if (this._boxProcessors[this.type]) { | ||
this._boxProcessors[this.type].call(this); | ||
} | ||
if (this._boxContainers.indexOf(this.type) !== -1) { | ||
for (var i = 0; i < this.boxes.length; i++) { | ||
this.boxes[i].write(); | ||
} | ||
} | ||
if (this._data) { | ||
this._writeData(this._data); | ||
} | ||
this._parent._cursor.offset += this.size; | ||
return this.size; | ||
}; | ||
ISOBox.prototype._writeInt = function(size, value) { | ||
if (this._rawo) { | ||
var offset = this._cursor.offset - this._rawo.byteOffset; | ||
switch(size) { | ||
case 8: | ||
this._rawo.setInt8(offset, value); | ||
break; | ||
case 16: | ||
this._rawo.setInt16(offset, value); | ||
break; | ||
case 32: | ||
this._rawo.setInt32(offset, value); | ||
break; | ||
case 64: | ||
// Warning: JavaScript cannot handle 64-bit integers natively. | ||
// This will give unexpected results for integers >= 2^53 | ||
var s1 = Math.round(value / Math.pow(2,32)); | ||
var s2 = value - (s1 * Math.pow(2,32)); | ||
this._rawo.setUint32(offset, s1); | ||
this._rawo.setUint32(offset + 4, s2); | ||
break; | ||
} | ||
this._cursor.offset += (size >> 3); | ||
} else { | ||
this.size += (size >> 3); | ||
} | ||
}; | ||
ISOBox.prototype._writeUint = function(size, value) { | ||
if (this._rawo) { | ||
var offset = this._cursor.offset - this._rawo.byteOffset, | ||
s1, s2; | ||
switch(size) { | ||
case 8: | ||
this._rawo.setUint8(offset, value); | ||
break; | ||
case 16: | ||
this._rawo.setUint16(offset, value); | ||
break; | ||
case 24: | ||
s1 = (value & 0xFFFF00) >> 8; | ||
s2 = (value & 0x0000FF); | ||
this._rawo.setUint16(offset, s1); | ||
this._rawo.setUint8(offset + 2, s2); | ||
break; | ||
case 32: | ||
this._rawo.setUint32(offset, value); | ||
break; | ||
case 64: | ||
// Warning: JavaScript cannot handle 64-bit integers natively. | ||
// This will give unexpected results for integers >= 2^53 | ||
s1 = Math.round(value / Math.pow(2,32)); | ||
s2 = value - (s1 * Math.pow(2,32)); | ||
this._rawo.setUint32(offset, s1); | ||
this._rawo.setUint32(offset + 4, s2); | ||
break; | ||
} | ||
this._cursor.offset += (size >> 3); | ||
} else { | ||
this.size += (size >> 3); | ||
} | ||
}; | ||
ISOBox.prototype._writeString = function(size, str) { | ||
for (var c = 0; c < size; c++) { | ||
this._writeUint(8, str.charCodeAt(c)); | ||
} | ||
}; | ||
ISOBox.prototype._writeTerminatedString = function(str) { | ||
if (str.length === 0) { | ||
return; | ||
} | ||
for (var c = 0; c < str.length; c++) { | ||
this._writeUint(8, str.charCodeAt(c)); | ||
} | ||
this._writeUint(8, 0); | ||
}; | ||
ISOBox.prototype._writeTemplate = function(size, value) { | ||
var pre = Math.round(value); | ||
var post = (value - pre) * Math.pow(2, size / 2); | ||
this._writeUint(size / 2, pre); | ||
this._writeUint(size / 2, post); | ||
}; | ||
ISOBox.prototype._writeData = function(data) { | ||
if (data instanceof Array) { | ||
data = new DataView(Uint8Array.from(data).buffer); | ||
} | ||
if (data instanceof Uint8Array) { | ||
data = new DataView(data.buffer); | ||
} | ||
if (this._rawo) { | ||
var offset = this._cursor.offset - this._rawo.byteOffset; | ||
for (var i = 0; i < data.byteLength; i++) { | ||
this._rawo.setUint8(offset + i, data.getUint8(i)); | ||
} | ||
this._cursor.offset += data.byteLength; | ||
} else { | ||
this.size += data.byteLength; | ||
} | ||
}; | ||
ISOBox.prototype._writeUTF8String = function(string) { | ||
var u = ISOBoxer.Utils.utf8ToByteArray(string); | ||
if (this._rawo) { | ||
var dataView = new DataView(this._rawo.buffer, this._cursor.offset, u.length); | ||
for (var i = 0; i < u.length; i++) { | ||
dataView.setUint8(i, u[i]); | ||
} | ||
} else { | ||
this.size += u.length; | ||
} | ||
}; | ||
ISOBox.prototype._writeField = function(type, size, value) { | ||
switch (type) { | ||
case 'uint': | ||
this._writeUint(size, value); | ||
break; | ||
case 'int': | ||
this._writeInt(size, value); | ||
break; | ||
case 'template': | ||
this._writeTemplate(size, value); | ||
break; | ||
case 'string': | ||
if (size == -1) { | ||
this._writeTerminatedString(value); | ||
} else { | ||
this._writeString(size, value); | ||
} | ||
break; | ||
case 'data': | ||
this._writeData(value); | ||
break; | ||
case 'utf8': | ||
this._writeUTF8String(value); | ||
break; | ||
default: | ||
break; | ||
} | ||
}; | ||
// @endif |
@@ -7,9 +7,32 @@ var ISOBoxer = {}; | ||
ISOBoxer.addBoxParser = function(type, parser) { | ||
ISOBoxer.addBoxProcessor = function(type, parser) { | ||
if (typeof type !== 'string' || typeof parser !== 'function') { | ||
return; | ||
} | ||
ISOBox.prototype._boxParsers[type] = parser; | ||
ISOBox.prototype._boxProcessors[type] = parser; | ||
}; | ||
// @ifdef WRITE | ||
ISOBoxer.createFile = function() { | ||
return new ISOFile(); | ||
}; | ||
// See ISOBoxer.append() for 'pos' parameter syntax | ||
ISOBoxer.createBox = function(type, parent, pos) { | ||
var newBox = ISOBox.create(type); | ||
if (parent) { | ||
parent.append(newBox, pos); | ||
} | ||
return newBox; | ||
}; | ||
// See ISOBoxer.append() for 'pos' parameter syntax | ||
ISOBoxer.createFullBox = function(type, parent, pos) { | ||
var newBox = ISOBoxer.createBox(type, parent, pos); | ||
newBox.version = 0; | ||
newBox.flags = 0; | ||
return newBox; | ||
}; | ||
// @endif | ||
ISOBoxer.Utils = {}; | ||
@@ -59,6 +82,89 @@ ISOBoxer.Utils.dataViewToString = function(dataView, encoding) { | ||
// @ifdef WRITE | ||
ISOBoxer.Utils.utf8ToByteArray = function(string) { | ||
// Only UTF-8 encoding is supported by TextEncoder | ||
var u, i; | ||
if (typeof TextEncoder !== 'undefined') { | ||
u = new TextEncoder().encode(string); | ||
} else { | ||
u = []; | ||
for (i = 0; i < string.length; ++i) { | ||
var c = string.charCodeAt(i); | ||
if (c < 0x80) { | ||
u.push(c); | ||
} else if (c < 0x800) { | ||
u.push(0xC0 | (c >> 6)); | ||
u.push(0x80 | (63 & c)); | ||
} else if (c < 0x10000) { | ||
u.push(0xE0 | (c >> 12)); | ||
u.push(0x80 | (63 & (c >> 6))); | ||
u.push(0x80 | (63 & c)); | ||
} else { | ||
u.push(0xF0 | (c >> 18)); | ||
u.push(0x80 | (63 & (c >> 12))); | ||
u.push(0x80 | (63 & (c >> 6))); | ||
u.push(0x80 | (63 & c)); | ||
} | ||
} | ||
} | ||
return u; | ||
}; | ||
// Method to append a box in the list of child boxes | ||
// The 'pos' parameter can be either: | ||
// - (number) a position index at which to insert the new box | ||
// - (string) the type of the box after which to insert the new box | ||
// - (object) the box after which to insert the new box | ||
ISOBoxer.Utils.appendBox = function(parent, box, pos) { | ||
box._offset = parent._cursor.offset; | ||
box._root = (parent._root ? parent._root : parent); | ||
box._raw = parent._raw; | ||
box._parent = parent; | ||
if (pos === -1) { | ||
// The new box is a sub-box of the parent but not added in boxes array, | ||
// for example when the new box is set as an entry (see dref and stsd for example) | ||
return; | ||
} | ||
if (pos === undefined || pos === null) { | ||
parent.boxes.push(box); | ||
return; | ||
} | ||
var index = -1, | ||
type; | ||
if (typeof pos === "number") { | ||
index = pos; | ||
} else { | ||
if (typeof pos === "string") { | ||
type = pos; | ||
} else if (typeof pos === "object" && pos.type) { | ||
type = pos.type; | ||
} else { | ||
parent.boxes.push(box); | ||
return; | ||
} | ||
for (var i = 0; i < parent.boxes.length; i++) { | ||
if (type === parent.boxes[i].type) { | ||
index = i + 1; | ||
break; | ||
} | ||
} | ||
} | ||
parent.boxes.splice(index, 0, box); | ||
}; | ||
// @endif | ||
if (typeof exports !== 'undefined') { | ||
exports.parseBuffer = ISOBoxer.parseBuffer; | ||
exports.addBoxParser = ISOBoxer.addBoxParser; | ||
exports.Utils = ISOBoxer.Utils; | ||
} | ||
exports.parseBuffer = ISOBoxer.parseBuffer; | ||
exports.addBoxProcessor = ISOBoxer.addBoxProcessor; | ||
// @ifdef WRITE | ||
exports.createFile = ISOBoxer.createFile; | ||
exports.createBox = ISOBoxer.createBox; | ||
exports.createFullBox = ISOBoxer.createFullBox; | ||
// @endif | ||
exports.Utils = ISOBoxer.Utils; | ||
} |
var ISOFile = function(arrayBuffer) { | ||
this._raw = new DataView(arrayBuffer); | ||
this._cursor = new ISOBoxer.Cursor(); | ||
this.boxes = []; | ||
if (arrayBuffer) { | ||
this._raw = new DataView(arrayBuffer); | ||
} | ||
}; | ||
@@ -38,2 +40,51 @@ | ||
} | ||
}; | ||
}; | ||
// @ifdef WRITE | ||
ISOFile.prototype.write = function() { | ||
var length = 0, | ||
i; | ||
for (i = 0; i < this.boxes.length; i++) { | ||
length += this.boxes[i].getLength(false); | ||
} | ||
var bytes = new Uint8Array(length); | ||
this._rawo = new DataView(bytes.buffer); | ||
this.bytes = bytes; | ||
this._cursor.offset = 0; | ||
for (i = 0; i < this.boxes.length; i++) { | ||
this.boxes[i].write(); | ||
} | ||
return bytes.buffer; | ||
}; | ||
ISOFile.prototype.append = function(box, pos) { | ||
ISOBoxer.Utils.appendBox(this, box, pos); | ||
}; | ||
/*ISOFile.prototype.create = function(type, parent, previousType) { | ||
var newBox = ISOBox.create(type, parent), | ||
inserted = false; | ||
if (previousType) { | ||
for (var i = 0; i < parent.boxes.length; i++) { | ||
if (previousType === parent.boxes[i].type) { | ||
parent.boxes.splice(i + 1, 0, newBox); | ||
inserted = true; | ||
break; | ||
} | ||
} | ||
} | ||
if (!inserted) { | ||
parent.boxes.push(newBox); | ||
} | ||
return newBox; | ||
};*/ | ||
// @endif |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
114573
50
2176
8
1