UNPKG

@meframe/core

Version:

Next generation media processing framework based on WebCodecs

1,520 lines (1,519 loc) 268 kB
var mp4box_all = {}; (function(exports) { var Log = /* @__PURE__ */ function() { var start = /* @__PURE__ */ new Date(); var LOG_LEVEL_ERROR = 4; var LOG_LEVEL_WARNING = 3; var LOG_LEVEL_INFO = 2; var LOG_LEVEL_DEBUG = 1; var log_level = LOG_LEVEL_ERROR; var logObject = { setLogLevel: function(level) { if (level == this.debug) log_level = LOG_LEVEL_DEBUG; else if (level == this.info) log_level = LOG_LEVEL_INFO; else if (level == this.warn) log_level = LOG_LEVEL_WARNING; else if (level == this.error) log_level = LOG_LEVEL_ERROR; else log_level = LOG_LEVEL_ERROR; }, debug: function(module, msg) { if (console.debug === void 0) { console.debug = console.log; } if (LOG_LEVEL_DEBUG >= log_level) { console.debug("[" + Log.getDurationString(/* @__PURE__ */ new Date() - start, 1e3) + "]", "[" + module + "]", msg); } }, log: function(module, msg) { this.debug(module.msg); }, info: function(module, msg) { if (LOG_LEVEL_INFO >= log_level) { console.info("[" + Log.getDurationString(/* @__PURE__ */ new Date() - start, 1e3) + "]", "[" + module + "]", msg); } }, warn: function(module, msg) { if (LOG_LEVEL_WARNING >= log_level) { console.warn("[" + Log.getDurationString(/* @__PURE__ */ new Date() - start, 1e3) + "]", "[" + module + "]", msg); } }, error: function(module, msg) { if (LOG_LEVEL_ERROR >= log_level) { console.error("[" + Log.getDurationString(/* @__PURE__ */ new Date() - start, 1e3) + "]", "[" + module + "]", msg); } } }; return logObject; }(); Log.getDurationString = function(duration, _timescale) { var neg; function pad(number, length) { var str = "" + number; var a = str.split("."); while (a[0].length < length) { a[0] = "0" + a[0]; } return a.join("."); } if (duration < 0) { neg = true; duration = -duration; } else { neg = false; } var timescale = _timescale || 1; var duration_sec = duration / timescale; var hours = Math.floor(duration_sec / 3600); duration_sec -= hours * 3600; var minutes = Math.floor(duration_sec / 60); duration_sec -= minutes * 60; var msec = duration_sec * 1e3; duration_sec = Math.floor(duration_sec); msec -= duration_sec * 1e3; msec = Math.floor(msec); return (neg ? "-" : "") + hours + ":" + pad(minutes, 2) + ":" + pad(duration_sec, 2) + "." + pad(msec, 3); }; Log.printRanges = function(ranges) { var length = ranges.length; if (length > 0) { var str = ""; for (var i2 = 0; i2 < length; i2++) { if (i2 > 0) str += ","; str += "[" + Log.getDurationString(ranges.start(i2)) + "," + Log.getDurationString(ranges.end(i2)) + "]"; } return str; } else { return "(empty)"; } }; { exports.Log = Log; } var MP4BoxStream = function(arrayBuffer) { if (arrayBuffer instanceof ArrayBuffer) { this.buffer = arrayBuffer; this.dataview = new DataView(arrayBuffer); } else { throw "Needs an array buffer"; } this.position = 0; }; MP4BoxStream.prototype.getPosition = function() { return this.position; }; MP4BoxStream.prototype.getEndPosition = function() { return this.buffer.byteLength; }; MP4BoxStream.prototype.getLength = function() { return this.buffer.byteLength; }; MP4BoxStream.prototype.seek = function(pos) { var npos = Math.max(0, Math.min(this.buffer.byteLength, pos)); this.position = isNaN(npos) || !isFinite(npos) ? 0 : npos; return true; }; MP4BoxStream.prototype.isEos = function() { return this.getPosition() >= this.getEndPosition(); }; MP4BoxStream.prototype.readAnyInt = function(size, signed) { var res = 0; if (this.position + size <= this.buffer.byteLength) { switch (size) { case 1: if (signed) { res = this.dataview.getInt8(this.position); } else { res = this.dataview.getUint8(this.position); } break; case 2: if (signed) { res = this.dataview.getInt16(this.position); } else { res = this.dataview.getUint16(this.position); } break; case 3: if (signed) { throw "No method for reading signed 24 bits values"; } else { res = this.dataview.getUint8(this.position) << 16; res |= this.dataview.getUint8(this.position + 1) << 8; res |= this.dataview.getUint8(this.position + 2); } break; case 4: if (signed) { res = this.dataview.getInt32(this.position); } else { res = this.dataview.getUint32(this.position); } break; case 8: if (signed) { throw "No method for reading signed 64 bits values"; } else { res = this.dataview.getUint32(this.position) << 32; res |= this.dataview.getUint32(this.position + 4); } break; default: throw "readInt method not implemented for size: " + size; } this.position += size; return res; } else { throw "Not enough bytes in buffer"; } }; MP4BoxStream.prototype.readUint8 = function() { return this.readAnyInt(1, false); }; MP4BoxStream.prototype.readUint16 = function() { return this.readAnyInt(2, false); }; MP4BoxStream.prototype.readUint24 = function() { return this.readAnyInt(3, false); }; MP4BoxStream.prototype.readUint32 = function() { return this.readAnyInt(4, false); }; MP4BoxStream.prototype.readUint64 = function() { return this.readAnyInt(8, false); }; MP4BoxStream.prototype.readString = function(length) { if (this.position + length <= this.buffer.byteLength) { var s = ""; for (var i2 = 0; i2 < length; i2++) { s += String.fromCharCode(this.readUint8()); } return s; } else { throw "Not enough bytes in buffer"; } }; MP4BoxStream.prototype.readCString = function() { var arr = []; while (true) { var b = this.readUint8(); if (b !== 0) { arr.push(b); } else { break; } } return String.fromCharCode.apply(null, arr); }; MP4BoxStream.prototype.readInt8 = function() { return this.readAnyInt(1, true); }; MP4BoxStream.prototype.readInt16 = function() { return this.readAnyInt(2, true); }; MP4BoxStream.prototype.readInt32 = function() { return this.readAnyInt(4, true); }; MP4BoxStream.prototype.readInt64 = function() { return this.readAnyInt(8, false); }; MP4BoxStream.prototype.readUint8Array = function(length) { var arr = new Uint8Array(length); for (var i2 = 0; i2 < length; i2++) { arr[i2] = this.readUint8(); } return arr; }; MP4BoxStream.prototype.readInt16Array = function(length) { var arr = new Int16Array(length); for (var i2 = 0; i2 < length; i2++) { arr[i2] = this.readInt16(); } return arr; }; MP4BoxStream.prototype.readUint16Array = function(length) { var arr = new Int16Array(length); for (var i2 = 0; i2 < length; i2++) { arr[i2] = this.readUint16(); } return arr; }; MP4BoxStream.prototype.readUint32Array = function(length) { var arr = new Uint32Array(length); for (var i2 = 0; i2 < length; i2++) { arr[i2] = this.readUint32(); } return arr; }; MP4BoxStream.prototype.readInt32Array = function(length) { var arr = new Int32Array(length); for (var i2 = 0; i2 < length; i2++) { arr[i2] = this.readInt32(); } return arr; }; { exports.MP4BoxStream = MP4BoxStream; } var DataStream = function(arrayBuffer, byteOffset, endianness) { this._byteOffset = byteOffset || 0; if (arrayBuffer instanceof ArrayBuffer) { this.buffer = arrayBuffer; } else if (typeof arrayBuffer == "object") { this.dataView = arrayBuffer; if (byteOffset) { this._byteOffset += byteOffset; } } else { this.buffer = new ArrayBuffer(arrayBuffer || 0); } this.position = 0; this.endianness = endianness == null ? DataStream.LITTLE_ENDIAN : endianness; }; DataStream.prototype = {}; DataStream.prototype.getPosition = function() { return this.position; }; DataStream.prototype._realloc = function(extra) { if (!this._dynamicSize) { return; } var req = this._byteOffset + this.position + extra; var blen = this._buffer.byteLength; if (req <= blen) { if (req > this._byteLength) { this._byteLength = req; } return; } if (blen < 1) { blen = 1; } while (req > blen) { blen *= 2; } var buf = new ArrayBuffer(blen); var src = new Uint8Array(this._buffer); var dst = new Uint8Array(buf, 0, src.length); dst.set(src); this.buffer = buf; this._byteLength = req; }; DataStream.prototype._trimAlloc = function() { if (this._byteLength == this._buffer.byteLength) { return; } var buf = new ArrayBuffer(this._byteLength); var dst = new Uint8Array(buf); var src = new Uint8Array(this._buffer, 0, dst.length); dst.set(src); this.buffer = buf; }; DataStream.BIG_ENDIAN = false; DataStream.LITTLE_ENDIAN = true; DataStream.prototype._byteLength = 0; Object.defineProperty( DataStream.prototype, "byteLength", { get: function() { return this._byteLength - this._byteOffset; } } ); Object.defineProperty( DataStream.prototype, "buffer", { get: function() { this._trimAlloc(); return this._buffer; }, set: function(v) { this._buffer = v; this._dataView = new DataView(this._buffer, this._byteOffset); this._byteLength = this._buffer.byteLength; } } ); Object.defineProperty( DataStream.prototype, "byteOffset", { get: function() { return this._byteOffset; }, set: function(v) { this._byteOffset = v; this._dataView = new DataView(this._buffer, this._byteOffset); this._byteLength = this._buffer.byteLength; } } ); Object.defineProperty( DataStream.prototype, "dataView", { get: function() { return this._dataView; }, set: function(v) { this._byteOffset = v.byteOffset; this._buffer = v.buffer; this._dataView = new DataView(this._buffer, this._byteOffset); this._byteLength = this._byteOffset + v.byteLength; } } ); DataStream.prototype.seek = function(pos) { var npos = Math.max(0, Math.min(this.byteLength, pos)); this.position = isNaN(npos) || !isFinite(npos) ? 0 : npos; }; DataStream.prototype.isEof = function() { return this.position >= this._byteLength; }; DataStream.prototype.mapUint8Array = function(length) { this._realloc(length * 1); var arr = new Uint8Array(this._buffer, this.byteOffset + this.position, length); this.position += length * 1; return arr; }; DataStream.prototype.readInt32Array = function(length, e) { length = length == null ? this.byteLength - this.position / 4 : length; var arr = new Int32Array(length); DataStream.memcpy( arr.buffer, 0, this.buffer, this.byteOffset + this.position, length * arr.BYTES_PER_ELEMENT ); DataStream.arrayToNative(arr, e == null ? this.endianness : e); this.position += arr.byteLength; return arr; }; DataStream.prototype.readInt16Array = function(length, e) { length = length == null ? this.byteLength - this.position / 2 : length; var arr = new Int16Array(length); DataStream.memcpy( arr.buffer, 0, this.buffer, this.byteOffset + this.position, length * arr.BYTES_PER_ELEMENT ); DataStream.arrayToNative(arr, e == null ? this.endianness : e); this.position += arr.byteLength; return arr; }; DataStream.prototype.readInt8Array = function(length) { length = length == null ? this.byteLength - this.position : length; var arr = new Int8Array(length); DataStream.memcpy( arr.buffer, 0, this.buffer, this.byteOffset + this.position, length * arr.BYTES_PER_ELEMENT ); this.position += arr.byteLength; return arr; }; DataStream.prototype.readUint32Array = function(length, e) { length = length == null ? this.byteLength - this.position / 4 : length; var arr = new Uint32Array(length); DataStream.memcpy( arr.buffer, 0, this.buffer, this.byteOffset + this.position, length * arr.BYTES_PER_ELEMENT ); DataStream.arrayToNative(arr, e == null ? this.endianness : e); this.position += arr.byteLength; return arr; }; DataStream.prototype.readUint16Array = function(length, e) { length = length == null ? this.byteLength - this.position / 2 : length; var arr = new Uint16Array(length); DataStream.memcpy( arr.buffer, 0, this.buffer, this.byteOffset + this.position, length * arr.BYTES_PER_ELEMENT ); DataStream.arrayToNative(arr, e == null ? this.endianness : e); this.position += arr.byteLength; return arr; }; DataStream.prototype.readUint8Array = function(length) { length = length == null ? this.byteLength - this.position : length; var arr = new Uint8Array(length); DataStream.memcpy( arr.buffer, 0, this.buffer, this.byteOffset + this.position, length * arr.BYTES_PER_ELEMENT ); this.position += arr.byteLength; return arr; }; DataStream.prototype.readFloat64Array = function(length, e) { length = length == null ? this.byteLength - this.position / 8 : length; var arr = new Float64Array(length); DataStream.memcpy( arr.buffer, 0, this.buffer, this.byteOffset + this.position, length * arr.BYTES_PER_ELEMENT ); DataStream.arrayToNative(arr, e == null ? this.endianness : e); this.position += arr.byteLength; return arr; }; DataStream.prototype.readFloat32Array = function(length, e) { length = length == null ? this.byteLength - this.position / 4 : length; var arr = new Float32Array(length); DataStream.memcpy( arr.buffer, 0, this.buffer, this.byteOffset + this.position, length * arr.BYTES_PER_ELEMENT ); DataStream.arrayToNative(arr, e == null ? this.endianness : e); this.position += arr.byteLength; return arr; }; DataStream.prototype.readInt32 = function(e) { var v = this._dataView.getInt32(this.position, e == null ? this.endianness : e); this.position += 4; return v; }; DataStream.prototype.readInt16 = function(e) { var v = this._dataView.getInt16(this.position, e == null ? this.endianness : e); this.position += 2; return v; }; DataStream.prototype.readInt8 = function() { var v = this._dataView.getInt8(this.position); this.position += 1; return v; }; DataStream.prototype.readUint32 = function(e) { var v = this._dataView.getUint32(this.position, e == null ? this.endianness : e); this.position += 4; return v; }; DataStream.prototype.readUint16 = function(e) { var v = this._dataView.getUint16(this.position, e == null ? this.endianness : e); this.position += 2; return v; }; DataStream.prototype.readUint8 = function() { var v = this._dataView.getUint8(this.position); this.position += 1; return v; }; DataStream.prototype.readFloat32 = function(e) { var v = this._dataView.getFloat32(this.position, e == null ? this.endianness : e); this.position += 4; return v; }; DataStream.prototype.readFloat64 = function(e) { var v = this._dataView.getFloat64(this.position, e == null ? this.endianness : e); this.position += 8; return v; }; DataStream.endianness = new Int8Array(new Int16Array([1]).buffer)[0] > 0; DataStream.memcpy = function(dst, dstOffset, src, srcOffset, byteLength) { var dstU8 = new Uint8Array(dst, dstOffset, byteLength); var srcU8 = new Uint8Array(src, srcOffset, byteLength); dstU8.set(srcU8); }; DataStream.arrayToNative = function(array, arrayIsLittleEndian) { if (arrayIsLittleEndian == this.endianness) { return array; } else { return this.flipArrayEndianness(array); } }; DataStream.nativeToEndian = function(array, littleEndian) { if (this.endianness == littleEndian) { return array; } else { return this.flipArrayEndianness(array); } }; DataStream.flipArrayEndianness = function(array) { var u8 = new Uint8Array(array.buffer, array.byteOffset, array.byteLength); for (var i2 = 0; i2 < array.byteLength; i2 += array.BYTES_PER_ELEMENT) { for (var j = i2 + array.BYTES_PER_ELEMENT - 1, k = i2; j > k; j--, k++) { var tmp = u8[k]; u8[k] = u8[j]; u8[j] = tmp; } } return array; }; DataStream.prototype.failurePosition = 0; String.fromCharCodeUint8 = function(uint8arr) { var arr = []; for (var i2 = 0; i2 < uint8arr.length; i2++) { arr[i2] = uint8arr[i2]; } return String.fromCharCode.apply(null, arr); }; DataStream.prototype.readString = function(length, encoding) { if (encoding == null || encoding == "ASCII") { return String.fromCharCodeUint8.apply(null, [this.mapUint8Array(length == null ? this.byteLength - this.position : length)]); } else { return new TextDecoder(encoding).decode(this.mapUint8Array(length)); } }; DataStream.prototype.readCString = function(length) { var blen = this.byteLength - this.position; var u8 = new Uint8Array(this._buffer, this._byteOffset + this.position); var len = blen; if (length != null) { len = Math.min(length, blen); } for (var i2 = 0; i2 < len && u8[i2] !== 0; i2++) ; var s = String.fromCharCodeUint8.apply(null, [this.mapUint8Array(i2)]); if (length != null) { this.position += len - i2; } else if (i2 != blen) { this.position += 1; } return s; }; var MAX_SIZE = Math.pow(2, 32); DataStream.prototype.readInt64 = function() { return this.readInt32() * MAX_SIZE + this.readUint32(); }; DataStream.prototype.readUint64 = function() { return this.readUint32() * MAX_SIZE + this.readUint32(); }; DataStream.prototype.readInt64 = function() { return this.readUint32() * MAX_SIZE + this.readUint32(); }; DataStream.prototype.readUint24 = function() { return (this.readUint8() << 16) + (this.readUint8() << 8) + this.readUint8(); }; { exports.DataStream = DataStream; } DataStream.prototype.save = function(filename) { var blob = new Blob([this.buffer]); if (window.URL && URL.createObjectURL) { var url = window.URL.createObjectURL(blob); var a = document.createElement("a"); document.body.appendChild(a); a.setAttribute("href", url); a.setAttribute("download", filename); a.setAttribute("target", "_self"); a.click(); window.URL.revokeObjectURL(url); } else { throw "DataStream.save: Can't create object URL."; } }; DataStream.prototype._dynamicSize = true; Object.defineProperty( DataStream.prototype, "dynamicSize", { get: function() { return this._dynamicSize; }, set: function(v) { if (!v) { this._trimAlloc(); } this._dynamicSize = v; } } ); DataStream.prototype.shift = function(offset) { var buf = new ArrayBuffer(this._byteLength - offset); var dst = new Uint8Array(buf); var src = new Uint8Array(this._buffer, offset, dst.length); dst.set(src); this.buffer = buf; this.position -= offset; }; DataStream.prototype.writeInt32Array = function(arr, e) { this._realloc(arr.length * 4); if (arr instanceof Int32Array && this.byteOffset + this.position % arr.BYTES_PER_ELEMENT === 0) { DataStream.memcpy( this._buffer, this.byteOffset + this.position, arr.buffer, 0, arr.byteLength ); this.mapInt32Array(arr.length, e); } else { for (var i2 = 0; i2 < arr.length; i2++) { this.writeInt32(arr[i2], e); } } }; DataStream.prototype.writeInt16Array = function(arr, e) { this._realloc(arr.length * 2); if (arr instanceof Int16Array && this.byteOffset + this.position % arr.BYTES_PER_ELEMENT === 0) { DataStream.memcpy( this._buffer, this.byteOffset + this.position, arr.buffer, 0, arr.byteLength ); this.mapInt16Array(arr.length, e); } else { for (var i2 = 0; i2 < arr.length; i2++) { this.writeInt16(arr[i2], e); } } }; DataStream.prototype.writeInt8Array = function(arr) { this._realloc(arr.length * 1); if (arr instanceof Int8Array && this.byteOffset + this.position % arr.BYTES_PER_ELEMENT === 0) { DataStream.memcpy( this._buffer, this.byteOffset + this.position, arr.buffer, 0, arr.byteLength ); this.mapInt8Array(arr.length); } else { for (var i2 = 0; i2 < arr.length; i2++) { this.writeInt8(arr[i2]); } } }; DataStream.prototype.writeUint32Array = function(arr, e) { this._realloc(arr.length * 4); if (arr instanceof Uint32Array && this.byteOffset + this.position % arr.BYTES_PER_ELEMENT === 0) { DataStream.memcpy( this._buffer, this.byteOffset + this.position, arr.buffer, 0, arr.byteLength ); this.mapUint32Array(arr.length, e); } else { for (var i2 = 0; i2 < arr.length; i2++) { this.writeUint32(arr[i2], e); } } }; DataStream.prototype.writeUint16Array = function(arr, e) { this._realloc(arr.length * 2); if (arr instanceof Uint16Array && this.byteOffset + this.position % arr.BYTES_PER_ELEMENT === 0) { DataStream.memcpy( this._buffer, this.byteOffset + this.position, arr.buffer, 0, arr.byteLength ); this.mapUint16Array(arr.length, e); } else { for (var i2 = 0; i2 < arr.length; i2++) { this.writeUint16(arr[i2], e); } } }; DataStream.prototype.writeUint8Array = function(arr) { this._realloc(arr.length * 1); if (arr instanceof Uint8Array && this.byteOffset + this.position % arr.BYTES_PER_ELEMENT === 0) { DataStream.memcpy( this._buffer, this.byteOffset + this.position, arr.buffer, 0, arr.byteLength ); this.mapUint8Array(arr.length); } else { for (var i2 = 0; i2 < arr.length; i2++) { this.writeUint8(arr[i2]); } } }; DataStream.prototype.writeFloat64Array = function(arr, e) { this._realloc(arr.length * 8); if (arr instanceof Float64Array && this.byteOffset + this.position % arr.BYTES_PER_ELEMENT === 0) { DataStream.memcpy( this._buffer, this.byteOffset + this.position, arr.buffer, 0, arr.byteLength ); this.mapFloat64Array(arr.length, e); } else { for (var i2 = 0; i2 < arr.length; i2++) { this.writeFloat64(arr[i2], e); } } }; DataStream.prototype.writeFloat32Array = function(arr, e) { this._realloc(arr.length * 4); if (arr instanceof Float32Array && this.byteOffset + this.position % arr.BYTES_PER_ELEMENT === 0) { DataStream.memcpy( this._buffer, this.byteOffset + this.position, arr.buffer, 0, arr.byteLength ); this.mapFloat32Array(arr.length, e); } else { for (var i2 = 0; i2 < arr.length; i2++) { this.writeFloat32(arr[i2], e); } } }; DataStream.prototype.writeInt32 = function(v, e) { this._realloc(4); this._dataView.setInt32(this.position, v, e == null ? this.endianness : e); this.position += 4; }; DataStream.prototype.writeInt16 = function(v, e) { this._realloc(2); this._dataView.setInt16(this.position, v, e == null ? this.endianness : e); this.position += 2; }; DataStream.prototype.writeInt8 = function(v) { this._realloc(1); this._dataView.setInt8(this.position, v); this.position += 1; }; DataStream.prototype.writeUint32 = function(v, e) { this._realloc(4); this._dataView.setUint32(this.position, v, e == null ? this.endianness : e); this.position += 4; }; DataStream.prototype.writeUint16 = function(v, e) { this._realloc(2); this._dataView.setUint16(this.position, v, e == null ? this.endianness : e); this.position += 2; }; DataStream.prototype.writeUint8 = function(v) { this._realloc(1); this._dataView.setUint8(this.position, v); this.position += 1; }; DataStream.prototype.writeFloat32 = function(v, e) { this._realloc(4); this._dataView.setFloat32(this.position, v, e == null ? this.endianness : e); this.position += 4; }; DataStream.prototype.writeFloat64 = function(v, e) { this._realloc(8); this._dataView.setFloat64(this.position, v, e == null ? this.endianness : e); this.position += 8; }; DataStream.prototype.writeUCS2String = function(str, endianness, lengthOverride) { if (lengthOverride == null) { lengthOverride = str.length; } for (var i2 = 0; i2 < str.length && i2 < lengthOverride; i2++) { this.writeUint16(str.charCodeAt(i2), endianness); } for (; i2 < lengthOverride; i2++) { this.writeUint16(0); } }; DataStream.prototype.writeString = function(s, encoding, length) { var i2 = 0; if (encoding == null || encoding == "ASCII") { if (length != null) { var len = Math.min(s.length, length); for (i2 = 0; i2 < len; i2++) { this.writeUint8(s.charCodeAt(i2)); } for (; i2 < length; i2++) { this.writeUint8(0); } } else { for (i2 = 0; i2 < s.length; i2++) { this.writeUint8(s.charCodeAt(i2)); } } } else { this.writeUint8Array(new TextEncoder(encoding).encode(s.substring(0, length))); } }; DataStream.prototype.writeCString = function(s, length) { var i2 = 0; if (length != null) { var len = Math.min(s.length, length); for (i2 = 0; i2 < len; i2++) { this.writeUint8(s.charCodeAt(i2)); } for (; i2 < length; i2++) { this.writeUint8(0); } } else { for (i2 = 0; i2 < s.length; i2++) { this.writeUint8(s.charCodeAt(i2)); } this.writeUint8(0); } }; DataStream.prototype.writeStruct = function(structDefinition, struct) { for (var i2 = 0; i2 < structDefinition.length; i2 += 2) { var t = structDefinition[i2 + 1]; this.writeType(t, struct[structDefinition[i2]], struct); } }; DataStream.prototype.writeType = function(t, v, struct) { var tp; if (typeof t == "function") { return t(this, v); } else if (typeof t == "object" && !(t instanceof Array)) { return t.set(this, v, struct); } var lengthOverride = null; var charset = "ASCII"; var pos = this.position; if (typeof t == "string" && /:/.test(t)) { tp = t.split(":"); t = tp[0]; lengthOverride = parseInt(tp[1]); } if (typeof t == "string" && /,/.test(t)) { tp = t.split(","); t = tp[0]; charset = parseInt(tp[1]); } switch (t) { case "uint8": this.writeUint8(v); break; case "int8": this.writeInt8(v); break; case "uint16": this.writeUint16(v, this.endianness); break; case "int16": this.writeInt16(v, this.endianness); break; case "uint32": this.writeUint32(v, this.endianness); break; case "int32": this.writeInt32(v, this.endianness); break; case "float32": this.writeFloat32(v, this.endianness); break; case "float64": this.writeFloat64(v, this.endianness); break; case "uint16be": this.writeUint16(v, DataStream.BIG_ENDIAN); break; case "int16be": this.writeInt16(v, DataStream.BIG_ENDIAN); break; case "uint32be": this.writeUint32(v, DataStream.BIG_ENDIAN); break; case "int32be": this.writeInt32(v, DataStream.BIG_ENDIAN); break; case "float32be": this.writeFloat32(v, DataStream.BIG_ENDIAN); break; case "float64be": this.writeFloat64(v, DataStream.BIG_ENDIAN); break; case "uint16le": this.writeUint16(v, DataStream.LITTLE_ENDIAN); break; case "int16le": this.writeInt16(v, DataStream.LITTLE_ENDIAN); break; case "uint32le": this.writeUint32(v, DataStream.LITTLE_ENDIAN); break; case "int32le": this.writeInt32(v, DataStream.LITTLE_ENDIAN); break; case "float32le": this.writeFloat32(v, DataStream.LITTLE_ENDIAN); break; case "float64le": this.writeFloat64(v, DataStream.LITTLE_ENDIAN); break; case "cstring": this.writeCString(v, lengthOverride); break; case "string": this.writeString(v, charset, lengthOverride); break; case "u16string": this.writeUCS2String(v, this.endianness, lengthOverride); break; case "u16stringle": this.writeUCS2String(v, DataStream.LITTLE_ENDIAN, lengthOverride); break; case "u16stringbe": this.writeUCS2String(v, DataStream.BIG_ENDIAN, lengthOverride); break; default: if (t.length == 3) { var ta = t[1]; for (var i2 = 0; i2 < v.length; i2++) { this.writeType(ta, v[i2]); } break; } else { this.writeStruct(t, v); break; } } if (lengthOverride != null) { this.position = pos; this._realloc(lengthOverride); this.position = pos + lengthOverride; } }; DataStream.prototype.writeUint64 = function(v) { var h = Math.floor(v / MAX_SIZE); this.writeUint32(h); this.writeUint32(v & 4294967295); }; DataStream.prototype.writeUint24 = function(v) { this.writeUint8((v & 16711680) >> 16); this.writeUint8((v & 65280) >> 8); this.writeUint8(v & 255); }; DataStream.prototype.adjustUint32 = function(position, value) { var pos = this.position; this.seek(position); this.writeUint32(value); this.seek(pos); }; DataStream.prototype.mapInt32Array = function(length, e) { this._realloc(length * 4); var arr = new Int32Array(this._buffer, this.byteOffset + this.position, length); DataStream.arrayToNative(arr, e == null ? this.endianness : e); this.position += length * 4; return arr; }; DataStream.prototype.mapInt16Array = function(length, e) { this._realloc(length * 2); var arr = new Int16Array(this._buffer, this.byteOffset + this.position, length); DataStream.arrayToNative(arr, e == null ? this.endianness : e); this.position += length * 2; return arr; }; DataStream.prototype.mapInt8Array = function(length) { this._realloc(length * 1); var arr = new Int8Array(this._buffer, this.byteOffset + this.position, length); this.position += length * 1; return arr; }; DataStream.prototype.mapUint32Array = function(length, e) { this._realloc(length * 4); var arr = new Uint32Array(this._buffer, this.byteOffset + this.position, length); DataStream.arrayToNative(arr, e == null ? this.endianness : e); this.position += length * 4; return arr; }; DataStream.prototype.mapUint16Array = function(length, e) { this._realloc(length * 2); var arr = new Uint16Array(this._buffer, this.byteOffset + this.position, length); DataStream.arrayToNative(arr, e == null ? this.endianness : e); this.position += length * 2; return arr; }; DataStream.prototype.mapFloat64Array = function(length, e) { this._realloc(length * 8); var arr = new Float64Array(this._buffer, this.byteOffset + this.position, length); DataStream.arrayToNative(arr, e == null ? this.endianness : e); this.position += length * 8; return arr; }; DataStream.prototype.mapFloat32Array = function(length, e) { this._realloc(length * 4); var arr = new Float32Array(this._buffer, this.byteOffset + this.position, length); DataStream.arrayToNative(arr, e == null ? this.endianness : e); this.position += length * 4; return arr; }; var MultiBufferStream = function(buffer) { this.buffers = []; this.bufferIndex = -1; if (buffer) { this.insertBuffer(buffer); this.bufferIndex = 0; } }; MultiBufferStream.prototype = new DataStream(new ArrayBuffer(), 0, DataStream.BIG_ENDIAN); MultiBufferStream.prototype.initialized = function() { var firstBuffer; if (this.bufferIndex > -1) { return true; } else if (this.buffers.length > 0) { firstBuffer = this.buffers[0]; if (firstBuffer.fileStart === 0) { this.buffer = firstBuffer; this.bufferIndex = 0; Log.debug("MultiBufferStream", "Stream ready for parsing"); return true; } else { Log.warn("MultiBufferStream", "The first buffer should have a fileStart of 0"); this.logBufferLevel(); return false; } } else { Log.warn("MultiBufferStream", "No buffer to start parsing from"); this.logBufferLevel(); return false; } }; ArrayBuffer.concat = function(buffer1, buffer2) { Log.debug("ArrayBuffer", "Trying to create a new buffer of size: " + (buffer1.byteLength + buffer2.byteLength)); var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength); tmp.set(new Uint8Array(buffer1), 0); tmp.set(new Uint8Array(buffer2), buffer1.byteLength); return tmp.buffer; }; MultiBufferStream.prototype.reduceBuffer = function(buffer, offset, newLength) { var smallB; smallB = new Uint8Array(newLength); smallB.set(new Uint8Array(buffer, offset, newLength)); smallB.buffer.fileStart = buffer.fileStart + offset; smallB.buffer.usedBytes = 0; return smallB.buffer; }; MultiBufferStream.prototype.insertBuffer = function(ab) { var to_add = true; for (var i2 = 0; i2 < this.buffers.length; i2++) { var b = this.buffers[i2]; if (ab.fileStart <= b.fileStart) { if (ab.fileStart === b.fileStart) { if (ab.byteLength > b.byteLength) { this.buffers.splice(i2, 1); i2--; continue; } else { Log.warn("MultiBufferStream", "Buffer (fileStart: " + ab.fileStart + " - Length: " + ab.byteLength + ") already appended, ignoring"); } } else { if (ab.fileStart + ab.byteLength <= b.fileStart) ; else { ab = this.reduceBuffer(ab, 0, b.fileStart - ab.fileStart); } Log.debug("MultiBufferStream", "Appending new buffer (fileStart: " + ab.fileStart + " - Length: " + ab.byteLength + ")"); this.buffers.splice(i2, 0, ab); if (i2 === 0) { this.buffer = ab; } } to_add = false; break; } else if (ab.fileStart < b.fileStart + b.byteLength) { var offset = b.fileStart + b.byteLength - ab.fileStart; var newLength = ab.byteLength - offset; if (newLength > 0) { ab = this.reduceBuffer(ab, offset, newLength); } else { to_add = false; break; } } } if (to_add) { Log.debug("MultiBufferStream", "Appending new buffer (fileStart: " + ab.fileStart + " - Length: " + ab.byteLength + ")"); this.buffers.push(ab); if (i2 === 0) { this.buffer = ab; } } }; MultiBufferStream.prototype.logBufferLevel = function(info) { var i2; var buffer; var used, total; var ranges = []; var range; var bufferedString = ""; used = 0; total = 0; for (i2 = 0; i2 < this.buffers.length; i2++) { buffer = this.buffers[i2]; if (i2 === 0) { range = {}; ranges.push(range); range.start = buffer.fileStart; range.end = buffer.fileStart + buffer.byteLength; bufferedString += "[" + range.start + "-"; } else if (range.end === buffer.fileStart) { range.end = buffer.fileStart + buffer.byteLength; } else { range = {}; range.start = buffer.fileStart; bufferedString += ranges[ranges.length - 1].end - 1 + "], [" + range.start + "-"; range.end = buffer.fileStart + buffer.byteLength; ranges.push(range); } used += buffer.usedBytes; total += buffer.byteLength; } if (ranges.length > 0) { bufferedString += range.end - 1 + "]"; } var log = info ? Log.info : Log.debug; if (this.buffers.length === 0) { log("MultiBufferStream", "No more buffer in memory"); } else { log("MultiBufferStream", "" + this.buffers.length + " stored buffer(s) (" + used + "/" + total + " bytes), continuous ranges: " + bufferedString); } }; MultiBufferStream.prototype.cleanBuffers = function() { var i2; var buffer; for (i2 = 0; i2 < this.buffers.length; i2++) { buffer = this.buffers[i2]; if (buffer.usedBytes === buffer.byteLength) { Log.debug("MultiBufferStream", "Removing buffer #" + i2); this.buffers.splice(i2, 1); i2--; } } }; MultiBufferStream.prototype.mergeNextBuffer = function() { var next_buffer; if (this.bufferIndex + 1 < this.buffers.length) { next_buffer = this.buffers[this.bufferIndex + 1]; if (next_buffer.fileStart === this.buffer.fileStart + this.buffer.byteLength) { var oldLength = this.buffer.byteLength; var oldUsedBytes = this.buffer.usedBytes; var oldFileStart = this.buffer.fileStart; this.buffers[this.bufferIndex] = ArrayBuffer.concat(this.buffer, next_buffer); this.buffer = this.buffers[this.bufferIndex]; this.buffers.splice(this.bufferIndex + 1, 1); this.buffer.usedBytes = oldUsedBytes; this.buffer.fileStart = oldFileStart; Log.debug("ISOFile", "Concatenating buffer for box parsing (length: " + oldLength + "->" + this.buffer.byteLength + ")"); return true; } else { return false; } } else { return false; } }; MultiBufferStream.prototype.findPosition = function(fromStart, filePosition, markAsUsed) { var i2; var abuffer = null; var index = -1; if (fromStart === true) { i2 = 0; } else { i2 = this.bufferIndex; } while (i2 < this.buffers.length) { abuffer = this.buffers[i2]; if (abuffer.fileStart <= filePosition) { index = i2; if (markAsUsed) { if (abuffer.fileStart + abuffer.byteLength <= filePosition) { abuffer.usedBytes = abuffer.byteLength; } else { abuffer.usedBytes = filePosition - abuffer.fileStart; } this.logBufferLevel(); } } else { break; } i2++; } if (index !== -1) { abuffer = this.buffers[index]; if (abuffer.fileStart + abuffer.byteLength >= filePosition) { Log.debug("MultiBufferStream", "Found position in existing buffer #" + index); return index; } else { return -1; } } else { return -1; } }; MultiBufferStream.prototype.findEndContiguousBuf = function(inputindex) { var i2; var currentBuf; var nextBuf; var index = inputindex !== void 0 ? inputindex : this.bufferIndex; currentBuf = this.buffers[index]; if (this.buffers.length > index + 1) { for (i2 = index + 1; i2 < this.buffers.length; i2++) { nextBuf = this.buffers[i2]; if (nextBuf.fileStart === currentBuf.fileStart + currentBuf.byteLength) { currentBuf = nextBuf; } else { break; } } } return currentBuf.fileStart + currentBuf.byteLength; }; MultiBufferStream.prototype.getEndFilePositionAfter = function(pos) { var index = this.findPosition(true, pos, false); if (index !== -1) { return this.findEndContiguousBuf(index); } else { return pos; } }; MultiBufferStream.prototype.addUsedBytes = function(nbBytes) { this.buffer.usedBytes += nbBytes; this.logBufferLevel(); }; MultiBufferStream.prototype.setAllUsedBytes = function() { this.buffer.usedBytes = this.buffer.byteLength; this.logBufferLevel(); }; MultiBufferStream.prototype.seek = function(filePosition, fromStart, markAsUsed) { var index; index = this.findPosition(fromStart, filePosition, markAsUsed); if (index !== -1) { this.buffer = this.buffers[index]; this.bufferIndex = index; this.position = filePosition - this.buffer.fileStart; Log.debug("MultiBufferStream", "Repositioning parser at buffer position: " + this.position); return true; } else { Log.debug("MultiBufferStream", "Position " + filePosition + " not found in buffered data"); return false; } }; MultiBufferStream.prototype.getPosition = function() { if (this.bufferIndex === -1 || this.buffers[this.bufferIndex] === null) { throw "Error accessing position in the MultiBufferStream"; } return this.buffers[this.bufferIndex].fileStart + this.position; }; MultiBufferStream.prototype.getLength = function() { return this.byteLength; }; MultiBufferStream.prototype.getEndPosition = function() { if (this.bufferIndex === -1 || this.buffers[this.bufferIndex] === null) { throw "Error accessing position in the MultiBufferStream"; } return this.buffers[this.bufferIndex].fileStart + this.byteLength; }; { exports.MultiBufferStream = MultiBufferStream; } var MPEG4DescriptorParser = function() { var ES_DescrTag = 3; var DecoderConfigDescrTag = 4; var DecSpecificInfoTag = 5; var SLConfigDescrTag = 6; var descTagToName = []; descTagToName[ES_DescrTag] = "ES_Descriptor"; descTagToName[DecoderConfigDescrTag] = "DecoderConfigDescriptor"; descTagToName[DecSpecificInfoTag] = "DecoderSpecificInfo"; descTagToName[SLConfigDescrTag] = "SLConfigDescriptor"; this.getDescriptorName = function(tag) { return descTagToName[tag]; }; var that = this; var classes = {}; this.parseOneDescriptor = function(stream) { var size = 0; var tag; var desc; var byteRead; tag = stream.readUint8(); byteRead = stream.readUint8(); while (byteRead & 128) { size = (size << 7) + (byteRead & 127); byteRead = stream.readUint8(); } size = (size << 7) + (byteRead & 127); Log.debug("MPEG4DescriptorParser", "Found " + (descTagToName[tag] || "Descriptor " + tag) + ", size " + size + " at position " + stream.getPosition()); if (descTagToName[tag]) { desc = new classes[descTagToName[tag]](size); } else { desc = new classes.Descriptor(size); } desc.parse(stream); return desc; }; classes.Descriptor = function(_tag, _size) { this.tag = _tag; this.size = _size; this.descs = []; }; classes.Descriptor.prototype.parse = function(stream) { this.data = stream.readUint8Array(this.size); }; classes.Descriptor.prototype.findDescriptor = function(tag) { for (var i2 = 0; i2 < this.descs.length; i2++) { if (this.descs[i2].tag == tag) { return this.descs[i2]; } } return null; }; classes.Descriptor.prototype.parseRemainingDescriptors = function(stream) { var start = stream.position; while (stream.position < start + this.size) { var desc = that.parseOneDescriptor(stream); this.descs.push(desc); } }; classes.ES_Descriptor = function(size) { classes.Descriptor.call(this, ES_DescrTag, size); }; classes.ES_Descriptor.prototype = new classes.Descriptor(); classes.ES_Descriptor.prototype.parse = function(stream) { this.ES_ID = stream.readUint16(); this.flags = stream.readUint8(); this.size -= 3; if (this.flags & 128) { this.dependsOn_ES_ID = stream.readUint16(); this.size -= 2; } else { this.dependsOn_ES_ID = 0; } if (this.flags & 64) { var l = stream.readUint8(); this.URL = stream.readString(l); this.size -= l + 1; } else { this.URL = ""; } if (this.flags & 32) { this.OCR_ES_ID = stream.readUint16(); this.size -= 2; } else { this.OCR_ES_ID = 0; } this.parseRemainingDescriptors(stream); }; classes.ES_Descriptor.prototype.getOTI = function(stream) { var dcd = this.findDescriptor(DecoderConfigDescrTag); if (dcd) { return dcd.oti; } else { return 0; } }; classes.ES_Descriptor.prototype.getAudioConfig = function(stream) { var dcd = this.findDescriptor(DecoderConfigDescrTag); if (!dcd) return null; var dsi = dcd.findDescriptor(DecSpecificInfoTag); if (dsi && dsi.data) { var audioObjectType = (dsi.data[0] & 248) >> 3; if (audioObjectType === 31 && dsi.data.length >= 2) { audioObjectType = 32 + ((dsi.data[0] & 7) << 3) + ((dsi.data[1] & 224) >> 5); } return audioObjectType; } else { return null; } }; classes.DecoderConfigDescriptor = function(size) { classes.Descriptor.call(this, DecoderConfigDescrTag, size); }; classes.DecoderConfigDescriptor.prototype = new classes.Descriptor(); classes.DecoderConfigDescriptor.prototype.parse = function(stream) { this.oti = stream.readUint8(); this.streamType = stream.readUint8(); this.upStream = (this.streamType >> 1 & 1) !== 0; this.streamType = this.streamType >>> 2; this.bufferSize = stream.readUint24(); this.maxBitrate = stream.readUint32(); this.avgBitrate = stream.readUint32(); this.size -= 13; this.parseRemainingDescriptors(stream); }; classes.DecoderSpecificInfo = function(size) { classes.Descriptor.call(this, DecSpecificInfoTag, size); }; classes.DecoderSpecificInfo.prototype = new classes.Descriptor(); classes.SLConfigDescriptor = function(size) { classes.Descriptor.call(this, SLConfigDescrTag, size); }; classes.SLConfigDescriptor.prototype = new classes.Descriptor(); return this; }; { exports.MPEG4DescriptorParser = MPEG4DescriptorParser; } var BoxParser = { ERR_INVALID_DATA: -1, ERR_NOT_ENOUGH_DATA: 0, OK: 1, // Boxes to be created with default parsing BASIC_BOXES: [ { type: "mdat", name: "MediaDataBox" }, { type: "idat", name: "ItemDataBox" }, { type: "free", name: "FreeSpaceBox" }, { type: "skip", name: "FreeSpaceBox" }, { type: "meco", name: "AdditionalMetadataContainerBox" }, { type: "strk", name: "SubTrackBox" } ], FULL_BOXES: [ { type: "hmhd", name: "HintMediaHeaderBox" }, { type: "nmhd", name: "NullMediaHeaderBox" }, { type: "iods", name: "ObjectDescriptorBox" }, { type: "xml ", name: "XMLBox" }, { type: "bxml", name: "BinaryXMLBox" }, { type: "ipro", name: "ItemProtectionBox" }, { type: "mere", name: "MetaboxRelationBox" } ], CONTAINER_BOXES: [ [{ type: "moov", name: "CompressedMovieBox" }, ["trak", "pssh"]], [{ type: "trak", name: "TrackBox" }], [{ type: "edts", name: "EditBox" }], [{ type: "mdia", name: "MediaBox" }], [{ type: "minf", name: "MediaInformationBox" }], [{ type: "dinf", name: "DataInformationBox" }], [{ type: "stbl", name: "SampleTableBox" }, ["sgpd", "sbgp"]], [{ type: "mvex", name: "MovieExtendsBox" }, ["trex"]], [{ type: "moof", name: "CompressedMovieFragmentBox" }, ["traf"]], [{ type: "traf", name: "TrackFragmentBox" }, ["trun", "sgpd", "sbgp"]], [{ type: "vttc", name: "VTTCueBox" }], [{ type: "tref", name: "TrackReferenceBox" }], [{ type: "iref", name: "ItemReferenceBox" }], [{ type: "mfra", name: "MovieFragmentRandomAccessBox" }, ["tfra"]], [{ type: "meco", name: "AdditionalMetadataContainerBox" }], [{ type: "hnti", name: "trackhintinformation" }], [{ type: "hinf", name: "hintstatisticsbox" }], [{ type: "strk", name: "SubTrackBox" }], [{ type: "strd", name: "SubTrackDefinitionBox" }], [{ type: "sinf", name: "ProtectionSchemeInfoBox" }], [{ type: "rinf", name: "RestrictedSchemeInfoBox" }], [{ type: "schi", name: "SchemeInformationBox" }], [{ type: "trgr", name: "TrackGroupBox" }], [{ type: "udta", name: "UserDataBox" }, ["kind"]], [{ type: "iprp", name: "ItemPropertiesBox" }, ["ipma"]], [{ type: "ipco", name: "ItemPropertyContainerBox" }], [{ type: "grpl", name: "GroupsListBox" }], [{ type: "j2kH", name: "J2KHeaderInfoBox" }], [{ type: "etyp", name: "ExtendedTypeBox" }, ["tyco"]] ], // Boxes effectively created boxCodes: [], fullBoxCodes: [], containerBoxCodes: [], sampleEntryCodes: {}, sampleGroupEntryCodes: [], trackGroupTypes: [], UUIDBoxes: {}, UUIDs: [],