view release on metacpan or search on metacpan
share/public_html/static/hls.js view on Meta::CPAN
// Identifier for a buffer seek over hole event
BUFFER_SEEK_OVER_HOLE: 'bufferSeekOverHole',
// Identifier for a buffer nudge on stall (playback is stuck although currentTime is in a buffered area)
BUFFER_NUDGE_ON_STALL: 'bufferNudgeOnStall',
// Identifier for an internal exception happening inside hls.js while handling an event
INTERNAL_EXCEPTION: 'internalException'
};
/***/ }),
/* 3 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = getSelfScope;
function getSelfScope() {
// see https://stackoverflow.com/a/11237259/589493
if (typeof window === 'undefined') {
/* eslint-disable-next-line no-undef */
return self;
} else {
return window;
}
}
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
// see https://tools.ietf.org/html/rfc1808
/* jshint ignore:start */
(function(root) {
/* jshint ignore:end */
var URL_REGEX = /^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/\;?#]*)?(.*?)??(;.*?)?(\?.*?)?(#.*?)?$/;
var FIRST_SEGMENT_REGEX = /^([^\/;?#]*)(.*)$/;
var SLASH_DOT_REGEX = /(?:\/|^)\.(?=\/)/g;
var SLASH_DOT_DOT_REGEX = /(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g;
var URLToolkit = { // jshint ignore:line
// If opts.alwaysNormalize is true then the path will always be normalized even when it starts with / or //
// E.g
// With opts.alwaysNormalize = false (default, spec compliant)
// http://a.com/b/cd + /e/f/../g => http://a.com/e/f/../g
// With opts.alwaysNormalize = true (not spec compliant)
// http://a.com/b/cd + /e/f/../g => http://a.com/e/g
buildAbsoluteURL: function(baseURL, relativeURL, opts) {
opts = opts || {};
// remove any remaining space and CRLF
baseURL = baseURL.trim();
relativeURL = relativeURL.trim();
if (!relativeURL) {
// 2a) If the embedded URL is entirely empty, it inherits the
// entire base URL (i.e., is set equal to the base URL)
// and we are done.
if (!opts.alwaysNormalize) {
return baseURL;
}
var basePartsForNormalise = this.parseURL(baseURL);
if (!baseParts) {
throw new Error('Error trying to parse base URL.');
}
basePartsForNormalise.path = URLToolkit.normalizePath(basePartsForNormalise.path);
return URLToolkit.buildURLFromParts(basePartsForNormalise);
}
var relativeParts = this.parseURL(relativeURL);
if (!relativeParts) {
throw new Error('Error trying to parse relative URL.');
}
if (relativeParts.scheme) {
// 2b) If the embedded URL starts with a scheme name, it is
// interpreted as an absolute URL and we are done.
if (!opts.alwaysNormalize) {
return relativeURL;
}
relativeParts.path = URLToolkit.normalizePath(relativeParts.path);
return URLToolkit.buildURLFromParts(relativeParts);
}
var baseParts = this.parseURL(baseURL);
if (!baseParts) {
throw new Error('Error trying to parse base URL.');
}
if (!baseParts.netLoc && baseParts.path && baseParts.path[0] !== '/') {
// If netLoc missing and path doesn't start with '/', assume everthing before the first '/' is the netLoc
// This causes 'example.com/a' to be handled as '//example.com/a' instead of '/example.com/a'
var pathParts = FIRST_SEGMENT_REGEX.exec(baseParts.path);
baseParts.netLoc = pathParts[1];
baseParts.path = pathParts[2];
}
if (baseParts.netLoc && !baseParts.path) {
baseParts.path = '/';
}
var builtParts = {
// 2c) Otherwise, the embedded URL inherits the scheme of
// the base URL.
scheme: baseParts.scheme,
netLoc: relativeParts.netLoc,
path: null,
params: relativeParts.params,
query: relativeParts.query,
fragment: relativeParts.fragment
};
if (!relativeParts.netLoc) {
// 3) If the embedded URL's <net_loc> is non-empty, we skip to
// Step 7. Otherwise, the embedded URL inherits the <net_loc>
// (if any) of the base URL.
builtParts.netLoc = baseParts.netLoc;
// 4) If the embedded URL path is preceded by a slash "/", the
// path is not relative and we skip to Step 7.
if (relativeParts.path[0] !== '/') {
if (!relativeParts.path) {
// 5) If the embedded URL path is empty (and not preceded by a
// slash), then the embedded URL inherits the base URL path
builtParts.path = baseParts.path;
// 5a) if the embedded URL's <params> is non-empty, we skip to
// step 7; otherwise, it inherits the <params> of the base
// URL (if any) and
if (!relativeParts.params) {
builtParts.params = baseParts.params;
// 5b) if the embedded URL's <query> is non-empty, we skip to
// step 7; otherwise, it inherits the <query> of the base
// URL (if any) and we skip to step 7.
if (!relativeParts.query) {
builtParts.query = baseParts.query;
}
}
} else {
// 6) The last segment of the base URL's path (anything
// following the rightmost slash "/", or the entire path if no
// slash is present) is removed and the embedded URL's path is
// appended in its place.
var baseURLPath = baseParts.path;
var newPath = baseURLPath.substring(0, baseURLPath.lastIndexOf('/') + 1) + relativeParts.path;
builtParts.path = URLToolkit.normalizePath(newPath);
}
}
}
if (builtParts.path === null) {
builtParts.path = opts.alwaysNormalize ? URLToolkit.normalizePath(relativeParts.path) : relativeParts.path;
}
return URLToolkit.buildURLFromParts(builtParts);
},
parseURL: function(url) {
var parts = URL_REGEX.exec(url);
if (!parts) {
return null;
}
return {
scheme: parts[1] || '',
netLoc: parts[2] || '',
path: parts[3] || '',
params: parts[4] || '',
query: parts[5] || '',
fragment: parts[6] || ''
};
},
normalizePath: function(path) {
// The following operations are
// then applied, in order, to the new path:
// 6a) All occurrences of "./", where "." is a complete path
// segment, are removed.
// 6b) If the path ends with "." as a complete path segment,
// that "." is removed.
path = path.split('').reverse().join('').replace(SLASH_DOT_REGEX, '');
// 6c) All occurrences of "<segment>/../", where <segment> is a
// complete path segment not equal to "..", are removed.
// Removal of these path segments is performed iteratively,
// removing the leftmost matching pattern on each iteration,
// until no matching pattern remains.
// 6d) If the path ends with "<segment>/..", where <segment> is a
// complete path segment not equal to "..", that
// "<segment>/.." is removed.
while (path.length !== (path = path.replace(SLASH_DOT_DOT_REGEX, '')).length) {} // jshint ignore:line
return path.split('').reverse().join('');
},
buildURLFromParts: function(parts) {
return parts.scheme + parts.netLoc + parts.path + parts.params + parts.query + parts.fragment;
}
};
/* jshint ignore:start */
if(true)
module.exports = URLToolkit;
else if(typeof define === 'function' && define.amd)
define([], function() { return URLToolkit; });
else if(typeof exports === 'object')
exports["URLToolkit"] = URLToolkit;
else
root["URLToolkit"] = URLToolkit;
})(this);
/* jshint ignore:end */
/***/ }),
/* 5 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return utf8ArrayToStr; });
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* ID3 parser
*/
var ID3 = function () {
function ID3() {
_classCallCheck(this, ID3);
}
/**
* Returns true if an ID3 header can be found at offset in data
* @param {Uint8Array} data - The data to search in
* @param {number} offset - The offset at which to start searching
* @return {boolean} - True if an ID3 header is found
*/
ID3.isHeader = function isHeader(data, offset) {
/*
* http://id3.org/id3v2.3.0
* [0] = 'I'
* [1] = 'D'
* [2] = '3'
* [3,4] = {Version}
* [5] = {Flags}
* [6-9] = {ID3 Size}
*
* An ID3v2 tag can be detected with the following pattern:
* $49 44 33 yy yy xx zz zz zz zz
* Where yy is less than $FF, xx is the 'flags' byte and zz is less than $80
*/
if (offset + 10 <= data.length) {
// look for 'ID3' identifier
if (data[offset] === 0x49 && data[offset + 1] === 0x44 && data[offset + 2] === 0x33) {
// check version is within range
if (data[offset + 3] < 0xFF && data[offset + 4] < 0xFF) {
// check size is within range
if (data[offset + 6] < 0x80 && data[offset + 7] < 0x80 && data[offset + 8] < 0x80 && data[offset + 9] < 0x80) {
return true;
}
}
}
}
return false;
};
/**
* Returns true if an ID3 footer can be found at offset in data
* @param {Uint8Array} data - The data to search in
* @param {number} offset - The offset at which to start searching
* @return {boolean} - True if an ID3 footer is found
*/
ID3.isFooter = function isFooter(data, offset) {
/*
* The footer is a copy of the header, but with a different identifier
*/
if (offset + 10 <= data.length) {
// look for '3DI' identifier
if (data[offset] === 0x33 && data[offset + 1] === 0x44 && data[offset + 2] === 0x49) {
share/public_html/static/hls.js view on Meta::CPAN
default:
}
}
return out;
};
return ID3;
}();
var utf8ArrayToStr = ID3._utf8ArrayToStr;
/* harmony default export */ __webpack_exports__["a"] = (ID3);
/***/ }),
/* 6 */
/***/ (function(module, exports) {
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
function EventEmitter() {
this._events = this._events || {};
this._maxListeners = this._maxListeners || undefined;
}
module.exports = EventEmitter;
// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = undefined;
EventEmitter.prototype._maxListeners = undefined;
// By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.
EventEmitter.defaultMaxListeners = 10;
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function(n) {
if (!isNumber(n) || n < 0 || isNaN(n))
throw TypeError('n must be a positive number');
this._maxListeners = n;
return this;
};
EventEmitter.prototype.emit = function(type) {
var er, handler, len, args, i, listeners;
if (!this._events)
this._events = {};
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this._events.error ||
(isObject(this._events.error) && !this._events.error.length)) {
er = arguments[1];
if (er instanceof Error) {
throw er; // Unhandled 'error' event
} else {
// At least give some kind of context to the user
var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
err.context = er;
throw err;
}
}
}
handler = this._events[type];
if (isUndefined(handler))
return false;
if (isFunction(handler)) {
switch (arguments.length) {
// fast cases
case 1:
handler.call(this);
break;
case 2:
handler.call(this, arguments[1]);
break;
case 3:
handler.call(this, arguments[1], arguments[2]);
break;
// slower
default:
args = Array.prototype.slice.call(arguments, 1);
handler.apply(this, args);
}
} else if (isObject(handler)) {
args = Array.prototype.slice.call(arguments, 1);
listeners = handler.slice();
len = listeners.length;
for (i = 0; i < len; i++)
listeners[i].apply(this, args);
}
return true;
};
EventEmitter.prototype.addListener = function(type, listener) {
var m;
if (!isFunction(listener))
throw TypeError('listener must be a function');
if (!this._events)
this._events = {};
// To avoid recursion in the case that type === "newListener"! Before
// adding it to the listeners, first emit "newListener".
if (this._events.newListener)
this.emit('newListener', type,
isFunction(listener.listener) ?
listener.listener : listener);
if (!this._events[type])
// Optimize the case of one listener. Don't need the extra array object.
this._events[type] = listener;
else if (isObject(this._events[type]))
// If we've already got an array, just append.
this._events[type].push(listener);
else
// Adding the second element, need to change to array.
this._events[type] = [this._events[type], listener];
// Check for listener leak
if (isObject(this._events[type]) && !this._events[type].warned) {
if (!isUndefined(this._maxListeners)) {
m = this._maxListeners;
} else {
m = EventEmitter.defaultMaxListeners;
}
if (m && m > 0 && this._events[type].length > m) {
this._events[type].warned = true;
console.error('(node) warning: possible EventEmitter memory ' +
'leak detected. %d listeners added. ' +
'Use emitter.setMaxListeners() to increase limit.',
this._events[type].length);
if (typeof console.trace === 'function') {
// not supported in IE 10
console.trace();
}
}
}
return this;
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.once = function(type, listener) {
if (!isFunction(listener))
throw TypeError('listener must be a function');
var fired = false;
function g() {
this.removeListener(type, g);
if (!fired) {
fired = true;
listener.apply(this, arguments);
}
}
g.listener = listener;
this.on(type, g);
return this;
};
// emits a 'removeListener' event iff the listener was removed
EventEmitter.prototype.removeListener = function(type, listener) {
var list, position, length, i;
if (!isFunction(listener))
throw TypeError('listener must be a function');
if (!this._events || !this._events[type])
return this;
list = this._events[type];
length = list.length;
position = -1;
if (list === listener ||
(isFunction(list.listener) && list.listener === listener)) {
delete this._events[type];
if (this._events.removeListener)
this.emit('removeListener', type, listener);
} else if (isObject(list)) {
for (i = length; i-- > 0;) {
if (list[i] === listener ||
(list[i].listener && list[i].listener === listener)) {
position = i;
break;
}
}
if (position < 0)
return this;
if (list.length === 1) {
list.length = 0;
delete this._events[type];
} else {
list.splice(position, 1);
}
if (this._events.removeListener)
this.emit('removeListener', type, listener);
}
return this;
};
EventEmitter.prototype.removeAllListeners = function(type) {
var key, listeners;
if (!this._events)
return this;
// not listening for removeListener, no need to emit
if (!this._events.removeListener) {
if (arguments.length === 0)
this._events = {};
else if (this._events[type])
delete this._events[type];
return this;
}
// emit removeListener for all listeners on all events
if (arguments.length === 0) {
for (key in this._events) {
if (key === 'removeListener') continue;
this.removeAllListeners(key);
share/public_html/static/hls.js view on Meta::CPAN
// LIFO order
while (listeners.length)
this.removeListener(type, listeners[listeners.length - 1]);
}
delete this._events[type];
return this;
};
EventEmitter.prototype.listeners = function(type) {
var ret;
if (!this._events || !this._events[type])
ret = [];
else if (isFunction(this._events[type]))
ret = [this._events[type]];
else
ret = this._events[type].slice();
return ret;
};
EventEmitter.prototype.listenerCount = function(type) {
if (this._events) {
var evlistener = this._events[type];
if (isFunction(evlistener))
return 1;
else if (evlistener)
return evlistener.length;
}
return 0;
};
EventEmitter.listenerCount = function(emitter, type) {
return emitter.listenerCount(type);
};
function isFunction(arg) {
return typeof arg === 'function';
}
function isNumber(arg) {
return typeof arg === 'number';
}
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
function isUndefined(arg) {
return arg === void 0;
}
/***/ }),
/* 7 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
// CONCATENATED MODULE: ./src/crypt/aes-crypto.js
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var AESCrypto = function () {
function AESCrypto(subtle, iv) {
_classCallCheck(this, AESCrypto);
this.subtle = subtle;
this.aesIV = iv;
}
AESCrypto.prototype.decrypt = function decrypt(data, key) {
return this.subtle.decrypt({ name: 'AES-CBC', iv: this.aesIV }, key, data);
};
return AESCrypto;
}();
/* harmony default export */ var aes_crypto = (AESCrypto);
// CONCATENATED MODULE: ./src/crypt/fast-aes-key.js
function fast_aes_key__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var FastAESKey = function () {
function FastAESKey(subtle, key) {
fast_aes_key__classCallCheck(this, FastAESKey);
this.subtle = subtle;
this.key = key;
}
FastAESKey.prototype.expandKey = function expandKey() {
return this.subtle.importKey('raw', this.key, { name: 'AES-CBC' }, false, ['encrypt', 'decrypt']);
};
return FastAESKey;
}();
/* harmony default export */ var fast_aes_key = (FastAESKey);
// CONCATENATED MODULE: ./src/crypt/aes-decryptor.js
function aes_decryptor__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
// PKCS7
function removePadding(buffer) {
var outputBytes = buffer.byteLength;
var paddingBytes = outputBytes && new DataView(buffer).getUint8(outputBytes - 1);
if (paddingBytes) {
return buffer.slice(0, outputBytes - paddingBytes);
} else {
return buffer;
}
}
var AESDecryptor = function () {
function AESDecryptor() {
aes_decryptor__classCallCheck(this, AESDecryptor);
// Static after running initTable
this.rcon = [0x0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
this.subMix = [new Uint32Array(256), new Uint32Array(256), new Uint32Array(256), new Uint32Array(256)];
this.invSubMix = [new Uint32Array(256), new Uint32Array(256), new Uint32Array(256), new Uint32Array(256)];
this.sBox = new Uint32Array(256);
this.invSBox = new Uint32Array(256);
// Changes during runtime
this.key = new Uint32Array(0);
this.initTable();
}
// Using view.getUint32() also swaps the byte order.
AESDecryptor.prototype.uint8ArrayToUint32Array_ = function uint8ArrayToUint32Array_(arrayBuffer) {
var view = new DataView(arrayBuffer);
var newArray = new Uint32Array(4);
for (var i = 0; i < 4; i++) {
newArray[i] = view.getUint32(i * 4);
}
return newArray;
};
AESDecryptor.prototype.initTable = function initTable() {
var sBox = this.sBox;
var invSBox = this.invSBox;
var subMix = this.subMix;
var subMix0 = subMix[0];
var subMix1 = subMix[1];
var subMix2 = subMix[2];
var subMix3 = subMix[3];
var invSubMix = this.invSubMix;
var invSubMix0 = invSubMix[0];
var invSubMix1 = invSubMix[1];
var invSubMix2 = invSubMix[2];
var invSubMix3 = invSubMix[3];
var d = new Uint32Array(256);
var x = 0;
var xi = 0;
var i = 0;
share/public_html/static/hls.js view on Meta::CPAN
d[i] = i << 1;
} else {
d[i] = i << 1 ^ 0x11b;
}
}
for (i = 0; i < 256; i++) {
var sx = xi ^ xi << 1 ^ xi << 2 ^ xi << 3 ^ xi << 4;
sx = sx >>> 8 ^ sx & 0xff ^ 0x63;
sBox[x] = sx;
invSBox[sx] = x;
// Compute multiplication
var x2 = d[x];
var x4 = d[x2];
var x8 = d[x4];
// Compute sub/invSub bytes, mix columns tables
var t = d[sx] * 0x101 ^ sx * 0x1010100;
subMix0[x] = t << 24 | t >>> 8;
subMix1[x] = t << 16 | t >>> 16;
subMix2[x] = t << 8 | t >>> 24;
subMix3[x] = t;
// Compute inv sub bytes, inv mix columns tables
t = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100;
invSubMix0[sx] = t << 24 | t >>> 8;
invSubMix1[sx] = t << 16 | t >>> 16;
invSubMix2[sx] = t << 8 | t >>> 24;
invSubMix3[sx] = t;
// Compute next counter
if (!x) {
x = xi = 1;
} else {
x = x2 ^ d[d[d[x8 ^ x2]]];
xi ^= d[d[xi]];
}
}
};
AESDecryptor.prototype.expandKey = function expandKey(keyBuffer) {
// convert keyBuffer to Uint32Array
var key = this.uint8ArrayToUint32Array_(keyBuffer);
var sameKey = true;
var offset = 0;
while (offset < key.length && sameKey) {
sameKey = key[offset] === this.key[offset];
offset++;
}
if (sameKey) {
return;
}
this.key = key;
var keySize = this.keySize = key.length;
if (keySize !== 4 && keySize !== 6 && keySize !== 8) {
throw new Error('Invalid aes key size=' + keySize);
}
var ksRows = this.ksRows = (keySize + 6 + 1) * 4;
var ksRow = void 0;
var invKsRow = void 0;
var keySchedule = this.keySchedule = new Uint32Array(ksRows);
var invKeySchedule = this.invKeySchedule = new Uint32Array(ksRows);
var sbox = this.sBox;
var rcon = this.rcon;
var invSubMix = this.invSubMix;
var invSubMix0 = invSubMix[0];
var invSubMix1 = invSubMix[1];
var invSubMix2 = invSubMix[2];
var invSubMix3 = invSubMix[3];
var prev = void 0;
var t = void 0;
for (ksRow = 0; ksRow < ksRows; ksRow++) {
if (ksRow < keySize) {
prev = keySchedule[ksRow] = key[ksRow];
continue;
}
t = prev;
if (ksRow % keySize === 0) {
// Rot word
t = t << 8 | t >>> 24;
// Sub word
t = sbox[t >>> 24] << 24 | sbox[t >>> 16 & 0xff] << 16 | sbox[t >>> 8 & 0xff] << 8 | sbox[t & 0xff];
// Mix Rcon
t ^= rcon[ksRow / keySize | 0] << 24;
} else if (keySize > 6 && ksRow % keySize === 4) {
// Sub word
t = sbox[t >>> 24] << 24 | sbox[t >>> 16 & 0xff] << 16 | sbox[t >>> 8 & 0xff] << 8 | sbox[t & 0xff];
}
keySchedule[ksRow] = prev = (keySchedule[ksRow - keySize] ^ t) >>> 0;
}
for (invKsRow = 0; invKsRow < ksRows; invKsRow++) {
ksRow = ksRows - invKsRow;
if (invKsRow & 3) {
t = keySchedule[ksRow];
} else {
t = keySchedule[ksRow - 4];
}
if (invKsRow < 4 || ksRow <= 4) {
invKeySchedule[invKsRow] = t;
} else {
invKeySchedule[invKsRow] = invSubMix0[sbox[t >>> 24]] ^ invSubMix1[sbox[t >>> 16 & 0xff]] ^ invSubMix2[sbox[t >>> 8 & 0xff]] ^ invSubMix3[sbox[t & 0xff]];
}
invKeySchedule[invKsRow] = invKeySchedule[invKsRow] >>> 0;
}
share/public_html/static/hls.js view on Meta::CPAN
ksRow = ksRow + 4;
}
// Shift rows, sub bytes, add round key
t0 = invSBOX[s0 >>> 24] << 24 ^ invSBOX[s1 >> 16 & 0xff] << 16 ^ invSBOX[s2 >> 8 & 0xff] << 8 ^ invSBOX[s3 & 0xff] ^ invKeySchedule[ksRow];
t1 = invSBOX[s1 >>> 24] << 24 ^ invSBOX[s2 >> 16 & 0xff] << 16 ^ invSBOX[s3 >> 8 & 0xff] << 8 ^ invSBOX[s0 & 0xff] ^ invKeySchedule[ksRow + 1];
t2 = invSBOX[s2 >>> 24] << 24 ^ invSBOX[s3 >> 16 & 0xff] << 16 ^ invSBOX[s0 >> 8 & 0xff] << 8 ^ invSBOX[s1 & 0xff] ^ invKeySchedule[ksRow + 2];
t3 = invSBOX[s3 >>> 24] << 24 ^ invSBOX[s0 >> 16 & 0xff] << 16 ^ invSBOX[s1 >> 8 & 0xff] << 8 ^ invSBOX[s2 & 0xff] ^ invKeySchedule[ksRow + 3];
ksRow = ksRow + 3;
// Write
outputInt32[offset] = swapWord(t0 ^ initVector0);
outputInt32[offset + 1] = swapWord(t3 ^ initVector1);
outputInt32[offset + 2] = swapWord(t2 ^ initVector2);
outputInt32[offset + 3] = swapWord(t1 ^ initVector3);
// reset initVector to last 4 unsigned int
initVector0 = inputWords0;
initVector1 = inputWords1;
initVector2 = inputWords2;
initVector3 = inputWords3;
offset = offset + 4;
}
return removePKCS7Padding ? removePadding(outputInt32.buffer) : outputInt32.buffer;
};
AESDecryptor.prototype.destroy = function destroy() {
this.key = undefined;
this.keySize = undefined;
this.ksRows = undefined;
this.sBox = undefined;
this.invSBox = undefined;
this.subMix = undefined;
this.invSubMix = undefined;
this.keySchedule = undefined;
this.invKeySchedule = undefined;
this.rcon = undefined;
};
return AESDecryptor;
}();
/* harmony default export */ var aes_decryptor = (AESDecryptor);
// EXTERNAL MODULE: ./src/errors.js
var errors = __webpack_require__(2);
// EXTERNAL MODULE: ./src/utils/logger.js
var logger = __webpack_require__(0);
// EXTERNAL MODULE: ./src/events.js
var events = __webpack_require__(1);
// EXTERNAL MODULE: ./src/utils/get-self-scope.js
var get_self_scope = __webpack_require__(3);
// CONCATENATED MODULE: ./src/crypt/decrypter.js
function decrypter__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
// see https://stackoverflow.com/a/11237259/589493
var global = Object(get_self_scope["a" /* getSelfScope */])(); // safeguard for code that might run both on worker and main thread
var decrypter_Decrypter = function () {
function Decrypter(observer, config) {
var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
_ref$removePKCS7Paddi = _ref.removePKCS7Padding,
removePKCS7Padding = _ref$removePKCS7Paddi === undefined ? true : _ref$removePKCS7Paddi;
decrypter__classCallCheck(this, Decrypter);
this.logEnabled = true;
this.observer = observer;
this.config = config;
this.removePKCS7Padding = removePKCS7Padding;
// built in decryptor expects PKCS7 padding
if (removePKCS7Padding) {
try {
var browserCrypto = global.crypto;
if (browserCrypto) {
this.subtle = browserCrypto.subtle || browserCrypto.webkitSubtle;
}
} catch (e) {}
}
this.disableWebCrypto = !this.subtle;
}
Decrypter.prototype.isSync = function isSync() {
return this.disableWebCrypto && this.config.enableSoftwareAES;
};
Decrypter.prototype.decrypt = function decrypt(data, key, iv, callback) {
var _this = this;
if (this.disableWebCrypto && this.config.enableSoftwareAES) {
if (this.logEnabled) {
logger["b" /* logger */].log('JS AES decrypt');
this.logEnabled = false;
}
var decryptor = this.decryptor;
if (!decryptor) {
this.decryptor = decryptor = new aes_decryptor();
}
decryptor.expandKey(key);
callback(decryptor.decrypt(data, 0, iv, this.removePKCS7Padding));
} else {
if (this.logEnabled) {
logger["b" /* logger */].log('WebCrypto AES decrypt');
this.logEnabled = false;
}
var subtle = this.subtle;
if (this.key !== key) {
this.key = key;
this.fastAesKey = new fast_aes_key(subtle, key);
}
this.fastAesKey.expandKey().then(function (aesKey) {
// decrypt using web crypto
var crypto = new aes_crypto(subtle, iv);
crypto.decrypt(data, aesKey).catch(function (err) {
_this.onWebCryptoError(err, data, key, iv, callback);
}).then(function (result) {
callback(result);
});
}).catch(function (err) {
_this.onWebCryptoError(err, data, key, iv, callback);
});
}
};
Decrypter.prototype.onWebCryptoError = function onWebCryptoError(err, data, key, iv, callback) {
if (this.config.enableSoftwareAES) {
logger["b" /* logger */].log('WebCrypto Error, disable WebCrypto API');
this.disableWebCrypto = true;
this.logEnabled = true;
this.decrypt(data, key, iv, callback);
} else {
logger["b" /* logger */].error('decrypting error : ' + err.message);
this.observer.trigger(events["a" /* default */].ERROR, { type: errors["b" /* ErrorTypes */].MEDIA_ERROR, details: errors["a" /* ErrorDetails */].FRAG_DECRYPT_ERROR, fatal: true, reason: err.message });
}
};
Decrypter.prototype.destroy = function destroy() {
var decryptor = this.decryptor;
if (decryptor) {
decryptor.destroy();
this.decryptor = undefined;
}
};
return Decrypter;
}();
/* harmony default export */ var decrypter = __webpack_exports__["a"] = (decrypter_Decrypter);
/***/ }),
/* 8 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__utils_logger__ = __webpack_require__(0);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__events__ = __webpack_require__(1);
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* MP4 demuxer
*/
var UINT32_MAX = Math.pow(2, 32) - 1;
var MP4Demuxer = function () {
function MP4Demuxer(observer, remuxer) {
_classCallCheck(this, MP4Demuxer);
this.observer = observer;
this.remuxer = remuxer;
}
MP4Demuxer.prototype.resetTimeStamp = function resetTimeStamp(initPTS) {
this.initPTS = initPTS;
};
MP4Demuxer.prototype.resetInitSegment = function resetInitSegment(initSegment, audioCodec, videoCodec, duration) {
// jshint unused:false
if (initSegment && initSegment.byteLength) {
var initData = this.initData = MP4Demuxer.parseInitSegment(initSegment);
// default audio codec if nothing specified
// TODO : extract that from initsegment
if (audioCodec == null) {
audioCodec = 'mp4a.40.5';
}
if (videoCodec == null) {
videoCodec = 'avc1.42e01e';
}
var tracks = {};
if (initData.audio && initData.video) {
tracks.audiovideo = { container: 'video/mp4', codec: audioCodec + ',' + videoCodec, initSegment: duration ? initSegment : null };
} else {
if (initData.audio) {
tracks.audio = { container: 'audio/mp4', codec: audioCodec, initSegment: duration ? initSegment : null };
}
if (initData.video) {
tracks.video = { container: 'video/mp4', codec: videoCodec, initSegment: duration ? initSegment : null };
}
}
this.observer.trigger(__WEBPACK_IMPORTED_MODULE_1__events__["a" /* default */].FRAG_PARSING_INIT_SEGMENT, { tracks: tracks });
} else {
if (audioCodec) {
this.audioCodec = audioCodec;
}
if (videoCodec) {
this.videoCodec = videoCodec;
}
}
};
share/public_html/static/hls.js view on Meta::CPAN
track.samplerate = config.samplerate;
track.channelCount = config.channelCount;
track.codec = config.codec;
track.manifestCodec = config.manifestCodec;
logger["b" /* logger */].log('parsed codec:' + track.codec + ',rate:' + config.samplerate + ',nb channel:' + config.channelCount);
}
}
function getFrameDuration(samplerate) {
return 1024 * 90000 / samplerate;
}
function parseFrameHeader(data, offset, pts, frameIndex, frameDuration) {
var headerLength = void 0,
frameLength = void 0,
stamp = void 0;
var length = data.length;
// The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header
headerLength = getHeaderLength(data, offset);
// retrieve frame size
frameLength = getFullFrameLength(data, offset);
frameLength -= headerLength;
if (frameLength > 0 && offset + headerLength + frameLength <= length) {
stamp = pts + frameIndex * frameDuration;
// logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`);
return { headerLength: headerLength, frameLength: frameLength, stamp: stamp };
}
return undefined;
}
function appendFrame(track, data, offset, pts, frameIndex) {
var frameDuration = getFrameDuration(track.samplerate);
var header = parseFrameHeader(data, offset, pts, frameIndex, frameDuration);
if (header) {
var stamp = header.stamp;
var headerLength = header.headerLength;
var frameLength = header.frameLength;
// logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`);
var aacSample = {
unit: data.subarray(offset + headerLength, offset + headerLength + frameLength),
pts: stamp,
dts: stamp
};
track.samples.push(aacSample);
track.len += frameLength;
return { sample: aacSample, length: frameLength + headerLength };
}
return undefined;
}
// EXTERNAL MODULE: ./src/demux/id3.js
var id3 = __webpack_require__(5);
// CONCATENATED MODULE: ./src/demux/aacdemuxer.js
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* AAC demuxer
*/
var aacdemuxer_AACDemuxer = function () {
function AACDemuxer(observer, remuxer, config) {
_classCallCheck(this, AACDemuxer);
this.observer = observer;
this.config = config;
this.remuxer = remuxer;
}
AACDemuxer.prototype.resetInitSegment = function resetInitSegment(initSegment, audioCodec, videoCodec, duration) {
this._audioTrack = { container: 'audio/adts', type: 'audio', id: 0, sequenceNumber: 0, isAAC: true, samples: [], len: 0, manifestCodec: audioCodec, duration: duration, inputTimeScale: 90000 };
};
AACDemuxer.prototype.resetTimeStamp = function resetTimeStamp() {};
AACDemuxer.probe = function probe(data) {
if (!data) {
return false;
}
// Check for the ADTS sync word
// Look for ADTS header | 1111 1111 | 1111 X00X | where X can be either 0 or 1
// Layer bits (position 14 and 15) in header should be always 0 for ADTS
// More info https://wiki.multimedia.cx/index.php?title=ADTS
var id3Data = id3["a" /* default */].getID3Data(data, 0) || [];
var offset = id3Data.length;
for (var length = data.length; offset < length; offset++) {
if (adts_probe(data, offset)) {
logger["b" /* logger */].log('ADTS sync word found !');
return true;
}
}
return false;
};
// feed incoming data to the front of the parsing pipeline
AACDemuxer.prototype.append = function append(data, timeOffset, contiguous, accurateTimeOffset) {
var track = this._audioTrack;
var id3Data = id3["a" /* default */].getID3Data(data, 0) || [];
var timestamp = id3["a" /* default */].getTimeStamp(id3Data);
var pts = timestamp ? 90 * timestamp : timeOffset * 90000;
var frameIndex = 0;
var stamp = pts;
var length = data.length;
var offset = id3Data.length;
var id3Samples = [{ pts: stamp, dts: stamp, data: id3Data }];
while (offset < length - 1) {
share/public_html/static/hls.js view on Meta::CPAN
var headerC = data[offset + 1] >> 1 & 3;
var headerE = data[offset + 2] >> 4 & 15;
var headerF = data[offset + 2] >> 2 & 3;
var headerG = data[offset + 2] >> 1 & 1;
if (headerB !== 1 && headerE !== 0 && headerE !== 15 && headerF !== 3) {
var columnInBitrates = headerB === 3 ? 3 - headerC : headerC === 3 ? 3 : 4;
var bitRate = MpegAudio.BitratesMap[columnInBitrates * 14 + headerE - 1] * 1000;
var columnInSampleRates = headerB === 3 ? 0 : headerB === 2 ? 1 : 2;
var sampleRate = MpegAudio.SamplingRateMap[columnInSampleRates * 3 + headerF];
var channelCount = data[offset + 3] >> 6 === 3 ? 1 : 2; // If bits of channel mode are `11` then it is a single channel (Mono)
var sampleCoefficient = MpegAudio.SamplesCoefficients[headerB][headerC];
var bytesInSlot = MpegAudio.BytesInSlot[headerC];
var samplesPerFrame = sampleCoefficient * 8 * bytesInSlot;
var frameLength = parseInt(sampleCoefficient * bitRate / sampleRate + headerG, 10) * bytesInSlot;
return { sampleRate: sampleRate, channelCount: channelCount, frameLength: frameLength, samplesPerFrame: samplesPerFrame };
}
return undefined;
},
isHeaderPattern: function isHeaderPattern(data, offset) {
return data[offset] === 0xff && (data[offset + 1] & 0xe0) === 0xe0 && (data[offset + 1] & 0x06) !== 0x00;
},
isHeader: function isHeader(data, offset) {
// Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
// Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
// More info http://www.mp3-tech.org/programmer/frame_header.html
if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) {
return true;
}
return false;
},
probe: function probe(data, offset) {
// same as isHeader but we also check that MPEG frame follows last MPEG frame
// or end of data is reached
if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) {
// MPEG header Length
var headerLength = 4;
// MPEG frame Length
var header = this.parseHeader(data, offset);
var frameLength = headerLength;
if (header && header.frameLength) {
frameLength = header.frameLength;
}
var newOffset = offset + frameLength;
if (newOffset === data.length || newOffset + 1 < data.length && this.isHeaderPattern(data, newOffset)) {
return true;
}
}
return false;
}
};
/* harmony default export */ var mpegaudio = (MpegAudio);
// CONCATENATED MODULE: ./src/demux/exp-golomb.js
function exp_golomb__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.
*/
var exp_golomb_ExpGolomb = function () {
function ExpGolomb(data) {
exp_golomb__classCallCheck(this, ExpGolomb);
this.data = data;
// the number of bytes left to examine in this.data
this.bytesAvailable = data.byteLength;
// the current word being examined
this.word = 0; // :uint
// the number of bits left to examine in the current word
this.bitsAvailable = 0; // :uint
}
// ():void
ExpGolomb.prototype.loadWord = function loadWord() {
var data = this.data,
bytesAvailable = this.bytesAvailable,
position = data.byteLength - bytesAvailable,
workingBytes = new Uint8Array(4),
availableBytes = Math.min(4, bytesAvailable);
if (availableBytes === 0) {
throw new Error('no bytes available');
}
workingBytes.set(data.subarray(position, position + availableBytes));
this.word = new DataView(workingBytes.buffer).getUint32(0);
// track the amount of this.data that has been processed
this.bitsAvailable = availableBytes * 8;
this.bytesAvailable -= availableBytes;
};
// (count:int):void
ExpGolomb.prototype.skipBits = function skipBits(count) {
var skipBytes = void 0; // :int
if (this.bitsAvailable > count) {
this.word <<= count;
this.bitsAvailable -= count;
} else {
count -= this.bitsAvailable;
skipBytes = count >> 3;
count -= skipBytes >> 3;
this.bytesAvailable -= skipBytes;
this.loadWord();
this.word <<= count;
this.bitsAvailable -= count;
}
};
// (size:int):uint
ExpGolomb.prototype.readBits = function readBits(size) {
var bits = Math.min(this.bitsAvailable, size),
// :uint
valu = this.word >>> 32 - bits; // :uint
if (size > 32) {
logger["b" /* logger */].error('Cannot read more than 32 bits at a time');
}
this.bitsAvailable -= bits;
if (this.bitsAvailable > 0) {
this.word <<= bits;
} else if (this.bytesAvailable > 0) {
this.loadWord();
}
bits = size - bits;
if (bits > 0 && this.bitsAvailable) {
return valu << bits | this.readBits(bits);
} else {
return valu;
}
};
// ():uint
ExpGolomb.prototype.skipLZ = function skipLZ() {
var leadingZeroCount = void 0; // :uint
for (leadingZeroCount = 0; leadingZeroCount < this.bitsAvailable; ++leadingZeroCount) {
share/public_html/static/hls.js view on Meta::CPAN
pixelRatio = [1, 1];break;
case 2:
pixelRatio = [12, 11];break;
case 3:
pixelRatio = [10, 11];break;
case 4:
pixelRatio = [16, 11];break;
case 5:
pixelRatio = [40, 33];break;
case 6:
pixelRatio = [24, 11];break;
case 7:
pixelRatio = [20, 11];break;
case 8:
pixelRatio = [32, 11];break;
case 9:
pixelRatio = [80, 33];break;
case 10:
pixelRatio = [18, 11];break;
case 11:
pixelRatio = [15, 11];break;
case 12:
pixelRatio = [64, 33];break;
case 13:
pixelRatio = [160, 99];break;
case 14:
pixelRatio = [4, 3];break;
case 15:
pixelRatio = [3, 2];break;
case 16:
pixelRatio = [2, 1];break;
case 255:
{
pixelRatio = [readUByte() << 8 | readUByte(), readUByte() << 8 | readUByte()];
break;
}
}
}
}
return {
width: Math.ceil((picWidthInMbsMinus1 + 1) * 16 - frameCropLeftOffset * 2 - frameCropRightOffset * 2),
height: (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 - (frameMbsOnlyFlag ? 2 : 4) * (frameCropTopOffset + frameCropBottomOffset),
pixelRatio: pixelRatio
};
};
ExpGolomb.prototype.readSliceType = function readSliceType() {
// skip NALu type
this.readUByte();
// discard first_mb_in_slice
this.readUEG();
// return slice_type
return this.readUEG();
};
return ExpGolomb;
}();
/* harmony default export */ var exp_golomb = (exp_golomb_ExpGolomb);
// CONCATENATED MODULE: ./src/demux/sample-aes.js
function sample_aes__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* SAMPLE-AES decrypter
*/
var sample_aes_SampleAesDecrypter = function () {
function SampleAesDecrypter(observer, config, decryptdata, discardEPB) {
sample_aes__classCallCheck(this, SampleAesDecrypter);
this.decryptdata = decryptdata;
this.discardEPB = discardEPB;
this.decrypter = new crypt_decrypter["a" /* default */](observer, config, { removePKCS7Padding: false });
}
SampleAesDecrypter.prototype.decryptBuffer = function decryptBuffer(encryptedData, callback) {
this.decrypter.decrypt(encryptedData, this.decryptdata.key.buffer, this.decryptdata.iv.buffer, callback);
};
// AAC - encrypt all full 16 bytes blocks starting from offset 16
SampleAesDecrypter.prototype.decryptAacSample = function decryptAacSample(samples, sampleIndex, callback, sync) {
var curUnit = samples[sampleIndex].unit;
var encryptedData = curUnit.subarray(16, curUnit.length - curUnit.length % 16);
var encryptedBuffer = encryptedData.buffer.slice(encryptedData.byteOffset, encryptedData.byteOffset + encryptedData.length);
var localthis = this;
this.decryptBuffer(encryptedBuffer, function (decryptedData) {
decryptedData = new Uint8Array(decryptedData);
curUnit.set(decryptedData, 16);
if (!sync) {
localthis.decryptAacSamples(samples, sampleIndex + 1, callback);
}
});
};
SampleAesDecrypter.prototype.decryptAacSamples = function decryptAacSamples(samples, sampleIndex, callback) {
for (;; sampleIndex++) {
if (sampleIndex >= samples.length) {
callback();
return;
}
if (samples[sampleIndex].unit.length < 32) {
continue;
}
var sync = this.decrypter.isSync();
this.decryptAacSample(samples, sampleIndex, callback, sync);
if (!sync) {
return;
}
}
};
share/public_html/static/hls.js view on Meta::CPAN
};
SampleAesDecrypter.prototype.getAvcDecryptedUnit = function getAvcDecryptedUnit(decodedData, decryptedData) {
decryptedData = new Uint8Array(decryptedData);
var inputPos = 0;
for (var outputPos = 32; outputPos <= decodedData.length - 16; outputPos += 160, inputPos += 16) {
decodedData.set(decryptedData.subarray(inputPos, inputPos + 16), outputPos);
}
return decodedData;
};
SampleAesDecrypter.prototype.decryptAvcSample = function decryptAvcSample(samples, sampleIndex, unitIndex, callback, curUnit, sync) {
var decodedData = this.discardEPB(curUnit.data);
var encryptedData = this.getAvcEncryptedData(decodedData);
var localthis = this;
this.decryptBuffer(encryptedData.buffer, function (decryptedData) {
curUnit.data = localthis.getAvcDecryptedUnit(decodedData, decryptedData);
if (!sync) {
localthis.decryptAvcSamples(samples, sampleIndex, unitIndex + 1, callback);
}
});
};
SampleAesDecrypter.prototype.decryptAvcSamples = function decryptAvcSamples(samples, sampleIndex, unitIndex, callback) {
for (;; sampleIndex++, unitIndex = 0) {
if (sampleIndex >= samples.length) {
callback();
return;
}
var curUnits = samples[sampleIndex].units;
for (;; unitIndex++) {
if (unitIndex >= curUnits.length) {
break;
}
var curUnit = curUnits[unitIndex];
if (curUnit.length <= 48 || curUnit.type !== 1 && curUnit.type !== 5) {
continue;
}
var sync = this.decrypter.isSync();
this.decryptAvcSample(samples, sampleIndex, unitIndex, callback, curUnit, sync);
if (!sync) {
return;
}
}
}
};
return SampleAesDecrypter;
}();
/* harmony default export */ var sample_aes = (sample_aes_SampleAesDecrypter);
// CONCATENATED MODULE: ./src/demux/tsdemuxer.js
function tsdemuxer__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* highly optimized TS demuxer:
* parse PAT, PMT
* extract PES packet from audio and video PIDs
* extract AVC/H264 NAL units and AAC/ADTS samples from PES packet
* trigger the remuxer upon parsing completion
* it also tries to workaround as best as it can audio codec switch (HE-AAC to AAC and vice versa), without having to restart the MediaSource.
* it also controls the remuxing process :
* upon discontinuity or level switch detection, it will also notifies the remuxer so that it can reset its state.
*/
// import Hex from '../utils/hex';
// We are using fixed track IDs for driving the MP4 remuxer
// instead of following the TS PIDs.
// There is no reason not to do this and some browsers/SourceBuffer-demuxers
// may not like if there are TrackID "switches"
// See https://github.com/video-dev/hls.js/issues/1331
// Here we are mapping our internal track types to constant MP4 track IDs
// With MSE currently one can only have one track of each, and we are muxing
// whatever video/audio rendition in them.
var RemuxerTrackIdConfig = {
video: 1,
audio: 2,
id3: 3,
text: 4
};
var tsdemuxer_TSDemuxer = function () {
function TSDemuxer(observer, remuxer, config, typeSupported) {
tsdemuxer__classCallCheck(this, TSDemuxer);
this.observer = observer;
this.config = config;
this.typeSupported = typeSupported;
this.remuxer = remuxer;
this.sampleAes = null;
}
TSDemuxer.prototype.setDecryptData = function setDecryptData(decryptdata) {
if (decryptdata != null && decryptdata.key != null && decryptdata.method === 'SAMPLE-AES') {
this.sampleAes = new sample_aes(this.observer, this.config, decryptdata, this.discardEPB);
} else {
this.sampleAes = null;
}
};
TSDemuxer.probe = function probe(data) {
var syncOffset = TSDemuxer._syncOffset(data);
if (syncOffset < 0) {
return false;
} else {
share/public_html/static/hls.js view on Meta::CPAN
var frame = appendFrame(track, data, offset, pts, frameIndex);
if (frame) {
// logger.log(`${Math.round(frame.sample.pts)} : AAC`);
offset += frame.length;
stamp = frame.sample.pts;
frameIndex++;
} else {
// logger.log('Unable to parse AAC frame');
break;
}
} else {
// nothing found, keep looking
offset++;
}
}
if (offset < len) {
aacOverFlow = data.subarray(offset, len);
// logger.log(`AAC: overflow detected:${len-offset}`);
} else {
aacOverFlow = null;
}
this.aacOverFlow = aacOverFlow;
this.aacLastPTS = stamp;
};
TSDemuxer.prototype._parseMPEGPES = function _parseMPEGPES(pes) {
var data = pes.data;
var length = data.length;
var frameIndex = 0;
var offset = 0;
var pts = pes.pts;
while (offset < length) {
if (mpegaudio.isHeader(data, offset)) {
var frame = mpegaudio.appendFrame(this._audioTrack, data, offset, pts, frameIndex);
if (frame) {
offset += frame.length;
frameIndex++;
} else {
// logger.log('Unable to parse Mpeg audio frame');
break;
}
} else {
// nothing found, keep looking
offset++;
}
}
};
TSDemuxer.prototype._parseID3PES = function _parseID3PES(pes) {
this._id3Track.samples.push(pes);
};
return TSDemuxer;
}();
/* harmony default export */ var tsdemuxer = (tsdemuxer_TSDemuxer);
// CONCATENATED MODULE: ./src/demux/mp3demuxer.js
function mp3demuxer__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* MP3 demuxer
*/
var mp3demuxer_MP3Demuxer = function () {
function MP3Demuxer(observer, remuxer, config) {
mp3demuxer__classCallCheck(this, MP3Demuxer);
this.observer = observer;
this.config = config;
this.remuxer = remuxer;
}
MP3Demuxer.prototype.resetInitSegment = function resetInitSegment(initSegment, audioCodec, videoCodec, duration) {
this._audioTrack = { container: 'audio/mpeg', type: 'audio', id: -1, sequenceNumber: 0, isAAC: false, samples: [], len: 0, manifestCodec: audioCodec, duration: duration, inputTimeScale: 90000 };
};
MP3Demuxer.prototype.resetTimeStamp = function resetTimeStamp() {};
MP3Demuxer.probe = function probe(data) {
// check if data contains ID3 timestamp and MPEG sync word
var offset = void 0,
length = void 0;
var id3Data = id3["a" /* default */].getID3Data(data, 0);
if (id3Data && id3["a" /* default */].getTimeStamp(id3Data) !== undefined) {
// Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1
// Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III)
// More info http://www.mp3-tech.org/programmer/frame_header.html
for (offset = id3Data.length, length = Math.min(data.length - 1, offset + 100); offset < length; offset++) {
if (mpegaudio.probe(data, offset)) {
logger["b" /* logger */].log('MPEG Audio sync word found !');
return true;
}
}
}
return false;
};
// feed incoming data to the front of the parsing pipeline
MP3Demuxer.prototype.append = function append(data, timeOffset, contiguous, accurateTimeOffset) {
var id3Data = id3["a" /* default */].getID3Data(data, 0);
var timestamp = id3["a" /* default */].getTimeStamp(id3Data);
var pts = timestamp ? 90 * timestamp : timeOffset * 90000;
var offset = id3Data.length;
var length = data.length;
var frameIndex = 0,
stamp = 0;
var track = this._audioTrack;
var id3Samples = [{ pts: pts, dts: pts, data: id3Data }];
while (offset < length) {
if (mpegaudio.isHeader(data, offset)) {
var frame = mpegaudio.appendFrame(track, data, offset, pts, frameIndex);
if (frame) {
offset += frame.length;
stamp = frame.sample.pts;
frameIndex++;
} else {
// logger.log('Unable to parse Mpeg audio frame');
break;
}
} else if (id3["a" /* default */].isHeader(data, offset)) {
id3Data = id3["a" /* default */].getID3Data(data, offset);
id3Samples.push({ pts: stamp, dts: stamp, data: id3Data });
offset += id3Data.length;
} else {
// nothing found, keep looking
offset++;
}
}
this.remuxer.remux(track, { samples: [] }, { samples: id3Samples, inputTimeScale: 90000 }, { samples: [] }, timeOffset, contiguous, accurateTimeOffset);
};
MP3Demuxer.prototype.destroy = function destroy() {};
return MP3Demuxer;
}();
/* harmony default export */ var mp3demuxer = (mp3demuxer_MP3Demuxer);
// CONCATENATED MODULE: ./src/remux/aac-helper.js
function aac_helper__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* AAC helper
*/
var AAC = function () {
function AAC() {
aac_helper__classCallCheck(this, AAC);
}
AAC.getSilentFrame = function getSilentFrame(codec, channelCount) {
switch (codec) {
case 'mp4a.40.2':
if (channelCount === 1) {
return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x23, 0x80]);
} else if (channelCount === 2) {
return new Uint8Array([0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80]);
} else if (channelCount === 3) {
return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x8e]);
} else if (channelCount === 4) {
return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x80, 0x2c, 0x80, 0x08, 0x02, 0x38]);
} else if (channelCount === 5) {
return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x38]);
} else if (channelCount === 6) {
return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x00, 0xb2, 0x00, 0x20, 0x08, 0xe0]);
}
break;
// handle HE-AAC below (mp4a.40.5 / mp4a.40.29)
default:
if (channelCount === 1) {
// ffmpeg -y -f lavfi -i "aevalsrc=0:d=0.05" -c:a libfdk_aac -profile:a aac_he -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac
return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x4e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x1c, 0x6, 0xf1, 0xc1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x...
} else if (channelCount === 2) {
// ffmpeg -y -f lavfi -i "aevalsrc=0|0:d=0.05" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac
return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a...
} else if (channelCount === 3) {
// ffmpeg -y -f lavfi -i "aevalsrc=0|0|0:d=0.05" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac
return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a...
}
break;
}
return null;
};
return AAC;
}();
/* harmony default export */ var aac_helper = (AAC);
// CONCATENATED MODULE: ./src/remux/mp4-generator.js
function mp4_generator__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* Generate MP4 Box
*/
var UINT32_MAX = Math.pow(2, 32) - 1;
var MP4 = function () {
function MP4() {
mp4_generator__classCallCheck(this, MP4);
}
MP4.init = function init() {
MP4.types = {
avc1: [], // codingname
avcC: [],
btrt: [],
dinf: [],
dref: [],
esds: [],
ftyp: [],
hdlr: [],
mdat: [],
mdhd: [],
mdia: [],
mfhd: [],
minf: [],
moof: [],
moov: [],
mp4a: [],
'.mp3': [],
mvex: [],
mvhd: [],
pasp: [],
sdtp: [],
stbl: [],
stco: [],
stsc: [],
stsd: [],
stsz: [],
stts: [],
tfdt: [],
tfhd: [],
traf: [],
trak: [],
trun: [],
trex: [],
tkhd: [],
vmhd: [],
smhd: []
};
var i = void 0;
for (i in MP4.types) {
if (MP4.types.hasOwnProperty(i)) {
MP4.types[i] = [i.charCodeAt(0), i.charCodeAt(1), i.charCodeAt(2), i.charCodeAt(3)];
}
}
var videoHdlr = new Uint8Array([0x00, // version 0
share/public_html/static/hls.js view on Meta::CPAN
return MP4.box(MP4.types.trex, new Uint8Array([0x00, // version 0
0x00, 0x00, 0x00, // flags
id >> 24, id >> 16 & 0XFF, id >> 8 & 0XFF, id & 0xFF, // track_ID
0x00, 0x00, 0x00, 0x01, // default_sample_description_index
0x00, 0x00, 0x00, 0x00, // default_sample_duration
0x00, 0x00, 0x00, 0x00, // default_sample_size
0x00, 0x01, 0x00, 0x01 // default_sample_flags
]));
};
MP4.trun = function trun(track, offset) {
var samples = track.samples || [],
len = samples.length,
arraylen = 12 + 16 * len,
array = new Uint8Array(arraylen),
i = void 0,
sample = void 0,
duration = void 0,
size = void 0,
flags = void 0,
cts = void 0;
offset += 8 + arraylen;
array.set([0x00, // version 0
0x00, 0x0f, 0x01, // flags
len >>> 24 & 0xFF, len >>> 16 & 0xFF, len >>> 8 & 0xFF, len & 0xFF, // sample_count
offset >>> 24 & 0xFF, offset >>> 16 & 0xFF, offset >>> 8 & 0xFF, offset & 0xFF // data_offset
], 0);
for (i = 0; i < len; i++) {
sample = samples[i];
duration = sample.duration;
size = sample.size;
flags = sample.flags;
cts = sample.cts;
array.set([duration >>> 24 & 0xFF, duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, // sample_duration
size >>> 24 & 0xFF, size >>> 16 & 0xFF, size >>> 8 & 0xFF, size & 0xFF, // sample_size
flags.isLeading << 2 | flags.dependsOn, flags.isDependedOn << 6 | flags.hasRedundancy << 4 | flags.paddingValue << 1 | flags.isNonSync, flags.degradPrio & 0xF0 << 8, flags.degradPrio & 0x0F, // sample_flags
cts >>> 24 & 0xFF, cts >>> 16 & 0xFF, cts >>> 8 & 0xFF, cts & 0xFF // sample_composition_time_offset
], 12 + 16 * i);
}
return MP4.box(MP4.types.trun, array);
};
MP4.initSegment = function initSegment(tracks) {
if (!MP4.types) {
MP4.init();
}
var movie = MP4.moov(tracks),
result = void 0;
result = new Uint8Array(MP4.FTYP.byteLength + movie.byteLength);
result.set(MP4.FTYP);
result.set(movie, MP4.FTYP.byteLength);
return result;
};
return MP4;
}();
/* harmony default export */ var mp4_generator = (MP4);
// CONCATENATED MODULE: ./src/remux/mp4-remuxer.js
function mp4_remuxer__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* fMP4 remuxer
*/
// 10 seconds
var MAX_SILENT_FRAME_DURATION = 10 * 1000;
var mp4_remuxer_MP4Remuxer = function () {
function MP4Remuxer(observer, config, typeSupported, vendor) {
mp4_remuxer__classCallCheck(this, MP4Remuxer);
this.observer = observer;
this.config = config;
this.typeSupported = typeSupported;
var userAgent = navigator.userAgent;
this.isSafari = vendor && vendor.indexOf('Apple') > -1 && userAgent && !userAgent.match('CriOS');
this.ISGenerated = false;
}
MP4Remuxer.prototype.destroy = function destroy() {};
MP4Remuxer.prototype.resetTimeStamp = function resetTimeStamp(defaultTimeStamp) {
this._initPTS = this._initDTS = defaultTimeStamp;
};
MP4Remuxer.prototype.resetInitSegment = function resetInitSegment() {
this.ISGenerated = false;
};
MP4Remuxer.prototype.remux = function remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset) {
// generate Init Segment if needed
if (!this.ISGenerated) {
this.generateIS(audioTrack, videoTrack, timeOffset);
}
if (this.ISGenerated) {
var nbAudioSamples = audioTrack.samples.length;
var nbVideoSamples = videoTrack.samples.length;
var audioTimeOffset = timeOffset;
var videoTimeOffset = timeOffset;
if (nbAudioSamples && nbVideoSamples) {
// timeOffset is expected to be the offset of the first timestamp of this fragment (first DTS)
// if first audio DTS is not aligned with first video DTS then we need to take that into account
// when providing timeOffset to remuxAudio / remuxVideo. if we don't do that, there might be a permanent / small
// drift between audio and video streams
var audiovideoDeltaDts = (audioTrack.samples[0].dts - videoTrack.samples[0].dts) / videoTrack.inputTimeScale;
audioTimeOffset += Math.max(0, audiovideoDeltaDts);
videoTimeOffset += Math.max(0, -audiovideoDeltaDts);
}
// Purposefully remuxing audio before video, so that remuxVideo can use nextAudioPts, which is
// calculated in remuxAudio.
share/public_html/static/hls.js view on Meta::CPAN
}
track.samples = [];
timeOffset = timeOffset;
};
MP4Remuxer.prototype.remuxText = function remuxText(track, timeOffset) {
track.samples.sort(function (a, b) {
return a.pts - b.pts;
});
var length = track.samples.length,
sample = void 0;
var inputTimeScale = track.inputTimeScale;
var initPTS = this._initPTS;
// consume samples
if (length) {
for (var index = 0; index < length; index++) {
sample = track.samples[index];
// setting text pts, dts to relative time
// using this._initPTS and this._initDTS to calculate relative time
sample.pts = (sample.pts - initPTS) / inputTimeScale;
}
this.observer.trigger(events["a" /* default */].FRAG_PARSING_USERDATA, {
samples: track.samples
});
}
track.samples = [];
timeOffset = timeOffset;
};
MP4Remuxer.prototype._PTSNormalize = function _PTSNormalize(value, reference) {
var offset = void 0;
if (reference === undefined) {
return value;
}
if (reference < value) {
// - 2^33
offset = -8589934592;
} else {
// + 2^33
offset = 8589934592;
}
/* PTS is 33bit (from 0 to 2^33 -1)
if diff between value and reference is bigger than half of the amplitude (2^32) then it means that
PTS looping occured. fill the gap */
while (Math.abs(value - reference) > 4294967296) {
value += offset;
}
return value;
};
return MP4Remuxer;
}();
/* harmony default export */ var mp4_remuxer = (mp4_remuxer_MP4Remuxer);
// CONCATENATED MODULE: ./src/remux/passthrough-remuxer.js
function passthrough_remuxer__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* passthrough remuxer
*/
var passthrough_remuxer_PassThroughRemuxer = function () {
function PassThroughRemuxer(observer) {
passthrough_remuxer__classCallCheck(this, PassThroughRemuxer);
this.observer = observer;
}
PassThroughRemuxer.prototype.destroy = function destroy() {};
PassThroughRemuxer.prototype.resetTimeStamp = function resetTimeStamp() {};
PassThroughRemuxer.prototype.resetInitSegment = function resetInitSegment() {};
PassThroughRemuxer.prototype.remux = function remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous, accurateTimeOffset, rawData) {
var observer = this.observer;
var streamType = '';
if (audioTrack) {
streamType += 'audio';
}
if (videoTrack) {
streamType += 'video';
}
observer.trigger(events["a" /* default */].FRAG_PARSING_DATA, {
data1: rawData,
startPTS: timeOffset,
startDTS: timeOffset,
type: streamType,
hasAudio: !!audioTrack,
hasVideo: !!videoTrack,
nb: 1,
dropped: 0
});
// notify end of parsing
observer.trigger(events["a" /* default */].FRAG_PARSED);
};
return PassThroughRemuxer;
}();
/* harmony default export */ var passthrough_remuxer = (passthrough_remuxer_PassThroughRemuxer);
// CONCATENATED MODULE: ./src/demux/demuxer-inline.js
function demuxer_inline__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
*
* inline demuxer: probe fragments and instantiate
* appropriate demuxer depending on content type (TSDemuxer, AACDemuxer, ...)
*
*/
// see https://stackoverflow.com/a/11237259/589493
var global = Object(get_self_scope["a" /* getSelfScope */])(); // safeguard for code that might run both on worker and main thread
var performance = global;
var demuxer_inline_DemuxerInline = function () {
function DemuxerInline(observer, typeSupported, config, vendor) {
demuxer_inline__classCallCheck(this, DemuxerInline);
this.observer = observer;
this.typeSupported = typeSupported;
this.config = config;
this.vendor = vendor;
}
DemuxerInline.prototype.destroy = function destroy() {
var demuxer = this.demuxer;
if (demuxer) {
demuxer.destroy();
}
};
DemuxerInline.prototype.push = function push(data, decryptdata, initSegment, audioCodec, videoCodec, timeOffset, discontinuity, trackSwitch, contiguous, duration, accurateTimeOffset, defaultInitPTS) {
if (data.byteLength > 0 && decryptdata != null && decryptdata.key != null && decryptdata.method === 'AES-128') {
var decrypter = this.decrypter;
if (decrypter == null) {
decrypter = this.decrypter = new crypt_decrypter["a" /* default */](this.observer, this.config);
}
var localthis = this;
// performance.now() not available on WebWorker, at least on Safari Desktop
var startTime = void 0;
try {
startTime = performance.now();
} catch (error) {
startTime = Date.now();
}
decrypter.decrypt(data, decryptdata.key.buffer, decryptdata.iv.buffer, function (decryptedData) {
var endTime = void 0;
try {
endTime = performance.now();
share/public_html/static/hls.js view on Meta::CPAN
if (probe(data)) {
var _remuxer = this.remuxer = new mux.remux(observer, config, typeSupported, this.vendor);
demuxer = new mux.demux(observer, _remuxer, config, typeSupported);
this.probe = probe;
break;
}
}
if (!demuxer) {
observer.trigger(events["a" /* default */].ERROR, { type: errors["b" /* ErrorTypes */].MEDIA_ERROR, details: errors["a" /* ErrorDetails */].FRAG_PARSING_ERROR, fatal: true, reason: 'no demux matching with content found' });
return;
}
this.demuxer = demuxer;
}
var remuxer = this.remuxer;
if (discontinuity || trackSwitch) {
demuxer.resetInitSegment(initSegment, audioCodec, videoCodec, duration);
remuxer.resetInitSegment();
}
if (discontinuity) {
demuxer.resetTimeStamp(defaultInitPTS);
remuxer.resetTimeStamp(defaultInitPTS);
}
if (typeof demuxer.setDecryptData === 'function') {
demuxer.setDecryptData(decryptdata);
}
demuxer.append(data, timeOffset, contiguous, accurateTimeOffset);
};
return DemuxerInline;
}();
/* harmony default export */ var demuxer_inline = __webpack_exports__["a"] = (demuxer_inline_DemuxerInline);
/***/ }),
/* 10 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
var cues_namespaceObject = {};
__webpack_require__.d(cues_namespaceObject, "newCue", function() { return newCue; });
// EXTERNAL MODULE: ./node_modules/url-toolkit/src/url-toolkit.js
var url_toolkit = __webpack_require__(4);
var url_toolkit_default = /*#__PURE__*/__webpack_require__.n(url_toolkit);
// EXTERNAL MODULE: ./src/errors.js
var errors = __webpack_require__(2);
// EXTERNAL MODULE: ./src/events.js
var events = __webpack_require__(1);
// EXTERNAL MODULE: ./src/utils/logger.js
var logger = __webpack_require__(0);
// CONCATENATED MODULE: ./src/event-handler.js
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbo...
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/*
*
* All objects in the event handling chain should inherit from this class
*
*/
var FORBIDDEN_EVENT_NAMES = new Set(['hlsEventGeneric', 'hlsHandlerDestroying', 'hlsHandlerDestroyed']);
var event_handler_EventHandler = function () {
function EventHandler(hls) {
_classCallCheck(this, EventHandler);
this.hls = hls;
this.onEvent = this.onEvent.bind(this);
for (var _len = arguments.length, events = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
events[_key - 1] = arguments[_key];
}
this.handledEvents = events;
this.useGenericHandler = true;
this.registerListeners();
}
EventHandler.prototype.destroy = function destroy() {
this.onHandlerDestroying();
this.unregisterListeners();
this.onHandlerDestroyed();
};
EventHandler.prototype.onHandlerDestroying = function onHandlerDestroying() {};
EventHandler.prototype.onHandlerDestroyed = function onHandlerDestroyed() {};
EventHandler.prototype.isEventHandler = function isEventHandler() {
return _typeof(this.handledEvents) === 'object' && this.handledEvents.length && typeof this.onEvent === 'function';
};
EventHandler.prototype.registerListeners = function registerListeners() {
if (this.isEventHandler()) {
this.handledEvents.forEach(function (event) {
if (FORBIDDEN_EVENT_NAMES.has(event)) {
throw new Error('Forbidden event-name: ' + event);
}
this.hls.on(event, this.onEvent);
}, this);
}
};
EventHandler.prototype.unregisterListeners = function unregisterListeners() {
if (this.isEventHandler()) {
this.handledEvents.forEach(function (event) {
this.hls.off(event, this.onEvent);
}, this);
}
};
/**
* arguments: event (string), data (any)
*/
EventHandler.prototype.onEvent = function onEvent(event, data) {
this.onEventGeneric(event, data);
};
EventHandler.prototype.onEventGeneric = function onEventGeneric(event, data) {
var eventToFunction = function eventToFunction(event, data) {
var funcName = 'on' + event.replace('hls', '');
if (typeof this[funcName] !== 'function') {
throw new Error('Event ' + event + ' has no generic handler in this ' + this.constructor.name + ' class (tried ' + funcName + ')');
}
return this[funcName].bind(this, data);
};
try {
eventToFunction.call(this, event, data).call();
} catch (err) {
logger["b" /* logger */].error('An internal error happened while handling event ' + event + '. Error message: "' + err.message + '". Here is a stacktrace:', err);
this.hls.trigger(events["a" /* default */].ERROR, { type: errors["b" /* ErrorTypes */].OTHER_ERROR, details: errors["a" /* ErrorDetails */].INTERNAL_EXCEPTION, fatal: false, event: event, err: err });
}
};
return EventHandler;
}();
/* harmony default export */ var event_handler = (event_handler_EventHandler);
// EXTERNAL MODULE: ./src/demux/mp4demuxer.js
var mp4demuxer = __webpack_require__(8);
// CONCATENATED MODULE: ./src/loader/level-key.js
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in des...
function level_key__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var level_key_LevelKey = function () {
function LevelKey() {
level_key__classCallCheck(this, LevelKey);
this.method = null;
this.key = null;
this.iv = null;
this._uri = null;
}
_createClass(LevelKey, [{
key: 'uri',
get: function get() {
if (!this._uri && this.reluri) {
this._uri = url_toolkit_default.a.buildAbsoluteURL(this.baseuri, this.reluri, { alwaysNormalize: true });
}
return this._uri;
}
}]);
return LevelKey;
}();
/* harmony default export */ var level_key = (level_key_LevelKey);
// CONCATENATED MODULE: ./src/loader/fragment.js
var fragment__createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("valu...
function fragment__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var fragment_Fragment = function () {
function Fragment() {
var _elementaryStreams;
fragment__classCallCheck(this, Fragment);
this._url = null;
this._byteRange = null;
this._decryptdata = null;
this.tagList = [];
// Holds the types of data this fragment supports
this._elementaryStreams = (_elementaryStreams = {}, _elementaryStreams[Fragment.ElementaryStreamTypes.AUDIO] = false, _elementaryStreams[Fragment.ElementaryStreamTypes.VIDEO] = false, _elementaryStreams);
}
/**
* `type` property for this._elementaryStreams
*
* @enum
*/
/**
* @param {ElementaryStreamType} type
*/
Fragment.prototype.addElementaryStream = function addElementaryStream(type) {
this._elementaryStreams[type] = true;
};
/**
* @param {ElementaryStreamType} type
*/
Fragment.prototype.hasElementaryStream = function hasElementaryStream(type) {
return this._elementaryStreams[type] === true;
};
/**
* Utility method for parseLevelPlaylist to create an initialization vector for a given segment
* @returns {Uint8Array}
*/
Fragment.prototype.createInitializationVector = function createInitializationVector(segmentNumber) {
var uint8View = new Uint8Array(16);
for (var i = 12; i < 16; i++) {
uint8View[i] = segmentNumber >> 8 * (15 - i) & 0xff;
}
return uint8View;
};
/**
share/public_html/static/hls.js view on Meta::CPAN
}
var byteRange = [];
if (this.rawByteRange) {
var params = this.rawByteRange.split('@', 2);
if (params.length === 1) {
var lastByteRangeEndOffset = this.lastByteRangeEndOffset;
byteRange[0] = lastByteRangeEndOffset || 0;
} else {
byteRange[0] = parseInt(params[1]);
}
byteRange[1] = parseInt(params[0]) + byteRange[0];
this._byteRange = byteRange;
}
return byteRange;
}
/**
* @type {number}
*/
}, {
key: 'byteRangeStartOffset',
get: function get() {
return this.byteRange[0];
}
}, {
key: 'byteRangeEndOffset',
get: function get() {
return this.byteRange[1];
}
}, {
key: 'decryptdata',
get: function get() {
if (!this._decryptdata) {
this._decryptdata = this.fragmentDecryptdataFromLevelkey(this.levelkey, this.sn);
}
return this._decryptdata;
}
}, {
key: 'encrypted',
get: function get() {
return !!(this.decryptdata && this.decryptdata.uri !== null && this.decryptdata.key === null);
}
}], [{
key: 'ElementaryStreamTypes',
get: function get() {
return {
AUDIO: 'audio',
VIDEO: 'video'
};
}
}]);
return Fragment;
}();
/* harmony default export */ var loader_fragment = (fragment_Fragment);
// CONCATENATED MODULE: ./src/utils/attr-list.js
function attr_list__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var DECIMAL_RESOLUTION_REGEX = /^(\d+)x(\d+)$/; // eslint-disable-line no-useless-escape
var ATTR_LIST_REGEX = /\s*(.+?)\s*=((?:\".*?\")|.*?)(?:,|$)/g; // eslint-disable-line no-useless-escape
// adapted from https://github.com/kanongil/node-m3u8parse/blob/master/attrlist.js
var AttrList = function () {
function AttrList(attrs) {
attr_list__classCallCheck(this, AttrList);
if (typeof attrs === 'string') {
attrs = AttrList.parseAttrList(attrs);
}
for (var attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
this[attr] = attrs[attr];
}
}
}
AttrList.prototype.decimalInteger = function decimalInteger(attrName) {
var intValue = parseInt(this[attrName], 10);
if (intValue > Number.MAX_SAFE_INTEGER) {
return Infinity;
}
return intValue;
};
AttrList.prototype.hexadecimalInteger = function hexadecimalInteger(attrName) {
if (this[attrName]) {
var stringValue = (this[attrName] || '0x').slice(2);
stringValue = (stringValue.length & 1 ? '0' : '') + stringValue;
var value = new Uint8Array(stringValue.length / 2);
for (var i = 0; i < stringValue.length / 2; i++) {
value[i] = parseInt(stringValue.slice(i * 2, i * 2 + 2), 16);
}
return value;
} else {
return null;
}
};
AttrList.prototype.hexadecimalIntegerAsNumber = function hexadecimalIntegerAsNumber(attrName) {
var intValue = parseInt(this[attrName], 16);
if (intValue > Number.MAX_SAFE_INTEGER) {
return Infinity;
}
return intValue;
};
AttrList.prototype.decimalFloatingPoint = function decimalFloatingPoint(attrName) {
return parseFloat(this[attrName]);
};
AttrList.prototype.enumeratedString = function enumeratedString(attrName) {
share/public_html/static/hls.js view on Meta::CPAN
'g719': true,
'g726': true,
'm4ae': true,
'mha1': true,
'mha2': true,
'mhm1': true,
'mhm2': true,
'mlpa': true,
'mp4a': true,
'raw ': true,
'Opus': true,
'samr': true,
'sawb': true,
'sawp': true,
'sevc': true,
'sqcp': true,
'ssmv': true,
'twos': true,
'ulaw': true
},
video: {
'avc1': true,
'avc2': true,
'avc3': true,
'avc4': true,
'avcp': true,
'drac': true,
'dvav': true,
'dvhe': true,
'encv': true,
'hev1': true,
'hvc1': true,
'mjp2': true,
'mp4v': true,
'mvc1': true,
'mvc2': true,
'mvc3': true,
'mvc4': true,
'resv': true,
'rv60': true,
's263': true,
'svc1': true,
'svc2': true,
'vc-1': true,
'vp08': true,
'vp09': true
}
};
function isCodecType(codec, type) {
var typeCodes = sampleEntryCodesISO[type];
return !!typeCodes && typeCodes[codec.slice(0, 4)] === true;
}
function isCodecSupportedInMp4(codec, type) {
return window.MediaSource.isTypeSupported((type || 'video') + '/mp4;codecs="' + codec + '"');
}
// CONCATENATED MODULE: ./src/loader/m3u8-parser.js
function m3u8_parser__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* M3U8 parser
* @module
*/
// https://regex101.com is your friend
var MASTER_PLAYLIST_REGEX = /#EXT-X-STREAM-INF:([^\n\r]*)[\r\n]+([^\r\n]+)/g;
var MASTER_PLAYLIST_MEDIA_REGEX = /#EXT-X-MEDIA:(.*)/g;
var LEVEL_PLAYLIST_REGEX_FAST = new RegExp([/#EXTINF:\s*(\d*(?:\.\d+)?)(?:,(.*)\s+)?/.source, // duration (#EXTINF:<duration>,<title>), group 1 => duration, group 2 => title
/|(?!#)(\S+)/.source, // segment URI, group 3 => the URI (note newline is not eaten)
/|#EXT-X-BYTERANGE:*(.+)/.source, // next segment's byterange, group 4 => range spec (x@y)
/|#EXT-X-PROGRAM-DATE-TIME:(.+)/.source, // next segment's program date/time group 5 => the datetime spec
/|#.*/.source // All other non-segment oriented tags will match with all groups empty
].join(''), 'g');
var LEVEL_PLAYLIST_REGEX_SLOW = /(?:(?:#(EXTM3U))|(?:#EXT-X-(PLAYLIST-TYPE):(.+))|(?:#EXT-X-(MEDIA-SEQUENCE): *(\d+))|(?:#EXT-X-(TARGETDURATION): *(\d+))|(?:#EXT-X-(KEY):(.+))|(?:#EXT-X-(START):(.+))|(?:#EXT-X-(ENDLIST))|(?:#EXT-X-(DISCONTINUITY-SEQ)...
var MP4_REGEX_SUFFIX = /\.(mp4|m4s|m4v|m4a)$/i;
var m3u8_parser_M3U8Parser = function () {
function M3U8Parser() {
m3u8_parser__classCallCheck(this, M3U8Parser);
}
M3U8Parser.findGroup = function findGroup(groups, mediaGroupId) {
if (!groups) {
return null;
}
var matchingGroup = null;
for (var i = 0; i < groups.length; i++) {
var group = groups[i];
if (group.id === mediaGroupId) {
matchingGroup = group;
}
}
return matchingGroup;
};
M3U8Parser.convertAVC1ToAVCOTI = function convertAVC1ToAVCOTI(codec) {
var result = void 0,
avcdata = codec.split('.');
if (avcdata.length > 2) {
result = avcdata.shift() + '.';
result += parseInt(avcdata.shift()).toString(16);
result += ('000' + parseInt(avcdata.shift()).toString(16)).substr(-4);
} else {
share/public_html/static/hls.js view on Meta::CPAN
case 'MAP':
var mapAttrs = new attr_list(value1);
frag.relurl = mapAttrs.URI;
frag.rawByteRange = mapAttrs.BYTERANGE;
frag.baseurl = baseurl;
frag.level = id;
frag.type = type;
frag.sn = 'initSegment';
level.initSegment = frag;
frag = new loader_fragment();
break;
default:
logger["b" /* logger */].warn('line parsed but not handled: ' + result);
break;
}
}
}
frag = prevFrag;
// logger.log('found ' + level.fragments.length + ' fragments');
if (frag && !frag.relurl) {
level.fragments.pop();
totalduration -= frag.duration;
}
level.totalduration = totalduration;
level.averagetargetduration = totalduration / level.fragments.length;
level.endSN = currentSN - 1;
level.startCC = level.fragments[0] ? level.fragments[0].cc : 0;
level.endCC = cc;
if (!level.initSegment && level.fragments.length) {
// this is a bit lurky but HLS really has no other way to tell us
// if the fragments are TS or MP4, except if we download them :/
// but this is to be able to handle SIDX.
if (level.fragments.every(function (frag) {
return MP4_REGEX_SUFFIX.test(frag.relurl);
})) {
logger["b" /* logger */].warn('MP4 fragments found but no init segment (probably no MAP, incomplete M3U8), trying to fetch SIDX');
frag = new loader_fragment();
frag.relurl = level.fragments[0].relurl;
frag.baseurl = baseurl;
frag.level = id;
frag.type = type;
frag.sn = 'initSegment';
level.initSegment = frag;
level.needSidxRanges = true;
}
}
return level;
};
return M3U8Parser;
}();
/* harmony default export */ var m3u8_parser = (m3u8_parser_M3U8Parser);
// CONCATENATED MODULE: ./src/loader/playlist-loader.js
var playlist_loader__createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if...
function playlist_loader__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superC...
/**
* PlaylistLoader - delegate for media manifest/playlist loading tasks. Takes care of parsing media to internal data-models.
*
* Once loaded, dispatches events with parsed data-models of manifest/levels/audio/subtitle tracks.
*
* Uses loader(s) set in config to do actual internal loading of resource tasks.
*
* @module
*
*/
var _window = window,
performance = _window.performance;
/**
* `type` property values for this loaders' context object
* @enum
*
*/
var ContextType = {
MANIFEST: 'manifest',
LEVEL: 'level',
AUDIO_TRACK: 'audioTrack',
SUBTITLE_TRACK: 'subtitleTrack'
};
/**
* @enum {string}
*/
var LevelType = {
MAIN: 'main',
AUDIO: 'audio',
SUBTITLE: 'subtitle'
};
/**
* @constructor
*/
var playlist_loader_PlaylistLoader = function (_EventHandler) {
_inherits(PlaylistLoader, _EventHandler);
/**
* @constructs
* @param {Hls} hls
*/
function PlaylistLoader(hls) {
playlist_loader__classCallCheck(this, PlaylistLoader);
share/public_html/static/hls.js view on Meta::CPAN
PlaylistLoader.prototype._handlePlaylistLoaded = function _handlePlaylistLoaded(response, stats, context, networkDetails) {
var type = context.type,
level = context.level,
id = context.id,
levelDetails = context.levelDetails;
if (!levelDetails.targetduration) {
this._handleManifestParsingError(response, context, 'invalid target duration', networkDetails);
return;
}
var canHaveLevels = PlaylistLoader.canHaveQualityLevels(context.type);
if (canHaveLevels) {
this.hls.trigger(events["a" /* default */].LEVEL_LOADED, {
details: levelDetails,
level: level || 0,
id: id || 0,
stats: stats,
networkDetails: networkDetails
});
} else {
switch (type) {
case ContextType.AUDIO_TRACK:
this.hls.trigger(events["a" /* default */].AUDIO_TRACK_LOADED, {
details: levelDetails,
id: id,
stats: stats,
networkDetails: networkDetails
});
break;
case ContextType.SUBTITLE_TRACK:
this.hls.trigger(events["a" /* default */].SUBTITLE_TRACK_LOADED, {
details: levelDetails,
id: id,
stats: stats,
networkDetails: networkDetails
});
break;
}
}
};
playlist_loader__createClass(PlaylistLoader, null, [{
key: 'ContextType',
get: function get() {
return ContextType;
}
}, {
key: 'LevelType',
get: function get() {
return LevelType;
}
}]);
return PlaylistLoader;
}(event_handler);
/* harmony default export */ var playlist_loader = (playlist_loader_PlaylistLoader);
// CONCATENATED MODULE: ./src/loader/fragment-loader.js
function fragment_loader__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function fragment_loader__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : s...
function fragment_loader__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Obje...
/*
* Fragment Loader
*/
var fragment_loader_FragmentLoader = function (_EventHandler) {
fragment_loader__inherits(FragmentLoader, _EventHandler);
function FragmentLoader(hls) {
fragment_loader__classCallCheck(this, FragmentLoader);
var _this = fragment_loader__possibleConstructorReturn(this, _EventHandler.call(this, hls, events["a" /* default */].FRAG_LOADING));
_this.loaders = {};
return _this;
}
FragmentLoader.prototype.destroy = function destroy() {
var loaders = this.loaders;
for (var loaderName in loaders) {
var loader = loaders[loaderName];
if (loader) {
loader.destroy();
}
}
this.loaders = {};
_EventHandler.prototype.destroy.call(this);
};
FragmentLoader.prototype.onFragLoading = function onFragLoading(data) {
var frag = data.frag,
type = frag.type,
loaders = this.loaders,
config = this.hls.config,
FragmentILoader = config.fLoader,
DefaultILoader = config.loader;
// reset fragment state
frag.loaded = 0;
var loader = loaders[type];
if (loader) {
logger["b" /* logger */].warn('abort previous fragment loader for type: ' + type);
loader.abort();
}
loader = loaders[type] = frag.loader = config.fLoader ? new FragmentILoader(config) : new DefaultILoader(config);
var loaderContext = void 0,
loaderConfig = void 0,
loaderCallbacks = void 0;
loaderContext = { url: frag.url, frag: frag, responseType: 'arraybuffer', progressData: false };
share/public_html/static/hls.js view on Meta::CPAN
onSuccess: this.loadsuccess.bind(this),
onError: this.loaderror.bind(this),
onTimeout: this.loadtimeout.bind(this),
onProgress: this.loadprogress.bind(this)
};
loader.load(loaderContext, loaderConfig, loaderCallbacks);
};
FragmentLoader.prototype.loadsuccess = function loadsuccess(response, stats, context) {
var networkDetails = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
var payload = response.data,
frag = context.frag;
// detach fragment loader on load success
frag.loader = undefined;
this.loaders[frag.type] = undefined;
this.hls.trigger(events["a" /* default */].FRAG_LOADED, { payload: payload, frag: frag, stats: stats, networkDetails: networkDetails });
};
FragmentLoader.prototype.loaderror = function loaderror(response, context) {
var networkDetails = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
var loader = context.loader;
if (loader) {
loader.abort();
}
this.loaders[context.type] = undefined;
this.hls.trigger(events["a" /* default */].ERROR, { type: errors["b" /* ErrorTypes */].NETWORK_ERROR, details: errors["a" /* ErrorDetails */].FRAG_LOAD_ERROR, fatal: false, frag: context.frag, response: response, networkDetails: networkDetails })...
};
FragmentLoader.prototype.loadtimeout = function loadtimeout(stats, context) {
var networkDetails = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
var loader = context.loader;
if (loader) {
loader.abort();
}
this.loaders[context.type] = undefined;
this.hls.trigger(events["a" /* default */].ERROR, { type: errors["b" /* ErrorTypes */].NETWORK_ERROR, details: errors["a" /* ErrorDetails */].FRAG_LOAD_TIMEOUT, fatal: false, frag: context.frag, networkDetails: networkDetails });
};
// data will be used for progressive parsing
FragmentLoader.prototype.loadprogress = function loadprogress(stats, context, data) {
var networkDetails = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
// jshint ignore:line
var frag = context.frag;
frag.loaded = stats.loaded;
this.hls.trigger(events["a" /* default */].FRAG_LOAD_PROGRESS, { frag: frag, stats: stats, networkDetails: networkDetails });
};
return FragmentLoader;
}(event_handler);
/* harmony default export */ var fragment_loader = (fragment_loader_FragmentLoader);
// CONCATENATED MODULE: ./src/loader/key-loader.js
function key_loader__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function key_loader__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; ...
function key_loader__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.cr...
/*
* Decrypt key Loader
*/
var key_loader_KeyLoader = function (_EventHandler) {
key_loader__inherits(KeyLoader, _EventHandler);
function KeyLoader(hls) {
key_loader__classCallCheck(this, KeyLoader);
var _this = key_loader__possibleConstructorReturn(this, _EventHandler.call(this, hls, events["a" /* default */].KEY_LOADING));
_this.loaders = {};
_this.decryptkey = null;
_this.decrypturl = null;
return _this;
}
KeyLoader.prototype.destroy = function destroy() {
for (var loaderName in this.loaders) {
var loader = this.loaders[loaderName];
if (loader) {
loader.destroy();
}
}
this.loaders = {};
event_handler.prototype.destroy.call(this);
};
KeyLoader.prototype.onKeyLoading = function onKeyLoading(data) {
var frag = data.frag,
type = frag.type,
loader = this.loaders[type],
decryptdata = frag.decryptdata,
uri = decryptdata.uri;
// if uri is different from previous one or if decrypt key not retrieved yet
if (uri !== this.decrypturl || this.decryptkey === null) {
var config = this.hls.config;
if (loader) {
logger["b" /* logger */].warn('abort previous key loader for type:' + type);
loader.abort();
}
frag.loader = this.loaders[type] = new config.loader(config);
this.decrypturl = uri;
this.decryptkey = null;
var loaderContext = void 0,
loaderConfig = void 0,
loaderCallbacks = void 0;
loaderContext = { url: uri, frag: frag, responseType: 'arraybuffer' };
loaderConfig = { timeout: config.fragLoadingTimeOut, maxRetry: config.fragLoadingMaxRetry, retryDelay: config.fragLoadingRetryDelay, maxRetryDelay: config.fragLoadingMaxRetryTimeout };
loaderCallbacks = { onSuccess: this.loadsuccess.bind(this), onError: this.loaderror.bind(this), onTimeout: this.loadtimeout.bind(this) };
frag.loader.load(loaderContext, loaderConfig, loaderCallbacks);
} else if (this.decryptkey) {
// we already loaded this key, return it
decryptdata.key = this.decryptkey;
this.hls.trigger(events["a" /* default */].KEY_LOADED, { frag: frag });
}
};
KeyLoader.prototype.loadsuccess = function loadsuccess(response, stats, context) {
var frag = context.frag;
this.decryptkey = frag.decryptdata.key = new Uint8Array(response.data);
// detach fragment loader on load success
frag.loader = undefined;
this.loaders[frag.type] = undefined;
this.hls.trigger(events["a" /* default */].KEY_LOADED, { frag: frag });
};
KeyLoader.prototype.loaderror = function loaderror(response, context) {
var frag = context.frag,
loader = frag.loader;
if (loader) {
loader.abort();
}
this.loaders[context.type] = undefined;
this.hls.trigger(events["a" /* default */].ERROR, { type: errors["b" /* ErrorTypes */].NETWORK_ERROR, details: errors["a" /* ErrorDetails */].KEY_LOAD_ERROR, fatal: false, frag: frag, response: response });
};
KeyLoader.prototype.loadtimeout = function loadtimeout(stats, context) {
var frag = context.frag,
loader = frag.loader;
if (loader) {
loader.abort();
}
this.loaders[context.type] = undefined;
this.hls.trigger(events["a" /* default */].ERROR, { type: errors["b" /* ErrorTypes */].NETWORK_ERROR, details: errors["a" /* ErrorDetails */].KEY_LOAD_TIMEOUT, fatal: false, frag: frag });
};
return KeyLoader;
}(event_handler);
/* harmony default export */ var key_loader = (key_loader_KeyLoader);
// CONCATENATED MODULE: ./src/controller/fragment-tracker.js
function fragment_tracker__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function fragment_tracker__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : ...
function fragment_tracker__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Obj...
var FragmentState = {
NOT_LOADED: 'NOT_LOADED',
APPENDING: 'APPENDING',
PARTIAL: 'PARTIAL',
OK: 'OK'
};
var fragment_tracker_FragmentTracker = function (_EventHandler) {
fragment_tracker__inherits(FragmentTracker, _EventHandler);
function FragmentTracker(hls) {
fragment_tracker__classCallCheck(this, FragmentTracker);
var _this = fragment_tracker__possibleConstructorReturn(this, _EventHandler.call(this, hls, events["a" /* default */].BUFFER_APPENDED, events["a" /* default */].FRAG_BUFFERED, events["a" /* default */].FRAG_LOADED));
_this.bufferPadding = 0.2;
_this.fragments = Object.create(null);
_this.timeRanges = Object.create(null);
_this.config = hls.config;
return _this;
}
FragmentTracker.prototype.destroy = function destroy() {
this.fragments = null;
this.timeRanges = null;
this.config = null;
event_handler.prototype.destroy.call(this);
_EventHandler.prototype.destroy.call(this);
};
/**
* Return a Fragment that match the position and levelType.
* If not found any Fragment, return null
* @param {number} position
* @param {LevelType} levelType
* @returns {Fragment|null}
*/
FragmentTracker.prototype.getBufferedFrag = function getBufferedFrag(position, levelType) {
var fragments = this.fragments;
var bufferedFrags = Object.keys(fragments).filter(function (key) {
var fragmentEntity = fragments[key];
if (fragmentEntity.body.type !== levelType) {
return false;
}
if (!fragmentEntity.buffered) {
return false;
}
var frag = fragmentEntity.body;
return frag.startPTS <= position && position <= frag.endPTS;
});
share/public_html/static/hls.js view on Meta::CPAN
FragmentTracker.prototype.removeFragment = function removeFragment(fragment) {
var fragKey = this.getFragmentKey(fragment);
delete this.fragments[fragKey];
};
/**
* Remove all fragments from fragment tracker.
*/
FragmentTracker.prototype.removeAllFragments = function removeAllFragments() {
this.fragments = Object.create(null);
};
return FragmentTracker;
}(event_handler);
// CONCATENATED MODULE: ./src/utils/binary-search.js
var BinarySearch = {
/**
* Searches for an item in an array which matches a certain condition.
* This requires the condition to only match one item in the array,
* and for the array to be ordered.
*
* @param {Array} list The array to search.
* @param {Function} comparisonFunction
* Called and provided a candidate item as the first argument.
* Should return:
* > -1 if the item should be located at a lower index than the provided item.
* > 1 if the item should be located at a higher index than the provided item.
* > 0 if the item is the item you're looking for.
*
* @return {*} The object if it is found or null otherwise.
*/
search: function search(list, comparisonFunction) {
var minIndex = 0;
var maxIndex = list.length - 1;
var currentIndex = null;
var currentElement = null;
while (minIndex <= maxIndex) {
currentIndex = (minIndex + maxIndex) / 2 | 0;
currentElement = list[currentIndex];
var comparisonResult = comparisonFunction(currentElement);
if (comparisonResult > 0) {
minIndex = currentIndex + 1;
} else if (comparisonResult < 0) {
maxIndex = currentIndex - 1;
} else {
return currentElement;
}
}
return null;
}
};
/* harmony default export */ var binary_search = (BinarySearch);
// CONCATENATED MODULE: ./src/utils/buffer-helper.js
function buffer_helper__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* @module BufferHelper
*
* Providing methods dealing with buffer length retrieval for example.
*
* In general, a helper around HTML5 MediaElement TimeRanges gathered from `buffered` property.
*
* Also @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/buffered
*/
var BufferHelper = function () {
function BufferHelper() {
buffer_helper__classCallCheck(this, BufferHelper);
}
/**
* Return true if `media`'s buffered include `position`
* @param {HTMLMediaElement|SourceBuffer} media
* @param {number} position
* @returns {boolean}
*/
BufferHelper.isBuffered = function isBuffered(media, position) {
try {
if (media) {
var buffered = media.buffered;
for (var i = 0; i < buffered.length; i++) {
if (position >= buffered.start(i) && position <= buffered.end(i)) {
return true;
}
}
}
} catch (error) {
// this is to catch
// InvalidStateError: Failed to read the 'buffered' property from 'SourceBuffer':
// This SourceBuffer has been removed from the parent media source
}
return false;
};
BufferHelper.bufferInfo = function bufferInfo(media, pos, maxHoleDuration) {
try {
if (media) {
var vbuffered = media.buffered,
buffered = [],
i = void 0;
for (i = 0; i < vbuffered.length; i++) {
buffered.push({ start: vbuffered.start(i), end: vbuffered.end(i) });
}
return this.bufferedInfo(buffered, pos, maxHoleDuration);
}
} catch (error) {
// this is to catch
// InvalidStateError: Failed to read the 'buffered' property from 'SourceBuffer':
// This SourceBuffer has been removed from the parent media source
}
return { len: 0, start: pos, end: pos, nextStart: undefined };
};
share/public_html/static/hls.js view on Meta::CPAN
// merge overlapping time ranges
// update lastRange.end only if smaller than item.end
// e.g. [ 1, 15] with [ 2,8] => [ 1,15] (no need to modify lastRange.end)
// whereas [ 1, 8] with [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15])
if (buffered[i].end > buf2end) {
buffered2[buf2len - 1].end = buffered[i].end;
}
} else {
// big hole
buffered2.push(buffered[i]);
}
} else {
// first value
buffered2.push(buffered[i]);
}
}
for (i = 0, bufferLen = 0, bufferStart = bufferEnd = pos; i < buffered2.length; i++) {
var start = buffered2[i].start,
end = buffered2[i].end;
// logger.log('buf start/end:' + buffered.start(i) + '/' + buffered.end(i));
if (pos + maxHoleDuration >= start && pos < end) {
// play position is inside this buffer TimeRange, retrieve end of buffer position and buffer length
bufferStart = start;
bufferEnd = end;
bufferLen = bufferEnd - pos;
} else if (pos + maxHoleDuration < start) {
bufferStartNext = start;
break;
}
}
return { len: bufferLen, start: bufferStart, end: bufferEnd, nextStart: bufferStartNext };
};
return BufferHelper;
}();
// EXTERNAL MODULE: ./node_modules/events/events.js
var events_events = __webpack_require__(6);
var events_default = /*#__PURE__*/__webpack_require__.n(events_events);
// EXTERNAL MODULE: ./node_modules/webworkify-webpack/index.js
var webworkify_webpack = __webpack_require__(11);
var webworkify_webpack_default = /*#__PURE__*/__webpack_require__.n(webworkify_webpack);
// EXTERNAL MODULE: ./src/demux/demuxer-inline.js + 11 modules
var demuxer_inline = __webpack_require__(9);
// CONCATENATED MODULE: ./src/utils/mediasource-helper.js
/**
* MediaSource helper
*/
function getMediaSource() {
if (typeof window !== 'undefined') {
return window.MediaSource || window.WebKitMediaSource;
}
}
// EXTERNAL MODULE: ./src/utils/get-self-scope.js
var get_self_scope = __webpack_require__(3);
// CONCATENATED MODULE: ./src/demux/demuxer.js
function demuxer__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
// see https://stackoverflow.com/a/11237259/589493
var global = Object(get_self_scope["a" /* getSelfScope */])(); // safeguard for code that might run both on worker and main thread
var MediaSource = getMediaSource();
var demuxer_Demuxer = function () {
function Demuxer(hls, id) {
demuxer__classCallCheck(this, Demuxer);
this.hls = hls;
this.id = id;
// observer setup
var observer = this.observer = new events_default.a();
var config = hls.config;
observer.trigger = function trigger(event) {
for (var _len = arguments.length, data = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
data[_key - 1] = arguments[_key];
}
observer.emit.apply(observer, [event, event].concat(data));
};
observer.off = function off(event) {
for (var _len2 = arguments.length, data = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
data[_key2 - 1] = arguments[_key2];
}
observer.removeListener.apply(observer, [event].concat(data));
};
var forwardMessage = function (ev, data) {
data = data || {};
data.frag = this.frag;
data.id = this.id;
hls.trigger(ev, data);
}.bind(this);
// forward events to main thread
observer.on(events["a" /* default */].FRAG_DECRYPTED, forwardMessage);
observer.on(events["a" /* default */].FRAG_PARSING_INIT_SEGMENT, forwardMessage);
observer.on(events["a" /* default */].FRAG_PARSING_DATA, forwardMessage);
observer.on(events["a" /* default */].FRAG_PARSED, forwardMessage);
observer.on(events["a" /* default */].ERROR, forwardMessage);
observer.on(events["a" /* default */].FRAG_PARSING_METADATA, forwardMessage);
observer.on(events["a" /* default */].FRAG_PARSING_USERDATA, forwardMessage);
observer.on(events["a" /* default */].INIT_PTS_FOUND, forwardMessage);
var typeSupported = {
mp4: MediaSource.isTypeSupported('video/mp4'),
mpeg: MediaSource.isTypeSupported('audio/mpeg'),
share/public_html/static/hls.js view on Meta::CPAN
}
// Find the first frag in the previous level which matches the CC of the first frag of the new level
function findDiscontinuousReferenceFrag(prevDetails, curDetails) {
var prevFrags = prevDetails.fragments;
var curFrags = curDetails.fragments;
if (!curFrags.length || !prevFrags.length) {
logger["b" /* logger */].log('No fragments to align');
return;
}
var prevStartFrag = findFirstFragWithCC(prevFrags, curFrags[0].cc);
if (!prevStartFrag || prevStartFrag && !prevStartFrag.startPTS) {
logger["b" /* logger */].log('No frag in previous level to align on');
return;
}
return prevStartFrag;
}
function adjustPts(sliding, details) {
details.fragments.forEach(function (frag) {
if (frag) {
var start = frag.start + sliding;
frag.start = frag.startPTS = start;
frag.endPTS = start + frag.duration;
}
});
details.PTSKnown = true;
}
// If a change in CC is detected, the PTS can no longer be relied upon
// Attempt to align the level by using the last level - find the last frag matching the current CC and use it's PTS
// as a reference
function alignDiscontinuities(lastFrag, lastLevel, details) {
if (shouldAlignOnDiscontinuities(lastFrag, lastLevel, details)) {
var referenceFrag = findDiscontinuousReferenceFrag(lastLevel.details, details);
if (referenceFrag) {
logger["b" /* logger */].log('Adjusting PTS using last level due to CC increase within current level');
adjustPts(referenceFrag.start, details);
}
}
// try to align using programDateTime attribute (if available)
if (details.PTSKnown === false && lastLevel && lastLevel.details && lastLevel.details.fragments && lastLevel.details.fragments.length) {
// if last level sliding is 1000 and its first frag PROGRAM-DATE-TIME is 2017-08-20 1:10:00 AM
// and if new details first frag PROGRAM DATE-TIME is 2017-08-20 1:10:08 AM
// then we can deduce that playlist B sliding is 1000+8 = 1008s
var lastPDT = lastLevel.details.programDateTime;
var newPDT = details.programDateTime;
// date diff is in ms. frag.start is in seconds
var sliding = (newPDT - lastPDT) / 1000 + lastLevel.details.fragments[0].start;
if (!isNaN(sliding)) {
logger["b" /* logger */].log('adjusting PTS using programDateTime delta, sliding:' + sliding.toFixed(3));
adjustPts(sliding, details);
}
}
}
// CONCATENATED MODULE: ./src/task-loop.js
function task_loop__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function task_loop__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function task_loop__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.cre...
/**
* Sub-class specialization of EventHandler base class.
*
* TaskLoop allows to schedule a task function being called (optionnaly repeatedly) on the main loop,
* scheduled asynchroneously, avoiding recursive calls in the same tick.
*
* The task itself is implemented in `doTick`. It can be requested and called for single execution
* using the `tick` method.
*
* It will be assured that the task execution method (`tick`) only gets called once per main loop "tick",
* no matter how often it gets requested for execution. Execution in further ticks will be scheduled accordingly.
*
* If further execution requests have already been scheduled on the next tick, it can be checked with `hasNextTick`,
* and cancelled with `clearNextTick`.
*
* The task can be scheduled as an interval repeatedly with a period as parameter (see `setInterval`, `clearInterval`).
*
* Sub-classes need to implement the `doTick` method which will effectively have the task execution routine.
*
* Further explanations:
*
* The baseclass has a `tick` method that will schedule the doTick call. It may be called synchroneously
* only for a stack-depth of one. On re-entrant calls, sub-sequent calls are scheduled for next main loop ticks.
*
* When the task execution (`tick` method) is called in re-entrant way this is detected and
* we are limiting the task execution per call stack to exactly one, but scheduling/post-poning further
* task processing on the next main loop iteration (also known as "next tick" in the Node/JS runtime lingo).
*/
var TaskLoop = function (_EventHandler) {
task_loop__inherits(TaskLoop, _EventHandler);
function TaskLoop(hls) {
task_loop__classCallCheck(this, TaskLoop);
for (var _len = arguments.length, events = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
events[_key - 1] = arguments[_key];
}
var _this = task_loop__possibleConstructorReturn(this, _EventHandler.call.apply(_EventHandler, [this, hls].concat(events)));
_this._tickInterval = null;
_this._tickTimer = null;
_this._tickCallCount = 0;
_this._boundTick = _this.tick.bind(_this);
return _this;
}
/**
* @override
*/
TaskLoop.prototype.onHandlerDestroying = function onHandlerDestroying() {
// clear all timers before unregistering from event bus
this.clearNextTick();
this.clearInterval();
share/public_html/static/hls.js view on Meta::CPAN
var bufferEnd = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var end = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
var maxFragLookUpTolerance = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
var foundFrag = void 0;
var fragNext = fragPrevious ? fragments[fragPrevious.sn - fragments[0].sn + 1] : null;
if (bufferEnd < end) {
if (bufferEnd > end - maxFragLookUpTolerance) {
maxFragLookUpTolerance = 0;
}
// Prefer the next fragment if it's within tolerance
if (fragNext && !fragment_finders_fragmentWithinToleranceTest(bufferEnd, maxFragLookUpTolerance, fragNext)) {
foundFrag = fragNext;
} else {
foundFrag = binary_search.search(fragments, fragment_finders_fragmentWithinToleranceTest.bind(null, bufferEnd, maxFragLookUpTolerance));
}
}
return foundFrag;
}
/**
* The test function used by the findFragmentBySn's BinarySearch to look for the best match to the current buffer conditions.
* @param {*} candidate - The fragment to test
* @param {number} [bufferEnd = 0] - The end of the current buffered range the playhead is currently within
* @param {number} [maxFragLookUpTolerance = 0] - The amount of time that a fragment's start can be within in order to be considered contiguous
* @returns {number} - 0 if it matches, 1 if too low, -1 if too high
*/
function fragment_finders_fragmentWithinToleranceTest() {
var bufferEnd = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var maxFragLookUpTolerance = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var candidate = arguments[2];
// offset should be within fragment boundary - config.maxFragLookUpTolerance
// this is to cope with situations like
// bufferEnd = 9.991
// frag[Ã] : [0,10]
// frag[1] : [10,20]
// bufferEnd is within frag[0] range ... although what we are expecting is to return frag[1] here
// frag start frag start+duration
// |-----------------------------|
// <---> <--->
// ...--------><-----------------------------><---------....
// previous frag matching fragment next frag
// return -1 return 0 return 1
// logger.log(`level/sn/start/end/bufEnd:${level}/${candidate.sn}/${candidate.start}/${(candidate.start+candidate.duration)}/${bufferEnd}`);
// Set the lookup tolerance to be small enough to detect the current segment - ensures we don't skip over very small segments
var candidateLookupTolerance = Math.min(maxFragLookUpTolerance, candidate.duration + (candidate.deltaPTS ? candidate.deltaPTS : 0));
if (candidate.start + candidate.duration - candidateLookupTolerance <= bufferEnd) {
return 1;
} else if (candidate.start - candidateLookupTolerance > bufferEnd && candidate.start) {
// if maxFragLookUpTolerance will have negative value then don't return -1 for first element
return -1;
}
return 0;
}
// CONCATENATED MODULE: ./src/controller/stream-controller.js
var stream_controller__createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; ...
function stream_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function stream_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call :...
function stream_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Ob...
/*
* Stream Controller
*/
var State = {
STOPPED: 'STOPPED',
IDLE: 'IDLE',
KEY_LOADING: 'KEY_LOADING',
FRAG_LOADING: 'FRAG_LOADING',
FRAG_LOADING_WAITING_RETRY: 'FRAG_LOADING_WAITING_RETRY',
WAITING_LEVEL: 'WAITING_LEVEL',
PARSING: 'PARSING',
PARSED: 'PARSED',
BUFFER_FLUSHING: 'BUFFER_FLUSHING',
ENDED: 'ENDED',
ERROR: 'ERROR'
};
var stream_controller_StreamController = function (_TaskLoop) {
stream_controller__inherits(StreamController, _TaskLoop);
function StreamController(hls, fragmentTracker) {
stream_controller__classCallCheck(this, StreamController);
var _this = stream_controller__possibleConstructorReturn(this, _TaskLoop.call(this, hls, events["a" /* default */].MEDIA_ATTACHED, events["a" /* default */].MEDIA_DETACHING, events["a" /* default */].MANIFEST_LOADING, events["a" /* default */].MA...
_this.fragmentTracker = fragmentTracker;
_this.config = hls.config;
_this.audioCodecSwap = false;
_this._state = State.STOPPED;
_this.stallReported = false;
return _this;
}
StreamController.prototype.onHandlerDestroying = function onHandlerDestroying() {
this.stopLoad();
_TaskLoop.prototype.onHandlerDestroying.call(this);
};
StreamController.prototype.onHandlerDestroyed = function onHandlerDestroyed() {
this.state = State.STOPPED;
this.fragmentTracker = null;
_TaskLoop.prototype.onHandlerDestroyed.call(this);
};
share/public_html/static/hls.js view on Meta::CPAN
this._state = nextState;
logger["b" /* logger */].log('main stream:' + previousState + '->' + nextState);
this.hls.trigger(events["a" /* default */].STREAM_STATE_TRANSITION, { previousState: previousState, nextState: nextState });
}
},
get: function get() {
return this._state;
}
}, {
key: 'currentLevel',
get: function get() {
var media = this.media;
if (media) {
var frag = this.getBufferedFrag(media.currentTime);
if (frag) {
return frag.level;
}
}
return -1;
}
}, {
key: 'nextBufferedFrag',
get: function get() {
var media = this.media;
if (media) {
// first get end range of current fragment
return this.followingBufferedFrag(this.getBufferedFrag(media.currentTime));
} else {
return null;
}
}
}, {
key: 'nextLevel',
get: function get() {
var frag = this.nextBufferedFrag;
if (frag) {
return frag.level;
} else {
return -1;
}
}
}, {
key: 'liveSyncPosition',
get: function get() {
return this._liveSyncPosition;
},
set: function set(value) {
this._liveSyncPosition = value;
}
}]);
return StreamController;
}(task_loop);
/* harmony default export */ var stream_controller = (stream_controller_StreamController);
// CONCATENATED MODULE: ./src/controller/level-controller.js
var level_controller__typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.p...
var level_controller__createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; i...
function level_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function level_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : ...
function level_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Obj...
/*
* Level Controller
*/
var level_controller__window = window,
level_controller_performance = level_controller__window.performance;
var level_controller_LevelController = function (_EventHandler) {
level_controller__inherits(LevelController, _EventHandler);
function LevelController(hls) {
level_controller__classCallCheck(this, LevelController);
var _this = level_controller__possibleConstructorReturn(this, _EventHandler.call(this, hls, events["a" /* default */].MANIFEST_LOADED, events["a" /* default */].LEVEL_LOADED, events["a" /* default */].AUDIO_TRACK_SWITCHED, events["a" /* default *...
_this.canload = false;
_this.currentLevelIndex = null;
_this.manualLevelIndex = -1;
_this.timer = null;
return _this;
}
LevelController.prototype.onHandlerDestroying = function onHandlerDestroying() {
this.clearTimer();
this.manualLevelIndex = -1;
};
LevelController.prototype.clearTimer = function clearTimer() {
if (this.timer !== null) {
clearTimeout(this.timer);
this.timer = null;
}
};
LevelController.prototype.startLoad = function startLoad() {
var levels = this._levels;
this.canload = true;
this.levelRetryCount = 0;
// clean up live level details to force reload them, and reset load errors
if (levels) {
levels.forEach(function (level) {
level.loadError = 0;
var levelDetails = level.details;
if (levelDetails && levelDetails.live) {
level.details = undefined;
}
});
}
// speed up live playlist refresh if timer exists
if (this.timer !== null) {
share/public_html/static/hls.js view on Meta::CPAN
var configStartLevel = this.hls.config.startLevel;
if (configStartLevel !== undefined) {
return configStartLevel;
} else {
return this._firstLevel;
}
} else {
return this._startLevel;
}
},
set: function set(newLevel) {
this._startLevel = newLevel;
}
}, {
key: 'nextLoadLevel',
get: function get() {
if (this.manualLevelIndex !== -1) {
return this.manualLevelIndex;
} else {
return this.hls.nextAutoLevel;
}
},
set: function set(nextLevel) {
this.level = nextLevel;
if (this.manualLevelIndex === -1) {
this.hls.nextAutoLevel = nextLevel;
}
}
}]);
return LevelController;
}(event_handler);
/* harmony default export */ var level_controller = (level_controller_LevelController);
// EXTERNAL MODULE: ./src/demux/id3.js
var id3 = __webpack_require__(5);
// CONCATENATED MODULE: ./src/utils/texttrack-utils.js
function sendAddTrackEvent(track, videoEl) {
var event = null;
try {
event = new window.Event('addtrack');
} catch (err) {
// for IE11
event = document.createEvent('Event');
event.initEvent('addtrack', false, false);
}
event.track = track;
videoEl.dispatchEvent(event);
}
function clearCurrentCues(track) {
if (track && track.cues) {
while (track.cues.length > 0) {
track.removeCue(track.cues[0]);
}
}
}
// CONCATENATED MODULE: ./src/controller/id3-track-controller.js
function id3_track_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function id3_track_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? cal...
function id3_track_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype =...
/*
* id3 metadata track controller
*/
var id3_track_controller_ID3TrackController = function (_EventHandler) {
id3_track_controller__inherits(ID3TrackController, _EventHandler);
function ID3TrackController(hls) {
id3_track_controller__classCallCheck(this, ID3TrackController);
var _this = id3_track_controller__possibleConstructorReturn(this, _EventHandler.call(this, hls, events["a" /* default */].MEDIA_ATTACHED, events["a" /* default */].MEDIA_DETACHING, events["a" /* default */].FRAG_PARSING_METADATA));
_this.id3Track = undefined;
_this.media = undefined;
return _this;
}
ID3TrackController.prototype.destroy = function destroy() {
event_handler.prototype.destroy.call(this);
};
// Add ID3 metatadata text track.
ID3TrackController.prototype.onMediaAttached = function onMediaAttached(data) {
this.media = data.media;
if (!this.media) {}
};
ID3TrackController.prototype.onMediaDetaching = function onMediaDetaching() {
clearCurrentCues(this.id3Track);
this.id3Track = undefined;
this.media = undefined;
};
ID3TrackController.prototype.getID3Track = function getID3Track(textTracks) {
for (var i = 0; i < textTracks.length; i++) {
var textTrack = textTracks[i];
if (textTrack.kind === 'metadata' && textTrack.label === 'id3') {
// send 'addtrack' when reusing the textTrack for metadata,
// same as what we do for captions
sendAddTrackEvent(textTrack, this.media);
return textTrack;
}
}
return this.media.addTextTrack('metadata', 'id3');
};
ID3TrackController.prototype.onFragParsingMetadata = function onFragParsingMetadata(data) {
var fragment = data.frag;
var samples = data.samples;
// create track dynamically
if (!this.id3Track) {
this.id3Track = this.getID3Track(this.media.textTracks);
this.id3Track.mode = 'hidden';
}
// Attempt to recreate Safari functionality by creating
// WebKitDataCue objects when available and store the decoded
// ID3 data in the value property of the cue
var Cue = window.WebKitDataCue || window.VTTCue || window.TextTrackCue;
for (var i = 0; i < samples.length; i++) {
var frames = id3["a" /* default */].getID3Frames(samples[i].data);
if (frames) {
var startTime = samples[i].pts;
var endTime = i < samples.length - 1 ? samples[i + 1].pts : fragment.endPTS;
// Give a slight bump to the endTime if it's equal to startTime to avoid a SyntaxError in IE
if (startTime === endTime) {
endTime += 0.0001;
}
for (var j = 0; j < frames.length; j++) {
var frame = frames[j];
// Safari doesn't put the timestamp frame in the TextTrack
if (!id3["a" /* default */].isTimeStampFrame(frame)) {
var cue = new Cue(startTime, endTime, '');
cue.value = frame;
this.id3Track.addCue(cue);
}
}
}
}
};
return ID3TrackController;
}(event_handler);
/* harmony default export */ var id3_track_controller = (id3_track_controller_ID3TrackController);
// CONCATENATED MODULE: ./src/is-supported.js
function is_supported_isSupported() {
var mediaSource = getMediaSource();
var sourceBuffer = window.SourceBuffer || window.WebKitSourceBuffer;
var isTypeSupported = mediaSource && typeof mediaSource.isTypeSupported === 'function' && mediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"');
// if SourceBuffer is exposed ensure its API is valid
// safari and old version of Chrome doe not expose SourceBuffer globally so checking SourceBuffer.prototype is impossible
var sourceBufferValidAPI = !sourceBuffer || sourceBuffer.prototype && typeof sourceBuffer.prototype.appendBuffer === 'function' && typeof sourceBuffer.prototype.remove === 'function';
return !!isTypeSupported && !!sourceBufferValidAPI;
}
// CONCATENATED MODULE: ./src/utils/ewma.js
function ewma__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/*
* compute an Exponential Weighted moving average
* - https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
* - heavily inspired from shaka-player
*/
var EWMA = function () {
// About half of the estimated value will be from the last |halfLife| samples by weight.
function EWMA(halfLife) {
ewma__classCallCheck(this, EWMA);
// Larger values of alpha expire historical data more slowly.
this.alpha_ = halfLife ? Math.exp(Math.log(0.5) / halfLife) : 0;
this.estimate_ = 0;
this.totalWeight_ = 0;
}
EWMA.prototype.sample = function sample(weight, value) {
var adjAlpha = Math.pow(this.alpha_, weight);
this.estimate_ = value * (1 - adjAlpha) + adjAlpha * this.estimate_;
this.totalWeight_ += weight;
};
EWMA.prototype.getTotalWeight = function getTotalWeight() {
return this.totalWeight_;
};
EWMA.prototype.getEstimate = function getEstimate() {
if (this.alpha_) {
var zeroFactor = 1 - Math.pow(this.alpha_, this.totalWeight_);
return this.estimate_ / zeroFactor;
} else {
return this.estimate_;
}
};
return EWMA;
}();
/* harmony default export */ var ewma = (EWMA);
// CONCATENATED MODULE: ./src/utils/ewma-bandwidth-estimator.js
function ewma_bandwidth_estimator__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/*
* EWMA Bandwidth Estimator
* - heavily inspired from shaka-player
* Tracks bandwidth samples and estimates available bandwidth.
* Based on the minimum of two exponentially-weighted moving averages with
* different half-lives.
*/
var ewma_bandwidth_estimator_EwmaBandWidthEstimator = function () {
function EwmaBandWidthEstimator(hls, slow, fast, defaultEstimate) {
ewma_bandwidth_estimator__classCallCheck(this, EwmaBandWidthEstimator);
this.hls = hls;
this.defaultEstimate_ = defaultEstimate;
this.minWeight_ = 0.001;
this.minDelayMs_ = 50;
this.slow_ = new ewma(slow);
this.fast_ = new ewma(fast);
}
EwmaBandWidthEstimator.prototype.sample = function sample(durationMs, numBytes) {
durationMs = Math.max(durationMs, this.minDelayMs_);
var bandwidth = 8000 * numBytes / durationMs,
// console.log('instant bw:'+ Math.round(bandwidth));
// we weight sample using loading duration....
weight = durationMs / 1000;
this.fast_.sample(weight, bandwidth);
this.slow_.sample(weight, bandwidth);
};
EwmaBandWidthEstimator.prototype.canEstimate = function canEstimate() {
var fast = this.fast_;
return fast && fast.getTotalWeight() >= this.minWeight_;
};
EwmaBandWidthEstimator.prototype.getEstimate = function getEstimate() {
if (this.canEstimate()) {
// console.log('slow estimate:'+ Math.round(this.slow_.getEstimate()));
// console.log('fast estimate:'+ Math.round(this.fast_.getEstimate()));
// Take the minimum of these two estimates. This should have the effect of
// adapting down quickly, but up more slowly.
return Math.min(this.fast_.getEstimate(), this.slow_.getEstimate());
} else {
return this.defaultEstimate_;
}
};
EwmaBandWidthEstimator.prototype.destroy = function destroy() {};
return EwmaBandWidthEstimator;
}();
/* harmony default export */ var ewma_bandwidth_estimator = (ewma_bandwidth_estimator_EwmaBandWidthEstimator);
// CONCATENATED MODULE: ./src/controller/abr-controller.js
var abr_controller__createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ...
function abr_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function abr_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : se...
function abr_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Objec...
/*
* simple ABR Controller
* - compute next level based on last fragment bw heuristics
* - implement an abandon rules triggered if we have less than 2 frag buffered and if computed bw shows that we risk buffer stalling
*/
var abr_controller__window = window,
abr_controller_performance = abr_controller__window.performance;
var abr_controller_AbrController = function (_EventHandler) {
abr_controller__inherits(AbrController, _EventHandler);
function AbrController(hls) {
abr_controller__classCallCheck(this, AbrController);
var _this = abr_controller__possibleConstructorReturn(this, _EventHandler.call(this, hls, events["a" /* default */].FRAG_LOADING, events["a" /* default */].FRAG_LOADED, events["a" /* default */].FRAG_BUFFERED, events["a" /* default */].ERROR));
_this.lastLoadedFragLevel = 0;
_this._nextAutoLevel = -1;
_this.hls = hls;
_this.timer = null;
_this._bwEstimator = null;
_this.onCheck = _this._abandonRulesCheck.bind(_this);
return _this;
}
AbrController.prototype.destroy = function destroy() {
this.clearTimer();
event_handler.prototype.destroy.call(this);
};
AbrController.prototype.onFragLoading = function onFragLoading(data) {
var frag = data.frag;
if (frag.type === 'main') {
if (!this.timer) {
this.fragCurrent = frag;
this.timer = setInterval(this.onCheck, 100);
}
// lazy init of BwEstimator, rationale is that we use different params for Live/VoD
// so we need to wait for stream manifest / playlist type to instantiate it.
if (!this._bwEstimator) {
var hls = this.hls;
var config = hls.config;
var level = frag.level;
var isLive = hls.levels[level].details.live;
var ewmaFast = void 0,
ewmaSlow = void 0;
if (isLive) {
ewmaFast = config.abrEwmaFastLive;
ewmaSlow = config.abrEwmaSlowLive;
share/public_html/static/hls.js view on Meta::CPAN
}
}, {
key: '_nextABRAutoLevel',
get: function get() {
var hls = this.hls,
maxAutoLevel = hls.maxAutoLevel,
levels = hls.levels,
config = hls.config,
minAutoLevel = hls.minAutoLevel;
var video = hls.media,
currentLevel = this.lastLoadedFragLevel,
currentFragDuration = this.fragCurrent ? this.fragCurrent.duration : 0,
pos = video ? video.currentTime : 0,
// playbackRate is the absolute value of the playback rate; if video.playbackRate is 0, we use 1 to load as
// if we're playing back at the normal rate.
playbackRate = video && video.playbackRate !== 0 ? Math.abs(video.playbackRate) : 1.0,
avgbw = this._bwEstimator ? this._bwEstimator.getEstimate() : config.abrEwmaDefaultEstimate,
// bufferStarvationDelay is the wall-clock time left until the playback buffer is exhausted.
bufferStarvationDelay = (BufferHelper.bufferInfo(video, pos, config.maxBufferHole).end - pos) / playbackRate;
// First, look to see if we can find a level matching with our avg bandwidth AND that could also guarantee no rebuffering at all
var bestLevel = this._findBestLevel(currentLevel, currentFragDuration, avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay, config.abrBandWidthFactor, config.abrBandWidthUpFactor, levels);
if (bestLevel >= 0) {
return bestLevel;
} else {
logger["b" /* logger */].trace('rebuffering expected to happen, lets try to find a quality level minimizing the rebuffering');
// not possible to get rid of rebuffering ... let's try to find level that will guarantee less than maxStarvationDelay of rebuffering
// if no matching level found, logic will return 0
var maxStarvationDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxStarvationDelay) : config.maxStarvationDelay,
bwFactor = config.abrBandWidthFactor,
bwUpFactor = config.abrBandWidthUpFactor;
if (bufferStarvationDelay === 0) {
// in case buffer is empty, let's check if previous fragment was loaded to perform a bitrate test
var bitrateTestDelay = this.bitrateTestDelay;
if (bitrateTestDelay) {
// if it is the case, then we need to adjust our max starvation delay using maxLoadingDelay config value
// max video loading delay used in automatic start level selection :
// in that mode ABR controller will ensure that video loading time (ie the time to fetch the first fragment at lowest quality level +
// the time to fetch the fragment at the appropriate quality level is less than ```maxLoadingDelay``` )
// cap maxLoadingDelay and ensure it is not bigger 'than bitrate test' frag duration
var maxLoadingDelay = currentFragDuration ? Math.min(currentFragDuration, config.maxLoadingDelay) : config.maxLoadingDelay;
maxStarvationDelay = maxLoadingDelay - bitrateTestDelay;
logger["b" /* logger */].trace('bitrate test took ' + Math.round(1000 * bitrateTestDelay) + 'ms, set first fragment max fetchDuration to ' + Math.round(1000 * maxStarvationDelay) + ' ms');
// don't use conservative factor on bitrate test
bwFactor = bwUpFactor = 1;
}
}
bestLevel = this._findBestLevel(currentLevel, currentFragDuration, avgbw, minAutoLevel, maxAutoLevel, bufferStarvationDelay + maxStarvationDelay, bwFactor, bwUpFactor, levels);
return Math.max(bestLevel, 0);
}
}
}]);
return AbrController;
}(event_handler);
/* harmony default export */ var abr_controller = (abr_controller_AbrController);
// CONCATENATED MODULE: ./src/controller/buffer-controller.js
function buffer_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function buffer_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call :...
function buffer_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Ob...
/*
* Buffer Controller
*/
var buffer_controller_MediaSource = getMediaSource();
var buffer_controller_BufferController = function (_EventHandler) {
buffer_controller__inherits(BufferController, _EventHandler);
function BufferController(hls) {
buffer_controller__classCallCheck(this, BufferController);
// the value that we have set mediasource.duration to
// (the actual duration may be tweaked slighly by the browser)
var _this = buffer_controller__possibleConstructorReturn(this, _EventHandler.call(this, hls, events["a" /* default */].MEDIA_ATTACHING, events["a" /* default */].MEDIA_DETACHING, events["a" /* default */].MANIFEST_PARSED, events["a" /* default */...
_this._msDuration = null;
// the value that we want to set mediaSource.duration to
_this._levelDuration = null;
// current stream state: true - for live broadcast, false - for VoD content
_this._live = null;
// cache the self generated object url to detect hijack of video tag
_this._objectUrl = null;
// Source Buffer listeners
_this.onsbue = _this.onSBUpdateEnd.bind(_this);
_this.onsbe = _this.onSBUpdateError.bind(_this);
_this.pendingTracks = {};
_this.tracks = {};
return _this;
}
BufferController.prototype.destroy = function destroy() {
event_handler.prototype.destroy.call(this);
};
BufferController.prototype.onLevelPtsUpdated = function onLevelPtsUpdated(data) {
var type = data.type;
var audioTrack = this.tracks.audio;
// Adjusting `SourceBuffer.timestampOffset` (desired point in the timeline where the next frames should be appended)
// in Chrome browser when we detect MPEG audio container and time delta between level PTS and `SourceBuffer.timestampOffset`
// is greater than 100ms (this is enough to handle seek for VOD or level change for LIVE videos). At the time of change we issue
// `SourceBuffer.abort()` and adjusting `SourceBuffer.timestampOffset` if `SourceBuffer.updating` is false or awaiting `updateend`
// event if SB is in updating state.
// More info here: https://github.com/video-dev/hls.js/issues/332#issuecomment-257986486
if (type === 'audio' && audioTrack && audioTrack.container === 'audio/mpeg') {
// Chrome audio mp3 track
var audioBuffer = this.sourceBuffer.audio;
var delta = Math.abs(audioBuffer.timestampOffset - data.start);
// adjust timestamp offset if time delta is greater than 100ms
share/public_html/static/hls.js view on Meta::CPAN
var duration = void 0;
if (this._levelDuration === null || !this.media || !this.mediaSource || !this.sourceBuffer || this.media.readyState === 0 || this.mediaSource.readyState !== 'open') {
return;
}
for (var type in this.sourceBuffer) {
if (this.sourceBuffer[type].updating === true) {
// can't set duration whilst a buffer is updating
return;
}
}
duration = this.media.duration;
// initialise to the value that the media source is reporting
if (this._msDuration === null) {
this._msDuration = this.mediaSource.duration;
}
if (this._live === true && config.liveDurationInfinity === true) {
// Override duration to Infinity
logger["b" /* logger */].log('Media Source duration is set to Infinity');
this._msDuration = this.mediaSource.duration = Infinity;
} else if (this._levelDuration > this._msDuration && this._levelDuration > duration || duration === Infinity || isNaN(duration)) {
// levelDuration was the last value we set.
// not using mediaSource.duration as the browser may tweak this value
// only update Media Source duration if its value increase, this is to avoid
// flushing already buffered portion when switching between quality level
logger["b" /* logger */].log('Updating Media Source duration to ' + this._levelDuration.toFixed(3));
this._msDuration = this.mediaSource.duration = this._levelDuration;
}
};
BufferController.prototype.doFlush = function doFlush() {
// loop through all buffer ranges to flush
while (this.flushRange.length) {
var range = this.flushRange[0];
// flushBuffer will abort any buffer append in progress and flush Audio/Video Buffer
if (this.flushBuffer(range.start, range.end, range.type)) {
// range flushed, remove from flush array
this.flushRange.shift();
this.flushBufferCounter = 0;
} else {
this._needsFlush = true;
// avoid looping, wait for SB update end to retrigger a flush
return;
}
}
if (this.flushRange.length === 0) {
// everything flushed
this._needsFlush = false;
// let's recompute this.appended, which is used to avoid flush looping
var appended = 0;
var sourceBuffer = this.sourceBuffer;
try {
for (var type in sourceBuffer) {
appended += sourceBuffer[type].buffered.length;
}
} catch (error) {
// error could be thrown while accessing buffered, in case sourcebuffer has already been removed from MediaSource
// this is harmess at this stage, catch this to avoid reporting an internal exception
logger["b" /* logger */].error('error while accessing sourceBuffer.buffered');
}
this.appended = appended;
this.hls.trigger(events["a" /* default */].BUFFER_FLUSHED);
}
};
BufferController.prototype.doAppending = function doAppending() {
var hls = this.hls,
sourceBuffer = this.sourceBuffer,
segments = this.segments;
if (Object.keys(sourceBuffer).length) {
if (this.media.error) {
this.segments = [];
logger["b" /* logger */].error('trying to append although a media error occured, flush segment and abort');
return;
}
if (this.appending) {
// logger.log(`sb appending in progress`);
return;
}
if (segments && segments.length) {
var segment = segments.shift();
try {
var type = segment.type,
sb = sourceBuffer[type];
if (sb) {
if (!sb.updating) {
// reset sourceBuffer ended flag before appending segment
sb.ended = false;
// logger.log(`appending ${segment.content} ${type} SB, size:${segment.data.length}, ${segment.parent}`);
this.parent = segment.parent;
sb.appendBuffer(segment.data);
this.appendError = 0;
this.appended++;
this.appending = true;
} else {
segments.unshift(segment);
}
} else {
// in case we don't have any source buffer matching with this segment type,
// it means that Mediasource fails to create sourcebuffer
// discard this segment, and trigger update end
this.onSBUpdateEnd();
}
} catch (err) {
// in case any error occured while appending, put back segment in segments table
logger["b" /* logger */].error('error while trying to append buffer:' + err.message);
segments.unshift(segment);
var event = { type: errors["b" /* ErrorTypes */].MEDIA_ERROR, parent: segment.parent };
if (err.code !== 22) {
if (this.appendError) {
this.appendError++;
} else {
this.appendError = 1;
}
event.details = errors["a" /* ErrorDetails */].BUFFER_APPEND_ERROR;
/* with UHD content, we could get loop of quota exceeded error until
share/public_html/static/hls.js view on Meta::CPAN
// if no, let's flush all sourcebuffers
if (typeIn && type !== typeIn) {
continue;
}
sb = sourceBuffer[type];
// we are going to flush buffer, mark source buffer as 'not ended'
sb.ended = false;
if (!sb.updating) {
try {
for (i = 0; i < sb.buffered.length; i++) {
bufStart = sb.buffered.start(i);
bufEnd = sb.buffered.end(i);
// workaround firefox not able to properly flush multiple buffered range.
if (navigator.userAgent.toLowerCase().indexOf('firefox') !== -1 && endOffset === Number.POSITIVE_INFINITY) {
flushStart = startOffset;
flushEnd = endOffset;
} else {
flushStart = Math.max(bufStart, startOffset);
flushEnd = Math.min(bufEnd, endOffset);
}
/* sometimes sourcebuffer.remove() does not flush
the exact expected time range.
to avoid rounding issues/infinite loop,
only flush buffer range of length greater than 500ms.
*/
if (Math.min(flushEnd, bufEnd) - flushStart > 0.5) {
this.flushBufferCounter++;
logger["b" /* logger */].log('flush ' + type + ' [' + flushStart + ',' + flushEnd + '], of [' + bufStart + ',' + bufEnd + '], pos:' + this.media.currentTime);
sb.remove(flushStart, flushEnd);
return false;
}
}
} catch (e) {
logger["b" /* logger */].warn('exception while accessing sourcebuffer, it might have been removed from MediaSource');
}
} else {
// logger.log('abort ' + type + ' append in progress');
// this will abort any appending in progress
// sb.abort();
logger["b" /* logger */].warn('cannot flush, sb updating in progress');
return false;
}
}
} else {
logger["b" /* logger */].warn('abort flushing too many retries');
}
logger["b" /* logger */].log('buffer flushed');
}
// everything flushed !
return true;
};
return BufferController;
}(event_handler);
/* harmony default export */ var buffer_controller = (buffer_controller_BufferController);
// CONCATENATED MODULE: ./src/controller/cap-level-controller.js
var cap_level_controller__createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = tru...
function cap_level_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function cap_level_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? cal...
function cap_level_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype =...
/*
* cap stream level to media size dimension controller
*/
var cap_level_controller_CapLevelController = function (_EventHandler) {
cap_level_controller__inherits(CapLevelController, _EventHandler);
function CapLevelController(hls) {
cap_level_controller__classCallCheck(this, CapLevelController);
var _this = cap_level_controller__possibleConstructorReturn(this, _EventHandler.call(this, hls, events["a" /* default */].FPS_DROP_LEVEL_CAPPING, events["a" /* default */].MEDIA_ATTACHING, events["a" /* default */].MANIFEST_PARSED, events["a" /* ...
_this.autoLevelCapping = Number.POSITIVE_INFINITY;
_this.firstLevel = null;
_this.levels = [];
_this.media = null;
_this.restrictedLevels = [];
_this.timer = null;
return _this;
}
CapLevelController.prototype.destroy = function destroy() {
if (this.hls.config.capLevelToPlayerSize) {
this.media = null;
this._stopCapping();
}
};
CapLevelController.prototype.onFpsDropLevelCapping = function onFpsDropLevelCapping(data) {
// Don't add a restricted level more than once
if (CapLevelController.isLevelAllowed(data.droppedLevel, this.restrictedLevels)) {
this.restrictedLevels.push(data.droppedLevel);
}
};
CapLevelController.prototype.onMediaAttaching = function onMediaAttaching(data) {
this.media = data.media instanceof window.HTMLVideoElement ? data.media : null;
};
CapLevelController.prototype.onManifestParsed = function onManifestParsed(data) {
var hls = this.hls;
this.restrictedLevels = [];
this.levels = data.levels;
this.firstLevel = data.firstLevel;
if (hls.config.capLevelToPlayerSize && (data.video || data.levels.length && data.altAudio)) {
// Start capping immediately if the manifest has signaled video codecs
this._startCapping();
}
};
// Only activate capping when playing a video stream; otherwise, multi-bitrate audio-only streams will be restricted
// to the first level
CapLevelController.prototype.onBufferCodecs = function onBufferCodecs(data) {
var hls = this.hls;
share/public_html/static/hls.js view on Meta::CPAN
if (!nextLevel) {
return true;
}
return curLevel.width !== nextLevel.width || curLevel.height !== nextLevel.height;
};
// If we run through the loop without breaking, the media's dimensions are greater than every level, so default to
// the max level
var maxLevelIndex = levels.length - 1;
for (var i = 0; i < levels.length; i += 1) {
var level = levels[i];
if ((level.width >= width || level.height >= height) && atGreatestBandiwdth(level, levels[i + 1])) {
maxLevelIndex = i;
break;
}
}
return maxLevelIndex;
};
cap_level_controller__createClass(CapLevelController, [{
key: 'mediaWidth',
get: function get() {
var width = void 0;
var media = this.media;
if (media) {
width = media.width || media.clientWidth || media.offsetWidth;
width *= CapLevelController.contentScaleFactor;
}
return width;
}
}, {
key: 'mediaHeight',
get: function get() {
var height = void 0;
var media = this.media;
if (media) {
height = media.height || media.clientHeight || media.offsetHeight;
height *= CapLevelController.contentScaleFactor;
}
return height;
}
}], [{
key: 'contentScaleFactor',
get: function get() {
var pixelRatio = 1;
try {
pixelRatio = window.devicePixelRatio;
} catch (e) {}
return pixelRatio;
}
}]);
return CapLevelController;
}(event_handler);
/* harmony default export */ var cap_level_controller = (cap_level_controller_CapLevelController);
// CONCATENATED MODULE: ./src/controller/fps-controller.js
function fps_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function fps_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : se...
function fps_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Objec...
/*
* FPS Controller
*/
var fps_controller__window = window,
fps_controller_performance = fps_controller__window.performance;
var fps_controller_FPSController = function (_EventHandler) {
fps_controller__inherits(FPSController, _EventHandler);
function FPSController(hls) {
fps_controller__classCallCheck(this, FPSController);
return fps_controller__possibleConstructorReturn(this, _EventHandler.call(this, hls, events["a" /* default */].MEDIA_ATTACHING));
}
FPSController.prototype.destroy = function destroy() {
if (this.timer) {
clearInterval(this.timer);
}
this.isVideoPlaybackQualityAvailable = false;
};
FPSController.prototype.onMediaAttaching = function onMediaAttaching(data) {
var config = this.hls.config;
if (config.capLevelOnFPSDrop) {
var video = this.video = data.media instanceof window.HTMLVideoElement ? data.media : null;
if (typeof video.getVideoPlaybackQuality === 'function') {
this.isVideoPlaybackQualityAvailable = true;
}
clearInterval(this.timer);
this.timer = setInterval(this.checkFPSInterval.bind(this), config.fpsDroppedMonitoringPeriod);
}
};
FPSController.prototype.checkFPS = function checkFPS(video, decodedFrames, droppedFrames) {
var currentTime = fps_controller_performance.now();
if (decodedFrames) {
if (this.lastTime) {
var currentPeriod = currentTime - this.lastTime,
currentDropped = droppedFrames - this.lastDroppedFrames,
currentDecoded = decodedFrames - this.lastDecodedFrames,
droppedFPS = 1000 * currentDropped / currentPeriod,
hls = this.hls;
hls.trigger(events["a" /* default */].FPS_DROP, { currentDropped: currentDropped, currentDecoded: currentDecoded, totalDroppedFrames: droppedFrames });
if (droppedFPS > 0) {
// logger.log('checkFPS : droppedFPS/decodedFPS:' + droppedFPS/(1000 * currentDecoded / currentPeriod));
if (currentDropped > hls.config.fpsDroppedMonitoringThreshold * currentDecoded) {
var currentLevel = hls.currentLevel;
logger["b" /* logger */].warn('drop FPS ratio greater than max allowed value for currentLevel: ' + currentLevel);
if (currentLevel > 0 && (hls.autoLevelCapping === -1 || hls.autoLevelCapping >= currentLevel)) {
currentLevel = currentLevel - 1;
hls.trigger(events["a" /* default */].FPS_DROP_LEVEL_CAPPING, { level: currentLevel, droppedLevel: hls.currentLevel });
hls.autoLevelCapping = currentLevel;
hls.streamController.nextLevelSwitch();
}
}
}
}
this.lastTime = currentTime;
this.lastDroppedFrames = droppedFrames;
this.lastDecodedFrames = decodedFrames;
}
};
FPSController.prototype.checkFPSInterval = function checkFPSInterval() {
var video = this.video;
if (video) {
if (this.isVideoPlaybackQualityAvailable) {
var videoPlaybackQuality = video.getVideoPlaybackQuality();
this.checkFPS(video, videoPlaybackQuality.totalVideoFrames, videoPlaybackQuality.droppedVideoFrames);
} else {
this.checkFPS(video, video.webkitDecodedFrameCount, video.webkitDroppedFrameCount);
}
}
};
return FPSController;
}(event_handler);
/* harmony default export */ var fps_controller = (fps_controller_FPSController);
// CONCATENATED MODULE: ./src/utils/xhr-loader.js
function xhr_loader__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* XHR based logger
*/
var xhr_loader__window = window,
xhr_loader_performance = xhr_loader__window.performance,
XMLHttpRequest = xhr_loader__window.XMLHttpRequest;
var xhr_loader_XhrLoader = function () {
function XhrLoader(config) {
xhr_loader__classCallCheck(this, XhrLoader);
if (config && config.xhrSetup) {
this.xhrSetup = config.xhrSetup;
}
}
XhrLoader.prototype.destroy = function destroy() {
this.abort();
this.loader = null;
};
XhrLoader.prototype.abort = function abort() {
var loader = this.loader;
if (loader && loader.readyState !== 4) {
this.stats.aborted = true;
loader.abort();
}
window.clearTimeout(this.requestTimeout);
this.requestTimeout = null;
window.clearTimeout(this.retryTimeout);
this.retryTimeout = null;
};
XhrLoader.prototype.load = function load(context, config, callbacks) {
this.context = context;
this.config = config;
this.callbacks = callbacks;
this.stats = { trequest: xhr_loader_performance.now(), retry: 0 };
this.retryDelay = config.retryDelay;
this.loadInternal();
};
XhrLoader.prototype.loadInternal = function loadInternal() {
var xhr = void 0,
context = this.context;
xhr = this.loader = new XMLHttpRequest();
var stats = this.stats;
stats.tfirst = 0;
stats.loaded = 0;
var xhrSetup = this.xhrSetup;
try {
if (xhrSetup) {
try {
xhrSetup(xhr, context.url);
} catch (e) {
// fix xhrSetup: (xhr, url) => {xhr.setRequestHeader("Content-Language", "test");}
// not working, as xhr.setRequestHeader expects xhr.readyState === OPEN
xhr.open('GET', context.url, true);
xhrSetup(xhr, context.url);
}
}
if (!xhr.readyState) {
xhr.open('GET', context.url, true);
}
} catch (e) {
// IE11 throws an exception on xhr.open if attempting to access an HTTP resource over HTTPS
this.callbacks.onError({ code: xhr.status, text: e.message }, context, xhr);
return;
}
if (context.rangeEnd) {
xhr.setRequestHeader('Range', 'bytes=' + context.rangeStart + '-' + (context.rangeEnd - 1));
}
xhr.onreadystatechange = this.readystatechange.bind(this);
xhr.onprogress = this.loadprogress.bind(this);
xhr.responseType = context.responseType;
// setup timeout before we perform request
this.requestTimeout = window.setTimeout(this.loadtimeout.bind(this), this.config.timeout);
xhr.send();
};
XhrLoader.prototype.readystatechange = function readystatechange(event) {
var xhr = event.currentTarget,
readyState = xhr.readyState,
stats = this.stats,
context = this.context,
config = this.config;
// don't proceed if xhr has been aborted
if (stats.aborted) {
return;
}
// >= HEADERS_RECEIVED
if (readyState >= 2) {
// clear xhr timeout and rearm it if readyState less than 4
window.clearTimeout(this.requestTimeout);
if (stats.tfirst === 0) {
stats.tfirst = Math.max(xhr_loader_performance.now(), stats.trequest);
}
if (readyState === 4) {
var status = xhr.status;
// http status between 200 to 299 are all successful
if (status >= 200 && status < 300) {
stats.tload = Math.max(stats.tfirst, xhr_loader_performance.now());
var data = void 0,
len = void 0;
if (context.responseType === 'arraybuffer') {
data = xhr.response;
len = data.byteLength;
} else {
data = xhr.responseText;
len = data.length;
}
stats.loaded = stats.total = len;
var response = { url: xhr.responseURL, data: data };
this.callbacks.onSuccess(response, stats, context, xhr);
} else {
// if max nb of retries reached or if http status between 400 and 499 (such error cannot be recovered, retrying is useless), return error
if (stats.retry >= config.maxRetry || status >= 400 && status < 499) {
logger["b" /* logger */].error(status + ' while loading ' + context.url);
this.callbacks.onError({ code: status, text: xhr.statusText }, context, xhr);
} else {
// retry
logger["b" /* logger */].warn(status + ' while loading ' + context.url + ', retrying in ' + this.retryDelay + '...');
// aborts and resets internal state
this.destroy();
// schedule retry
this.retryTimeout = window.setTimeout(this.loadInternal.bind(this), this.retryDelay);
// set exponential backoff
this.retryDelay = Math.min(2 * this.retryDelay, config.maxRetryDelay);
stats.retry++;
}
}
} else {
// readyState >= 2 AND readyState !==4 (readyState = HEADERS_RECEIVED || LOADING) rearm timeout as xhr not finished yet
this.requestTimeout = window.setTimeout(this.loadtimeout.bind(this), config.timeout);
}
}
};
XhrLoader.prototype.loadtimeout = function loadtimeout() {
logger["b" /* logger */].warn('timeout while loading ' + this.context.url);
this.callbacks.onTimeout(this.stats, this.context, null);
};
XhrLoader.prototype.loadprogress = function loadprogress(event) {
var xhr = event.currentTarget,
stats = this.stats;
stats.loaded = event.loaded;
if (event.lengthComputable) {
stats.total = event.total;
}
var onProgress = this.callbacks.onProgress;
if (onProgress) {
// third arg is to provide on progress data
onProgress(stats, this.context, null, xhr);
}
};
return XhrLoader;
}();
/* harmony default export */ var xhr_loader = (xhr_loader_XhrLoader);
// CONCATENATED MODULE: ./src/controller/audio-track-controller.js
var audio_track_controller__createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = t...
function audio_track_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function audio_track_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? c...
function audio_track_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype...
/**
* @class AudioTrackController
* @implements {EventHandler}
*
* Handles main manifest and audio-track metadata loaded,
* owns and exposes the selectable audio-tracks data-models.
*
* Exposes internal interface to select available audio-tracks.
*
* Handles errors on loading audio-track playlists. Manages fallback mechanism
* with redundants tracks (group-IDs).
*
* Handles level-loading and group-ID switches for video (fallback on video levels),
* and eventually adapts the audio-track group-ID to match.
*
* @fires AUDIO_TRACK_LOADING
* @fires AUDIO_TRACK_SWITCHING
* @fires AUDIO_TRACKS_UPDATED
* @fires ERROR
*
*/
var audio_track_controller_AudioTrackController = function (_TaskLoop) {
audio_track_controller__inherits(AudioTrackController, _TaskLoop);
function AudioTrackController(hls) {
audio_track_controller__classCallCheck(this, AudioTrackController);
/**
* @private
* Currently selected index in `tracks`
* @member {number} trackId
*/
var _this = audio_track_controller__possibleConstructorReturn(this, _TaskLoop.call(this, hls, events["a" /* default */].MANIFEST_LOADING, events["a" /* default */].MANIFEST_PARSED, events["a" /* default */].AUDIO_TRACK_LOADED, events["a" /* defau...
_this.trackId = -1;
/**
* @public
* All tracks available
* @member {AudioTrack[]}
*/
_this.tracks = [];
/**
* @public
* List of blacklisted audio track IDs (that have caused failure)
* @member {number[]}
*/
_this.trackIdBlacklist = Object.create(null);
/**
* @public
* The currently running group ID for audio
share/public_html/static/hls.js view on Meta::CPAN
this.audioTrack = newId;
};
audio_track_controller__createClass(AudioTrackController, [{
key: 'audioTracks',
get: function get() {
return this.tracks;
}
/**
* @type {number} Index into audio-tracks list of currently selected track.
*/
}, {
key: 'audioTrack',
get: function get() {
return this.trackId;
}
/**
* Select current track by index
*/
,
set: function set(newId) {
// noop on same audio track id as already set
if (this.trackId === newId && this.tracks[this.trackId].details) {
logger["b" /* logger */].debug('Same id as current audio-track passed, and track details available -> no-op');
return;
}
// check if level idx is valid
if (newId < 0 || newId >= this.tracks.length) {
logger["b" /* logger */].warn('Invalid id passed to audio-track controller');
return;
}
var audioTrack = this.tracks[newId];
logger["b" /* logger */].log('Now switching to audio-track index ' + newId);
// stopping live reloading timer if any
this.clearInterval();
this.trackId = newId;
var url = audioTrack.url,
type = audioTrack.type,
id = audioTrack.id;
this.hls.trigger(events["a" /* default */].AUDIO_TRACK_SWITCHING, { id: id, type: type, url: url });
this._loadTrackDetailsIfNeeded(audioTrack);
}
}]);
return AudioTrackController;
}(task_loop);
/* harmony default export */ var audio_track_controller = (audio_track_controller_AudioTrackController);
// CONCATENATED MODULE: ./src/controller/audio-stream-controller.js
var audio_stream_controller__createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = ...
function audio_stream_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function audio_stream_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? ...
function audio_stream_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototyp...
/*
* Audio Stream Controller
*/
var audio_stream_controller__window = window,
audio_stream_controller_performance = audio_stream_controller__window.performance;
var audio_stream_controller_State = {
STOPPED: 'STOPPED',
STARTING: 'STARTING',
IDLE: 'IDLE',
PAUSED: 'PAUSED',
KEY_LOADING: 'KEY_LOADING',
FRAG_LOADING: 'FRAG_LOADING',
FRAG_LOADING_WAITING_RETRY: 'FRAG_LOADING_WAITING_RETRY',
WAITING_TRACK: 'WAITING_TRACK',
PARSING: 'PARSING',
PARSED: 'PARSED',
BUFFER_FLUSHING: 'BUFFER_FLUSHING',
ENDED: 'ENDED',
ERROR: 'ERROR',
WAITING_INIT_PTS: 'WAITING_INIT_PTS'
};
var audio_stream_controller_AudioStreamController = function (_TaskLoop) {
audio_stream_controller__inherits(AudioStreamController, _TaskLoop);
function AudioStreamController(hls, fragmentTracker) {
audio_stream_controller__classCallCheck(this, AudioStreamController);
var _this = audio_stream_controller__possibleConstructorReturn(this, _TaskLoop.call(this, hls, events["a" /* default */].MEDIA_ATTACHED, events["a" /* default */].MEDIA_DETACHING, events["a" /* default */].AUDIO_TRACKS_UPDATED, events["a" /* defa...
_this.fragmentTracker = fragmentTracker;
_this.config = hls.config;
_this.audioCodecSwap = false;
_this._state = audio_stream_controller_State.STOPPED;
_this.initPTS = [];
_this.waitingFragment = null;
_this.videoTrackCC = null;
return _this;
}
AudioStreamController.prototype.onHandlerDestroying = function onHandlerDestroying() {
this.stopLoad();
_TaskLoop.prototype.onHandlerDestroying.call(this);
share/public_html/static/hls.js view on Meta::CPAN
if (isIE8) {
cue = document.createElement('custom');
} else {
baseObj.enumerable = true;
}
/**
* Shim implementation specific properties. These properties are not in
* the spec.
*/
// Lets us know when the VTTCue's data has changed in such a way that we need
// to recompute its display state. This lets us compute its display state
// lazily.
cue.hasBeenReset = false;
/**
* VTTCue and TextTrackCue properties
* http://dev.w3.org/html5/webvtt/#vttcue-interface
*/
var _id = '';
var _pauseOnExit = false;
var _startTime = startTime;
var _endTime = endTime;
var _text = text;
var _region = null;
var _vertical = '';
var _snapToLines = true;
var _line = 'auto';
var _lineAlign = 'start';
var _position = 50;
var _positionAlign = 'middle';
var _size = 50;
var _align = 'middle';
Object.defineProperty(cue, 'id', extend({}, baseObj, {
get: function get() {
return _id;
},
set: function set(value) {
_id = '' + value;
}
}));
Object.defineProperty(cue, 'pauseOnExit', extend({}, baseObj, {
get: function get() {
return _pauseOnExit;
},
set: function set(value) {
_pauseOnExit = !!value;
}
}));
Object.defineProperty(cue, 'startTime', extend({}, baseObj, {
get: function get() {
return _startTime;
},
set: function set(value) {
if (typeof value !== 'number') {
throw new TypeError('Start time must be set to a number.');
}
_startTime = value;
this.hasBeenReset = true;
}
}));
Object.defineProperty(cue, 'endTime', extend({}, baseObj, {
get: function get() {
return _endTime;
},
set: function set(value) {
if (typeof value !== 'number') {
throw new TypeError('End time must be set to a number.');
}
_endTime = value;
this.hasBeenReset = true;
}
}));
Object.defineProperty(cue, 'text', extend({}, baseObj, {
get: function get() {
return _text;
},
set: function set(value) {
_text = '' + value;
this.hasBeenReset = true;
}
}));
Object.defineProperty(cue, 'region', extend({}, baseObj, {
get: function get() {
return _region;
},
set: function set(value) {
_region = value;
this.hasBeenReset = true;
}
}));
Object.defineProperty(cue, 'vertical', extend({}, baseObj, {
get: function get() {
return _vertical;
},
set: function set(value) {
var setting = findDirectionSetting(value);
// Have to check for false because the setting an be an empty string.
if (setting === false) {
throw new SyntaxError('An invalid or illegal string was specified.');
}
_vertical = setting;
this.hasBeenReset = true;
}
}));
Object.defineProperty(cue, 'snapToLines', extend({}, baseObj, {
get: function get() {
return _snapToLines;
},
set: function set(value) {
_snapToLines = !!value;
this.hasBeenReset = true;
}
}));
Object.defineProperty(cue, 'line', extend({}, baseObj, {
get: function get() {
return _line;
},
set: function set(value) {
if (typeof value !== 'number' && value !== autoKeyword) {
throw new SyntaxError('An invalid number or illegal string was specified.');
}
_line = value;
this.hasBeenReset = true;
}
}));
Object.defineProperty(cue, 'lineAlign', extend({}, baseObj, {
get: function get() {
return _lineAlign;
},
set: function set(value) {
var setting = findAlignSetting(value);
if (!setting) {
throw new SyntaxError('An invalid or illegal string was specified.');
}
_lineAlign = setting;
this.hasBeenReset = true;
}
}));
Object.defineProperty(cue, 'position', extend({}, baseObj, {
get: function get() {
return _position;
},
set: function set(value) {
if (value < 0 || value > 100) {
throw new Error('Position must be between 0 and 100.');
}
_position = value;
this.hasBeenReset = true;
}
}));
Object.defineProperty(cue, 'positionAlign', extend({}, baseObj, {
get: function get() {
return _positionAlign;
},
set: function set(value) {
var setting = findAlignSetting(value);
if (!setting) {
throw new SyntaxError('An invalid or illegal string was specified.');
}
_positionAlign = setting;
this.hasBeenReset = true;
}
}));
Object.defineProperty(cue, 'size', extend({}, baseObj, {
get: function get() {
return _size;
},
set: function set(value) {
if (value < 0 || value > 100) {
throw new Error('Size must be between 0 and 100.');
}
_size = value;
this.hasBeenReset = true;
}
}));
Object.defineProperty(cue, 'align', extend({}, baseObj, {
get: function get() {
return _align;
},
set: function set(value) {
var setting = findAlignSetting(value);
if (!setting) {
throw new SyntaxError('An invalid or illegal string was specified.');
}
_align = setting;
this.hasBeenReset = true;
}
}));
/**
* Other <track> spec defined properties
*/
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#text-track-cue-display-state
cue.displayState = undefined;
if (isIE8) {
return cue;
}
}
/**
* VTTCue methods
*/
VTTCue.prototype.getCueAsHTML = function () {
// Assume WebVTT.convertCueToDOMTree is on the global.
var WebVTT = window.WebVTT;
return WebVTT.convertCueToDOMTree(window, this.text);
};
return VTTCue;
})());
// CONCATENATED MODULE: ./src/utils/vttparser.js
/*
* Source: https://github.com/mozilla/vtt.js/blob/master/dist/vtt.js#L1716
*/
var StringDecoder = function StringDecoder() {
return {
decode: function decode(data) {
if (!data) {
return '';
}
if (typeof data !== 'string') {
throw new Error('Error - expected string data.');
}
return decodeURIComponent(encodeURIComponent(data));
}
};
};
function VTTParser() {
this.window = window;
this.state = 'INITIAL';
this.buffer = '';
this.decoder = new StringDecoder();
this.regionList = [];
}
// Try to parse input as a time stamp.
function parseTimeStamp(input) {
function computeSeconds(h, m, s, f) {
return (h | 0) * 3600 + (m | 0) * 60 + (s | 0) + (f | 0) / 1000;
}
var m = input.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/);
if (!m) {
return null;
}
if (m[3]) {
// Timestamp takes the form of [hours]:[minutes]:[seconds].[milliseconds]
return computeSeconds(m[1], m[2], m[3].replace(':', ''), m[4]);
} else if (m[1] > 59) {
// Timestamp takes the form of [hours]:[minutes].[milliseconds]
// First position is hours as it's over 59.
return computeSeconds(m[1], m[2], 0, m[4]);
} else {
// Timestamp takes the form of [minutes]:[seconds].[milliseconds]
return computeSeconds(0, m[1], m[2], m[4]);
}
}
// A settings object holds key/value pairs and will ignore anything but the first
// assignment to a specific key.
function Settings() {
this.values = Object.create(null);
}
Settings.prototype = {
// Only accept the first assignment to any key.
set: function set(k, v) {
if (!this.get(k) && v !== '') {
this.values[k] = v;
}
},
// Return the value for a key, or a default value.
// If 'defaultKey' is passed then 'dflt' is assumed to be an object with
// a number of possible default values as properties where 'defaultKey' is
// the key of the property that will be chosen; otherwise it's assumed to be
// a single value.
get: function get(k, dflt, defaultKey) {
if (defaultKey) {
return this.has(k) ? this.values[k] : dflt[defaultKey];
share/public_html/static/hls.js view on Meta::CPAN
// Check whether we have a value for a key.
has: function has(k) {
return k in this.values;
},
// Accept a setting if its one of the given alternatives.
alt: function alt(k, v, a) {
for (var n = 0; n < a.length; ++n) {
if (v === a[n]) {
this.set(k, v);
break;
}
}
},
// Accept a setting if its a valid (signed) integer.
integer: function integer(k, v) {
if (/^-?\d+$/.test(v)) {
// integer
this.set(k, parseInt(v, 10));
}
},
// Accept a setting if its a valid percentage.
percent: function percent(k, v) {
var m = void 0;
if (m = v.match(/^([\d]{1,3})(\.[\d]*)?%$/)) {
v = parseFloat(v);
if (v >= 0 && v <= 100) {
this.set(k, v);
return true;
}
}
return false;
}
};
// Helper function to parse input into groups separated by 'groupDelim', and
// interprete each group as a key/value pair separated by 'keyValueDelim'.
function parseOptions(input, callback, keyValueDelim, groupDelim) {
var groups = groupDelim ? input.split(groupDelim) : [input];
for (var i in groups) {
if (typeof groups[i] !== 'string') {
continue;
}
var kv = groups[i].split(keyValueDelim);
if (kv.length !== 2) {
continue;
}
var k = kv[0];
var v = kv[1];
callback(k, v);
}
}
var defaults = new vttcue(0, 0, 0);
// 'middle' was changed to 'center' in the spec: https://github.com/w3c/webvtt/pull/244
// Safari doesn't yet support this change, but FF and Chrome do.
var center = defaults.align === 'middle' ? 'middle' : 'center';
function parseCue(input, cue, regionList) {
// Remember the original input if we need to throw an error.
var oInput = input;
// 4.1 WebVTT timestamp
function consumeTimeStamp() {
var ts = parseTimeStamp(input);
if (ts === null) {
throw new Error('Malformed timestamp: ' + oInput);
}
// Remove time stamp from input.
input = input.replace(/^[^\sa-zA-Z-]+/, '');
return ts;
}
// 4.4.2 WebVTT cue settings
function consumeCueSettings(input, cue) {
var settings = new Settings();
parseOptions(input, function (k, v) {
switch (k) {
case 'region':
// Find the last region we parsed with the same region id.
for (var i = regionList.length - 1; i >= 0; i--) {
if (regionList[i].id === v) {
settings.set(k, regionList[i].region);
break;
}
}
break;
case 'vertical':
settings.alt(k, v, ['rl', 'lr']);
break;
case 'line':
var vals = v.split(','),
vals0 = vals[0];
settings.integer(k, vals0);
if (settings.percent(k, vals0)) {
settings.set('snapToLines', false);
}
settings.alt(k, vals0, ['auto']);
if (vals.length === 2) {
settings.alt('lineAlign', vals[1], ['start', center, 'end']);
}
break;
case 'position':
vals = v.split(',');
settings.percent(k, vals[0]);
if (vals.length === 2) {
settings.alt('positionAlign', vals[1], ['start', center, 'end', 'line-left', 'line-right', 'auto']);
}
break;
case 'size':
settings.percent(k, v);
break;
case 'align':
settings.alt(k, v, ['start', center, 'end', 'left', 'right']);
break;
}
}, /:/, /\s/);
// Apply default values for any missing fields.
cue.region = settings.get('region', null);
cue.vertical = settings.get('vertical', '');
var line = settings.get('line', 'auto');
if (line === 'auto' && defaults.line === -1) {
// set numeric line number for Safari
line = -1;
}
cue.line = line;
cue.lineAlign = settings.get('lineAlign', 'start');
cue.snapToLines = settings.get('snapToLines', true);
cue.size = settings.get('size', 100);
cue.align = settings.get('align', center);
var position = settings.get('position', 'auto');
if (position === 'auto' && defaults.position === 50) {
// set numeric position for Safari
position = cue.align === 'start' || cue.align === 'left' ? 0 : cue.align === 'end' || cue.align === 'right' ? 100 : 50;
}
cue.position = position;
}
function skipWhitespace() {
input = input.replace(/^\s+/, '');
}
// 4.1 WebVTT cue timings.
skipWhitespace();
cue.startTime = consumeTimeStamp(); // (1) collect cue start time
skipWhitespace();
if (input.substr(0, 3) !== '-->') {
// (3) next characters must match '-->'
throw new Error('Malformed time stamp (time stamps must be separated by \'-->\'): ' + oInput);
}
input = input.substr(3);
skipWhitespace();
cue.endTime = consumeTimeStamp(); // (5) collect cue end time
// 4.1 WebVTT cue settings list.
skipWhitespace();
consumeCueSettings(input, cue);
}
function fixLineBreaks(input) {
return input.replace(/<br(?: \/)?>/gi, '\n');
}
VTTParser.prototype = {
parse: function parse(data) {
var self = this;
// If there is no data then we won't decode it, but will just try to parse
// whatever is in buffer already. This may occur in circumstances, for
// example when flush() is called.
if (data) {
// Try to decode the data that we received.
self.buffer += self.decoder.decode(data, { stream: true });
}
function collectNextLine() {
var buffer = self.buffer;
var pos = 0;
buffer = fixLineBreaks(buffer);
while (pos < buffer.length && buffer[pos] !== '\r' && buffer[pos] !== '\n') {
++pos;
}
var line = buffer.substr(0, pos);
// Advance the buffer early in case we fail below.
if (buffer[pos] === '\r') {
++pos;
}
if (buffer[pos] === '\n') {
++pos;
}
self.buffer = buffer.substr(pos);
return line;
}
// 3.2 WebVTT metadata header syntax
function parseHeader(input) {
parseOptions(input, function (k, v) {
switch (k) {
case 'Region':
// 3.3 WebVTT region metadata header syntax
// console.log('parse region', v);
// parseRegion(v);
break;
}
}, /:/);
}
// 5.1 WebVTT file parsing.
try {
var line = void 0;
if (self.state === 'INITIAL') {
// We can't start parsing until we have the first line.
if (!/\r\n|\n/.test(self.buffer)) {
return this;
}
line = collectNextLine();
// strip of UTF-8 BOM if any
// https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8
var m = line.match(/^()?WEBVTT([ \t].*)?$/);
if (!m || !m[0]) {
throw new Error('Malformed WebVTT signature.');
}
self.state = 'HEADER';
}
var alreadyCollectedLine = false;
while (self.buffer) {
// We can't parse a line until we have the full line.
if (!/\r\n|\n/.test(self.buffer)) {
return this;
}
if (!alreadyCollectedLine) {
line = collectNextLine();
} else {
alreadyCollectedLine = false;
}
switch (self.state) {
case 'HEADER':
// 13-18 - Allow a header (metadata) under the WEBVTT line.
if (/:/.test(line)) {
parseHeader(line);
} else if (!line) {
// An empty line terminates the header and starts the body (cues).
self.state = 'ID';
}
continue;
case 'NOTE':
// Ignore NOTE blocks.
if (!line) {
self.state = 'ID';
}
continue;
case 'ID':
// Check for the start of NOTE blocks.
if (/^NOTE($|[ \t])/.test(line)) {
self.state = 'NOTE';
break;
}
// 19-29 - Allow any number of line terminators, then initialize new cue values.
if (!line) {
continue;
}
self.cue = new vttcue(0, 0, '');
self.state = 'CUE';
// 30-39 - Check if self line contains an optional identifier or timing data.
if (line.indexOf('-->') === -1) {
self.cue.id = line;
continue;
}
// Process line as start of a cue.
/* falls through */
case 'CUE':
// 40 - Collect cue timings and settings.
try {
parseCue(line, self.cue, self.regionList);
} catch (e) {
share/public_html/static/hls.js view on Meta::CPAN
continue;
case 'CUETEXT':
var hasSubstring = line.indexOf('-->') !== -1;
// 34 - If we have an empty line then report the cue.
// 35 - If we have the special substring '-->' then report the cue,
// but do not collect the line as we need to process the current
// one as a new cue.
if (!line || hasSubstring && (alreadyCollectedLine = true)) {
// We are done parsing self cue.
if (self.oncue) {
self.oncue(self.cue);
}
self.cue = null;
self.state = 'ID';
continue;
}
if (self.cue.text) {
self.cue.text += '\n';
}
self.cue.text += line;
continue;
case 'BADCUE':
// BADCUE
// 54-62 - Collect and discard the remaining cue.
if (!line) {
self.state = 'ID';
}
continue;
}
}
} catch (e) {
// If we are currently parsing a cue, report what we have.
if (self.state === 'CUETEXT' && self.cue && self.oncue) {
self.oncue(self.cue);
}
self.cue = null;
// Enter BADWEBVTT state if header was not parsed correctly otherwise
// another exception occurred so enter BADCUE state.
self.state = self.state === 'INITIAL' ? 'BADWEBVTT' : 'BADCUE';
}
return this;
},
flush: function flush() {
var self = this;
try {
// Finish decoding the stream.
self.buffer += self.decoder.decode();
// Synthesize the end of the current cue or region.
if (self.cue || self.state === 'HEADER') {
self.buffer += '\n\n';
self.parse();
}
// If we've flushed, parsed, and we're still on the INITIAL state then
// that means we don't have enough of the stream to parse the first
// line.
if (self.state === 'INITIAL') {
throw new Error('Malformed WebVTT signature.');
}
} catch (e) {
throw e;
}
if (self.onflush) {
self.onflush();
}
return this;
}
};
/* harmony default export */ var vttparser = (VTTParser);
// CONCATENATED MODULE: ./src/utils/cues.js
function newCue(track, startTime, endTime, captionScreen) {
var row = void 0;
var cue = void 0;
var indenting = void 0;
var indent = void 0;
var text = void 0;
var VTTCue = window.VTTCue || window.TextTrackCue;
for (var r = 0; r < captionScreen.rows.length; r++) {
row = captionScreen.rows[r];
indenting = true;
indent = 0;
text = '';
if (!row.isEmpty()) {
for (var c = 0; c < row.chars.length; c++) {
if (row.chars[c].uchar.match(/\s/) && indenting) {
indent++;
} else {
text += row.chars[c].uchar;
indenting = false;
}
}
// To be used for cleaning-up orphaned roll-up captions
row.cueStartTime = startTime;
// Give a slight bump to the endTime if it's equal to startTime to avoid a SyntaxError in IE
if (startTime === endTime) {
endTime += 0.0001;
}
cue = new VTTCue(startTime, endTime, fixLineBreaks(text.trim()));
if (indent >= 16) {
indent--;
} else {
indent++;
}
// VTTCue.line get's flakey when using controls, so let's now include line 13&14
// also, drop line 1 since it's to close to the top
if (navigator.userAgent.match(/Firefox\//)) {
cue.line = r + 1;
} else {
cue.line = r > 7 ? r - 2 : r + 1;
}
cue.align = 'left';
// Clamp the position between 0 and 100 - if out of these bounds, Firefox throws an exception and captions break
cue.position = Math.max(0, Math.min(100, 100 * (indent / 32) + (navigator.userAgent.match(/Firefox\//) ? 50 : 0)));
track.addCue(cue);
}
}
}
// CONCATENATED MODULE: ./src/utils/cea-608-parser.js
function cea_608_parser__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
*
* This code was ported from the dash.js project at:
* https://github.com/Dash-Industry-Forum/dash.js/blob/development/externals/cea608-parser.js
* https://github.com/Dash-Industry-Forum/dash.js/commit/8269b26a761e0853bb21d78780ed945144ecdd4d#diff-71bc295a2d6b6b7093a1d3290d53a4b2
*
* The original copyright appears below:
*
* The copyright in this software is being made available under the BSD License,
* included below. This software may be subject to other third party and contributor
* rights, including patent rights, and no such rights are granted under this license.
*
* Copyright (c) 2015-2016, DASH Industry Forum.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* 2. Neither the name of Dash Industry Forum nor the names of its
* contributors may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Exceptions from regular ASCII. CodePoints are mapped to UTF-16 codes
*/
var specialCea608CharsCodes = {
0x2a: 0xe1, // lowercase a, acute accent
0x5c: 0xe9, // lowercase e, acute accent
0x5e: 0xed, // lowercase i, acute accent
0x5f: 0xf3, // lowercase o, acute accent
0x60: 0xfa, // lowercase u, acute accent
0x7b: 0xe7, // lowercase c with cedilla
0x7c: 0xf7, // division symbol
0x7d: 0xd1, // uppercase N tilde
0x7e: 0xf1, // lowercase n tilde
0x7f: 0x2588, // Full block
// THIS BLOCK INCLUDES THE 16 EXTENDED (TWO-BYTE) LINE 21 CHARACTERS
// THAT COME FROM HI BYTE=0x11 AND LOW BETWEEN 0x30 AND 0x3F
// THIS MEANS THAT \x50 MUST BE ADDED TO THE VALUES
0x80: 0xae, // Registered symbol (R)
0x81: 0xb0, // degree sign
0x82: 0xbd, // 1/2 symbol
0x83: 0xbf, // Inverted (open) question mark
share/public_html/static/hls.js view on Meta::CPAN
if (!(case1 || case2)) {
return false;
}
bkgData = {};
if (a === 0x10 || a === 0x18) {
index = Math.floor((b - 0x20) / 2);
bkgData.background = backgroundColors[index];
if (b % 2 === 1) {
bkgData.background = bkgData.background + '_semi';
}
} else if (b === 0x2d) {
bkgData.background = 'transparent';
} else {
bkgData.foreground = 'black';
if (b === 0x2f) {
bkgData.underline = true;
}
}
chNr = a < 0x18 ? 1 : 2;
channel = this.channels[chNr - 1];
channel.setBkgData(bkgData);
this.lastCmdA = null;
this.lastCmdB = null;
return true;
};
/**
* Reset state of parser and its channels.
*/
Cea608Parser.prototype.reset = function reset() {
for (var i = 0; i < this.channels.length; i++) {
if (this.channels[i]) {
this.channels[i].reset();
}
}
this.lastCmdA = null;
this.lastCmdB = null;
};
/**
* Trigger the generation of a cue, and the start of a new one if displayScreens are not empty.
*/
Cea608Parser.prototype.cueSplitAtTime = function cueSplitAtTime(t) {
for (var i = 0; i < this.channels.length; i++) {
if (this.channels[i]) {
this.channels[i].cueSplitAtTime(t);
}
}
};
return Cea608Parser;
}();
/* harmony default export */ var cea_608_parser = (Cea608Parser);
// CONCATENATED MODULE: ./src/utils/output-filter.js
function output_filter__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var OutputFilter = function () {
function OutputFilter(timelineController, trackName) {
output_filter__classCallCheck(this, OutputFilter);
this.timelineController = timelineController;
this.trackName = trackName;
this.startTime = null;
this.endTime = null;
this.screen = null;
}
OutputFilter.prototype.dispatchCue = function dispatchCue() {
if (this.startTime === null) {
return;
}
this.timelineController.addCues(this.trackName, this.startTime, this.endTime, this.screen);
this.startTime = null;
};
OutputFilter.prototype.newCue = function newCue(startTime, endTime, screen) {
if (this.startTime === null || this.startTime > startTime) {
this.startTime = startTime;
}
this.endTime = endTime;
this.screen = screen;
this.timelineController.createCaptionsTrack(this.trackName);
};
return OutputFilter;
}();
/* harmony default export */ var output_filter = (OutputFilter);
// CONCATENATED MODULE: ./src/utils/webvtt-parser.js
// String.prototype.startsWith is not supported in IE11
var startsWith = function startsWith(inputString, searchString, position) {
return inputString.substr(position || 0, searchString.length) === searchString;
};
var cueString2millis = function cueString2millis(timeString) {
var ts = parseInt(timeString.substr(-3));
var secs = parseInt(timeString.substr(-6, 2));
var mins = parseInt(timeString.substr(-9, 2));
var hours = timeString.length > 9 ? parseInt(timeString.substr(0, timeString.indexOf(':'))) : 0;
if (isNaN(ts) || isNaN(secs) || isNaN(mins) || isNaN(hours)) {
return -1;
}
ts += 1000 * secs;
ts += 60 * 1000 * mins;
ts += 60 * 60 * 1000 * hours;
return ts;
};
share/public_html/static/hls.js view on Meta::CPAN
parser.onparsingerror = function (e) {
parsingError = e;
};
parser.onflush = function () {
if (parsingError && errorCallBack) {
errorCallBack(parsingError);
return;
}
callBack(cues);
};
// Go through contents line by line.
vttLines.forEach(function (line) {
if (inHeader) {
// Look for X-TIMESTAMP-MAP in header.
if (startsWith(line, 'X-TIMESTAMP-MAP=')) {
// Once found, no more are allowed anyway, so stop searching.
inHeader = false;
// Extract LOCAL and MPEGTS.
line.substr(16).split(',').forEach(function (timestamp) {
if (startsWith(timestamp, 'LOCAL:')) {
cueTime = timestamp.substr(6);
} else if (startsWith(timestamp, 'MPEGTS:')) {
mpegTs = parseInt(timestamp.substr(7));
}
});
try {
// Calculate subtitle offset in milliseconds.
// If sync PTS is less than zero, we have a 33-bit wraparound, which is fixed by adding 2^33 = 8589934592.
syncPTS = syncPTS < 0 ? syncPTS + 8589934592 : syncPTS;
// Adjust MPEGTS by sync PTS.
mpegTs -= syncPTS;
// Convert cue time to seconds
localTime = cueString2millis(cueTime) / 1000;
// Convert MPEGTS to seconds from 90kHz.
presentationTime = mpegTs / 90000;
if (localTime === -1) {
parsingError = new Error('Malformed X-TIMESTAMP-MAP: ' + line);
}
} catch (e) {
parsingError = new Error('Malformed X-TIMESTAMP-MAP: ' + line);
}
// Return without parsing X-TIMESTAMP-MAP line.
return;
} else if (line === '') {
inHeader = false;
}
}
// Parse line by default.
parser.parse(line + '\n');
});
parser.flush();
}
};
/* harmony default export */ var webvtt_parser = (WebVTTParser);
// CONCATENATED MODULE: ./src/controller/timeline-controller.js
function timeline_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function timeline_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call...
function timeline_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = ...
/*
* Timeline Controller
*/
function reuseVttTextTrack(inUseTrack, manifestTrack) {
return inUseTrack && inUseTrack.label === manifestTrack.name && !(inUseTrack.textTrack1 || inUseTrack.textTrack2);
}
function intersection(x1, x2, y1, y2) {
return Math.min(x2, y2) - Math.max(x1, y1);
}
var timeline_controller_TimelineController = function (_EventHandler) {
timeline_controller__inherits(TimelineController, _EventHandler);
function TimelineController(hls) {
timeline_controller__classCallCheck(this, TimelineController);
var _this = timeline_controller__possibleConstructorReturn(this, _EventHandler.call(this, hls, events["a" /* default */].MEDIA_ATTACHING, events["a" /* default */].MEDIA_DETACHING, events["a" /* default */].FRAG_PARSING_USERDATA, events["a" /* de...
_this.hls = hls;
_this.config = hls.config;
_this.enabled = true;
_this.Cues = hls.config.cueHandler;
_this.textTracks = [];
_this.tracks = [];
_this.unparsedVttFrags = [];
_this.initPTS = undefined;
_this.cueRanges = [];
_this.captionsTracks = {};
_this.captionsProperties = {
textTrack1: {
label: _this.config.captionsTextTrack1Label,
languageCode: _this.config.captionsTextTrack1LanguageCode
},
textTrack2: {
label: _this.config.captionsTextTrack2Label,
languageCode: _this.config.captionsTextTrack2LanguageCode
}
};
if (_this.config.enableCEA708Captions) {
var channel1 = new output_filter(_this, 'textTrack1');
var channel2 = new output_filter(_this, 'textTrack2');
_this.cea608Parser = new cea_608_parser(0, channel1, channel2);
}
return _this;
}
share/public_html/static/hls.js view on Meta::CPAN
}
_this3.textTracks.push(textTrack);
});
}
};
TimelineController.prototype.onLevelSwitching = function onLevelSwitching() {
this.enabled = this.hls.currentLevel.closedCaptions !== 'NONE';
};
TimelineController.prototype.onFragLoaded = function onFragLoaded(data) {
var frag = data.frag,
payload = data.payload;
if (frag.type === 'main') {
var sn = frag.sn;
// if this frag isn't contiguous, clear the parser so cues with bad start/end times aren't added to the textTrack
if (sn !== this.lastSn + 1) {
var cea608Parser = this.cea608Parser;
if (cea608Parser) {
cea608Parser.reset();
}
}
this.lastSn = sn;
} // eslint-disable-line brace-style
// If fragment is subtitle type, parse as WebVTT.
else if (frag.type === 'subtitle') {
if (payload.byteLength) {
// We need an initial synchronisation PTS. Store fragments as long as none has arrived.
if (typeof this.initPTS === 'undefined') {
this.unparsedVttFrags.push(data);
return;
}
var decryptData = frag.decryptdata;
// If the subtitles are not encrypted, parse VTTs now. Otherwise, we need to wait.
if (decryptData == null || decryptData.key == null || decryptData.method !== 'AES-128') {
this._parseVTTs(frag, payload);
}
} else {
// In case there is no payload, finish unsuccessfully.
this.hls.trigger(events["a" /* default */].SUBTITLE_FRAG_PROCESSED, { success: false, frag: frag });
}
}
};
TimelineController.prototype._parseVTTs = function _parseVTTs(frag, payload) {
var vttCCs = this.vttCCs;
if (!vttCCs[frag.cc]) {
vttCCs[frag.cc] = { start: frag.start, prevCC: this.prevCC, new: true };
this.prevCC = frag.cc;
}
var textTracks = this.textTracks,
hls = this.hls;
// Parse the WebVTT file contents.
webvtt_parser.parse(payload, this.initPTS, vttCCs, frag.cc, function (cues) {
var currentTrack = textTracks[frag.trackId];
// WebVTTParser.parse is an async method and if the currently selected text track mode is set to "disabled"
// before parsing is done then don't try to access currentTrack.cues.getCueById as cues will be null
// and trying to access getCueById method of cues will throw an exception
if (currentTrack.mode === 'disabled') {
hls.trigger(events["a" /* default */].SUBTITLE_FRAG_PROCESSED, { success: false, frag: frag });
return;
}
// Add cues and trigger event with success true.
cues.forEach(function (cue) {
// Sometimes there are cue overlaps on segmented vtts so the same
// cue can appear more than once in different vtt files.
// This avoid showing duplicated cues with same timecode and text.
if (!currentTrack.cues.getCueById(cue.id)) {
try {
currentTrack.addCue(cue);
} catch (err) {
var textTrackCue = new window.TextTrackCue(cue.startTime, cue.endTime, cue.text);
textTrackCue.id = cue.id;
currentTrack.addCue(textTrackCue);
}
}
});
hls.trigger(events["a" /* default */].SUBTITLE_FRAG_PROCESSED, { success: true, frag: frag });
}, function (e) {
// Something went wrong while parsing. Trigger event with success false.
logger["b" /* logger */].log('Failed to parse VTT cue: ' + e);
hls.trigger(events["a" /* default */].SUBTITLE_FRAG_PROCESSED, { success: false, frag: frag });
});
};
TimelineController.prototype.onFragDecrypted = function onFragDecrypted(data) {
var decryptedData = data.payload,
frag = data.frag;
if (frag.type === 'subtitle') {
if (typeof this.initPTS === 'undefined') {
this.unparsedVttFrags.push(data);
return;
}
this._parseVTTs(frag, decryptedData);
}
};
TimelineController.prototype.onFragParsingUserdata = function onFragParsingUserdata(data) {
// push all of the CEA-708 messages into the interpreter
// immediately. It will create the proper timestamps based on our PTS value
if (this.enabled && this.config.enableCEA708Captions) {
for (var i = 0; i < data.samples.length; i++) {
var ccdatas = this.extractCea608Data(data.samples[i].bytes);
this.cea608Parser.addData(data.samples[i].pts, ccdatas);
}
}
};
TimelineController.prototype.extractCea608Data = function extractCea608Data(byteArray) {
var count = byteArray[0] & 31;
var position = 2;
var tmpByte = void 0,
ccbyte1 = void 0,
ccbyte2 = void 0,
ccValid = void 0,
ccType = void 0;
var actualCCBytes = [];
for (var j = 0; j < count; j++) {
tmpByte = byteArray[position++];
ccbyte1 = 0x7F & byteArray[position++];
ccbyte2 = 0x7F & byteArray[position++];
ccValid = (4 & tmpByte) !== 0;
ccType = 3 & tmpByte;
if (ccbyte1 === 0 && ccbyte2 === 0) {
continue;
}
if (ccValid) {
if (ccType === 0) {
// || ccType === 1
actualCCBytes.push(ccbyte1);
actualCCBytes.push(ccbyte2);
}
}
}
return actualCCBytes;
};
return TimelineController;
}(event_handler);
/* harmony default export */ var timeline_controller = (timeline_controller_TimelineController);
// CONCATENATED MODULE: ./src/controller/subtitle-track-controller.js
var subtitle_track_controller__createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable ...
function subtitle_track_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function subtitle_track_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ...
function subtitle_track_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.protot...
/*
* subtitle track controller
*/
function filterSubtitleTracks(textTrackList) {
var tracks = [];
for (var i = 0; i < textTrackList.length; i++) {
if (textTrackList[i].kind === 'subtitles') {
tracks.push(textTrackList[i]);
}
}
return tracks;
}
var subtitle_track_controller_SubtitleTrackController = function (_EventHandler) {
subtitle_track_controller__inherits(SubtitleTrackController, _EventHandler);
function SubtitleTrackController(hls) {
subtitle_track_controller__classCallCheck(this, SubtitleTrackController);
var _this = subtitle_track_controller__possibleConstructorReturn(this, _EventHandler.call(this, hls, events["a" /* default */].MEDIA_ATTACHED, events["a" /* default */].MEDIA_DETACHING, events["a" /* default */].MANIFEST_LOADING, events["a" /* de...
_this.tracks = [];
_this.trackId = -1;
_this.media = null;
/**
* @member {boolean} subtitleDisplay Enable/disable subtitle display rendering
*/
_this.subtitleDisplay = true;
return _this;
}
SubtitleTrackController.prototype._onTextTracksChanged = function _onTextTracksChanged() {
// Media is undefined when switching streams via loadSource()
if (!this.media) {
return;
}
var trackId = -1;
var tracks = filterSubtitleTracks(this.media.textTracks);
for (var id = 0; id < tracks.length; id++) {
if (tracks[id].mode === 'hidden') {
// Do not break in case there is a following track with showing.
trackId = id;
} else if (tracks[id].mode === 'showing') {
trackId = id;
break;
}
}
// Setting current subtitleTrack will invoke code.
this.subtitleTrack = trackId;
};
share/public_html/static/hls.js view on Meta::CPAN
SubtitleTrackController.prototype._toggleTrackModes = function _toggleTrackModes(newId) {
var media = this.media,
subtitleDisplay = this.subtitleDisplay,
trackId = this.trackId;
if (!media) {
return;
}
var textTracks = filterSubtitleTracks(media.textTracks);
if (newId === -1) {
[].slice.call(textTracks).forEach(function (track) {
track.mode = 'disabled';
});
} else {
var oldTrack = textTracks[trackId];
if (oldTrack) {
oldTrack.mode = 'disabled';
}
}
var nextTrack = textTracks[newId];
if (nextTrack) {
nextTrack.mode = subtitleDisplay ? 'showing' : 'hidden';
}
};
subtitle_track_controller__createClass(SubtitleTrackController, [{
key: 'subtitleTracks',
get: function get() {
return this.tracks;
}
/** get index of the selected subtitle track (index in subtitle track lists) **/
}, {
key: 'subtitleTrack',
get: function get() {
return this.trackId;
}
/** select a subtitle track, based on its index in subtitle track lists**/
,
set: function set(subtitleTrackId) {
if (this.trackId !== subtitleTrackId) {
this._toggleTrackModes(subtitleTrackId);
this.setSubtitleTrackInternal(subtitleTrackId);
}
}
}]);
return SubtitleTrackController;
}(event_handler);
/* harmony default export */ var subtitle_track_controller = (subtitle_track_controller_SubtitleTrackController);
// EXTERNAL MODULE: ./src/crypt/decrypter.js + 3 modules
var decrypter = __webpack_require__(7);
// CONCATENATED MODULE: ./src/controller/subtitle-stream-controller.js
function subtitle_stream_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function subtitle_stream_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function")...
function subtitle_stream_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.proto...
/*
* Subtitle Stream Controller
*/
var subtitle_stream_controller__window = window,
subtitle_stream_controller_performance = subtitle_stream_controller__window.performance;
var subtitle_stream_controller_State = {
STOPPED: 'STOPPED',
IDLE: 'IDLE',
KEY_LOADING: 'KEY_LOADING',
FRAG_LOADING: 'FRAG_LOADING'
};
var subtitle_stream_controller_SubtitleStreamController = function (_TaskLoop) {
subtitle_stream_controller__inherits(SubtitleStreamController, _TaskLoop);
function SubtitleStreamController(hls) {
subtitle_stream_controller__classCallCheck(this, SubtitleStreamController);
var _this = subtitle_stream_controller__possibleConstructorReturn(this, _TaskLoop.call(this, hls, events["a" /* default */].MEDIA_ATTACHED, events["a" /* default */].ERROR, events["a" /* default */].KEY_LOADED, events["a" /* default */].FRAG_LOAD...
_this.config = hls.config;
_this.vttFragSNsProcessed = {};
_this.vttFragQueues = undefined;
_this.currentlyProcessing = null;
_this.state = subtitle_stream_controller_State.STOPPED;
_this.currentTrackId = -1;
_this.decrypter = new decrypter["a" /* default */](hls.observer, hls.config);
return _this;
}
SubtitleStreamController.prototype.onHandlerDestroyed = function onHandlerDestroyed() {
this.state = subtitle_stream_controller_State.STOPPED;
};
// Remove all queued items and create a new, empty queue for each track.
SubtitleStreamController.prototype.clearVttFragQueues = function clearVttFragQueues() {
var _this2 = this;
this.vttFragQueues = {};
this.tracks.forEach(function (track) {
_this2.vttFragQueues[track.id] = [];
});
};
// If no frag is being processed and queue isn't empty, initiate processing of next frag in line.
SubtitleStreamController.prototype.nextFrag = function nextFrag() {
if (this.currentlyProcessing === null && this.currentTrackId > -1 && this.vttFragQueues[this.currentTrackId].length) {
share/public_html/static/hls.js view on Meta::CPAN
return;
}
// Check if track was already loaded and if so make sure we finish
// downloading its frags, if not all have been downloaded yet
var currentTrack = this.tracks[this.currentTrackId];
if (currentTrack && currentTrack.details) {
this.tick();
}
};
// Got a new set of subtitle fragments.
SubtitleStreamController.prototype.onSubtitleTrackLoaded = function onSubtitleTrackLoaded() {
this.tick();
};
SubtitleStreamController.prototype.onKeyLoaded = function onKeyLoaded() {
if (this.state === subtitle_stream_controller_State.KEY_LOADING) {
this.state = subtitle_stream_controller_State.IDLE;
this.tick();
}
};
SubtitleStreamController.prototype.onFragLoaded = function onFragLoaded(data) {
var fragCurrent = this.fragCurrent,
decryptData = data.frag.decryptdata;
var fragLoaded = data.frag,
hls = this.hls;
if (this.state === subtitle_stream_controller_State.FRAG_LOADING && fragCurrent && data.frag.type === 'subtitle' && fragCurrent.sn === data.frag.sn) {
// check to see if the payload needs to be decrypted
if (data.payload.byteLength > 0 && decryptData != null && decryptData.key != null && decryptData.method === 'AES-128') {
var startTime = void 0;
try {
startTime = subtitle_stream_controller_performance.now();
} catch (error) {
startTime = Date.now();
}
// decrypt the subtitles
this.decrypter.decrypt(data.payload, decryptData.key.buffer, decryptData.iv.buffer, function (decryptedData) {
var endTime = void 0;
try {
endTime = subtitle_stream_controller_performance.now();
} catch (error) {
endTime = Date.now();
}
hls.trigger(events["a" /* default */].FRAG_DECRYPTED, { frag: fragLoaded, payload: decryptedData, stats: { tstart: startTime, tdecrypt: endTime } });
});
}
}
};
return SubtitleStreamController;
}(task_loop);
/* harmony default export */ var subtitle_stream_controller = (subtitle_stream_controller_SubtitleStreamController);
// CONCATENATED MODULE: ./src/controller/eme-controller.js
var eme_controller__createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ...
function eme_controller__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function eme_controller__possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : se...
function eme_controller__inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Objec...
/**
* @author Stephan Hesse <disparat@gmail.com> | <tchakabam@gmail.com>
*
* DRM support for Hls.js
*/
var eme_controller__window = window,
eme_controller_XMLHttpRequest = eme_controller__window.XMLHttpRequest;
var MAX_LICENSE_REQUEST_FAILURES = 3;
/**
* @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/requestMediaKeySystemAccess
*/
var KeySystems = {
WIDEVINE: 'com.widevine.alpha',
PLAYREADY: 'com.microsoft.playready'
};
/**
* @see https://developer.mozilla.org/en-US/docs/Web/API/MediaKeySystemConfiguration
* @param {Array<string>} audioCodecs List of required audio codecs to support
* @param {Array<string>} videoCodecs List of required video codecs to support
* @param {object} drmSystemOptions Optional parameters/requirements for the key-system
* @returns {Array<MediaSystemConfiguration>} An array of supported configurations
*/
var createWidevineMediaKeySystemConfigurations = function createWidevineMediaKeySystemConfigurations(audioCodecs, videoCodecs, drmSystemOptions) {
/* jshint ignore:line */
var baseConfig = {
// initDataTypes: ['keyids', 'mp4'],
// label: "",
// persistentState: "not-allowed", // or "required" ?
// distinctiveIdentifier: "not-allowed", // or "required" ?
// sessionTypes: ['temporary'],
videoCapabilities: [
// { contentType: 'video/mp4; codecs="avc1.42E01E"' }
]
};
videoCodecs.forEach(function (codec) {
baseConfig.videoCapabilities.push({
contentType: 'video/mp4; codecs="' + codec + '"'
});
});
return [baseConfig];
};
/**
* The idea here is to handle key-system (and their respective platforms) specific configuration differences
* in order to work with the local requestMediaKeySystemAccess method.
*
* We can also rule-out platform-related key-system support at this point by throwing an error or returning null.
*
* @param {string} keySystem Identifier for the key-system, see `KeySystems` enum
* @param {Array<string>} audioCodecs List of required audio codecs to support
* @param {Array<string>} videoCodecs List of required video codecs to support
* @returns {Array<MediaSystemConfiguration> | null} A non-empty Array of MediaKeySystemConfiguration objects or `null`
*/
var getSupportedMediaKeySystemConfigurations = function getSupportedMediaKeySystemConfigurations(keySystem, audioCodecs, videoCodecs) {
switch (keySystem) {
case KeySystems.WIDEVINE:
return createWidevineMediaKeySystemConfigurations(audioCodecs, videoCodecs);
default:
throw Error('Unknown key-system: ' + keySystem);
}
};
/**
* Controller to deal with encrypted media extensions (EME)
* @see https://developer.mozilla.org/en-US/docs/Web/API/Encrypted_Media_Extensions_API
*
* @class
* @constructor
*/
var eme_controller_EMEController = function (_EventHandler) {
eme_controller__inherits(EMEController, _EventHandler);
/**
* @constructs
* @param {Hls} hls Our Hls.js instance
*/
function EMEController(hls) {
eme_controller__classCallCheck(this, EMEController);
var _this = eme_controller__possibleConstructorReturn(this, _EventHandler.call(this, hls, events["a" /* default */].MEDIA_ATTACHED, events["a" /* default */].MANIFEST_PARSED));
_this._widevineLicenseUrl = hls.config.widevineLicenseUrl;
_this._licenseXhrSetup = hls.config.licenseXhrSetup;
_this._emeEnabled = hls.config.emeEnabled;
_this._requestMediaKeySystemAccess = hls.config.requestMediaKeySystemAccessFunc;
_this._mediaKeysList = [];
_this._media = null;
_this._hasSetMediaKeys = false;
_this._isMediaEncrypted = false;
_this._requestLicenseFailureCount = 0;
return _this;
}
/**
*
* @param {string} keySystem Identifier for the key-system, see `KeySystems` enum
* @returns {string} License server URL for key-system (if any configured, otherwise causes error)
*/
EMEController.prototype.getLicenseServerUrl = function getLicenseServerUrl(keySystem) {
var url = void 0;
switch (keySystem) {
case KeySystems.WIDEVINE:
url = this._widevineLicenseUrl;
break;
default:
url = null;
break;
}
if (!url) {
logger["b" /* logger */].error('No license server URL configured for key-system "' + keySystem + '"');
this.hls.trigger(events["a" /* default */].ERROR, {
share/public_html/static/hls.js view on Meta::CPAN
logger["b" /* logger */].warn('Key-Session already initialized but requested again');
return;
}
var keySession = keysListItem.mediaKeysSession;
if (!keySession) {
logger["b" /* logger */].error('Fatal: Media is encrypted but no key-session existing');
this.hls.trigger(events["a" /* default */].ERROR, {
type: errors["b" /* ErrorTypes */].KEY_SYSTEM_ERROR,
details: errors["a" /* ErrorDetails */].KEY_SYSTEM_NO_SESSION,
fatal: true
});
}
var initDataType = this._mediaEncryptionInitDataType;
var initData = this._mediaEncryptionInitData;
logger["b" /* logger */].log('Generating key-session request for "' + initDataType + '" init data type');
keysListItem.mediaKeysSessionInitialized = true;
keySession.generateRequest(initDataType, initData).then(function () {
logger["b" /* logger */].debug('Key-session generation succeeded');
}).catch(function (err) {
logger["b" /* logger */].error('Error generating key-session request:', err);
_this6.hls.trigger(events["a" /* default */].ERROR, {
type: errors["b" /* ErrorTypes */].KEY_SYSTEM_ERROR,
details: errors["a" /* ErrorDetails */].KEY_SYSTEM_NO_SESSION,
fatal: false
});
});
};
/**
* @param {string} url License server URL
* @param {ArrayBuffer} keyMessage Message data issued by key-system
* @param {function} callback Called when XHR has succeeded
* @returns {XMLHttpRequest} Unsent (but opened state) XHR object
*/
EMEController.prototype._createLicenseXhr = function _createLicenseXhr(url, keyMessage, callback) {
var xhr = new eme_controller_XMLHttpRequest();
var licenseXhrSetup = this._licenseXhrSetup;
try {
if (licenseXhrSetup) {
try {
licenseXhrSetup(xhr, url);
} catch (e) {
// let's try to open before running setup
xhr.open('POST', url, true);
licenseXhrSetup(xhr, url);
}
}
// if licenseXhrSetup did not yet call open, let's do it now
if (!xhr.readyState) {
xhr.open('POST', url, true);
}
} catch (e) {
// IE11 throws an exception on xhr.open if attempting to access an HTTP resource over HTTPS
logger["b" /* logger */].error('Error setting up key-system license XHR', e);
this.hls.trigger(events["a" /* default */].ERROR, {
type: errors["b" /* ErrorTypes */].KEY_SYSTEM_ERROR,
details: errors["a" /* ErrorDetails */].KEY_SYSTEM_LICENSE_REQUEST_FAILED,
fatal: true
});
return;
}
xhr.responseType = 'arraybuffer';
xhr.onreadystatechange = this._onLicenseRequestReadyStageChange.bind(this, xhr, url, keyMessage, callback);
return xhr;
};
/**
* @param {XMLHttpRequest} xhr
* @param {string} url License server URL
* @param {ArrayBuffer} keyMessage Message data issued by key-system
* @param {function} callback Called when XHR has succeeded
*
*/
EMEController.prototype._onLicenseRequestReadyStageChange = function _onLicenseRequestReadyStageChange(xhr, url, keyMessage, callback) {
switch (xhr.readyState) {
case 4:
if (xhr.status === 200) {
this._requestLicenseFailureCount = 0;
logger["b" /* logger */].log('License request succeeded');
callback(xhr.response);
} else {
logger["b" /* logger */].error('License Request XHR failed (' + url + '). Status: ' + xhr.status + ' (' + xhr.statusText + ')');
this._requestLicenseFailureCount++;
if (this._requestLicenseFailureCount <= MAX_LICENSE_REQUEST_FAILURES) {
var attemptsLeft = MAX_LICENSE_REQUEST_FAILURES - this._requestLicenseFailureCount + 1;
logger["b" /* logger */].warn('Retrying license request, ' + attemptsLeft + ' attempts left');
this._requestLicense(keyMessage, callback);
return;
}
this.hls.trigger(events["a" /* default */].ERROR, {
type: errors["b" /* ErrorTypes */].KEY_SYSTEM_ERROR,
details: errors["a" /* ErrorDetails */].KEY_SYSTEM_LICENSE_REQUEST_FAILED,
fatal: true
});
}
break;
}
};
/**
* @param {object} keysListItem
* @param {ArrayBuffer} keyMessage
* @returns {ArrayBuffer} Challenge data posted to license server
*/
EMEController.prototype._generateLicenseRequestChallenge = function _generateLicenseRequestChallenge(keysListItem, keyMessage) {
var challenge = void 0;
if (keysListItem.mediaKeySystemDomain === KeySystems.PLAYREADY) {
logger["b" /* logger */].error('PlayReady is not supported (yet)');
// from https://github.com/MicrosoftEdge/Demos/blob/master/eme/scripts/demo.js
/*
if (this.licenseType !== this.LICENSE_TYPE_WIDEVINE) {
// For PlayReady CDMs, we need to dig the Challenge out of the XML.
var keyMessageXml = new DOMParser().parseFromString(String.fromCharCode.apply(null, new Uint16Array(keyMessage)), 'application/xml');
if (keyMessageXml.getElementsByTagName('Challenge')[0]) {
challenge = atob(keyMessageXml.getElementsByTagName('Challenge')[0].childNodes[0].nodeValue);
} else {
throw 'Cannot find <Challenge> in key message';
}
var headerNames = keyMessageXml.getElementsByTagName('name');
var headerValues = keyMessageXml.getElementsByTagName('value');
if (headerNames.length !== headerValues.length) {
throw 'Mismatched header <name>/<value> pair in key message';
}
for (var i = 0; i < headerNames.length; i++) {
xhr.setRequestHeader(headerNames[i].childNodes[0].nodeValue, headerValues[i].childNodes[0].nodeValue);
}
}
*/
} else if (keysListItem.mediaKeySystemDomain === KeySystems.WIDEVINE) {
// For Widevine CDMs, the challenge is the keyMessage.
challenge = keyMessage;
} else {
logger["b" /* logger */].error('Unsupported key-system:', keysListItem.mediaKeySystemDomain);
}
return challenge;
};
EMEController.prototype._requestLicense = function _requestLicense(keyMessage, callback) {
logger["b" /* logger */].log('Requesting content license for key-system');
var keysListItem = this._mediaKeysList[0];
if (!keysListItem) {
logger["b" /* logger */].error('Fatal error: Media is encrypted but no key-system access has been obtained yet');
this.hls.trigger(events["a" /* default */].ERROR, {
type: errors["b" /* ErrorTypes */].KEY_SYSTEM_ERROR,
details: errors["a" /* ErrorDetails */].KEY_SYSTEM_NO_ACCESS,
fatal: true
});
return;
}
var url = this.getLicenseServerUrl(keysListItem.mediaKeySystemDomain);
var xhr = this._createLicenseXhr(url, keyMessage, callback);
logger["b" /* logger */].log('Sending license request to URL: ' + url);
xhr.send(this._generateLicenseRequestChallenge(keysListItem, keyMessage));
};
EMEController.prototype.onMediaAttached = function onMediaAttached(data) {
var _this7 = this;
if (!this._emeEnabled) {
return;
}
var media = data.media;
// keep reference of media
this._media = media;
// FIXME: also handle detaching media !
media.addEventListener('encrypted', function (e) {
_this7._onMediaEncrypted(e.initDataType, e.initData);
});
};
EMEController.prototype.onManifestParsed = function onManifestParsed(data) {
if (!this._emeEnabled) {
return;
}
var audioCodecs = data.levels.map(function (level) {
return level.audioCodec;
});
var videoCodecs = data.levels.map(function (level) {
return level.videoCodec;
});
this._attemptKeySystemAccess(KeySystems.WIDEVINE, audioCodecs, videoCodecs);
};
eme_controller__createClass(EMEController, [{
key: 'requestMediaKeySystemAccess',
get: function get() {
if (!this._requestMediaKeySystemAccess) {
throw new Error('No requestMediaKeySystemAccess function configured');
}
return this._requestMediaKeySystemAccess;
}
}]);
return EMEController;
}(event_handler);
/* harmony default export */ var eme_controller = (eme_controller_EMEController);
// CONCATENATED MODULE: ./src/utils/mediakeys-helper.js
var requestMediaKeySystemAccess = function () {
if (typeof window !== 'undefined' && window.navigator && window.navigator.requestMediaKeySystemAccess) {
return window.navigator.requestMediaKeySystemAccess.bind(window.navigator);
} else {
return null;
}
}();
// CONCATENATED MODULE: ./src/config.js
/**
* HLS config
*/
// import FetchLoader from './utils/fetch-loader';
var hlsDefaultConfig = {
autoStartLoad: true, // used by stream-controller
startPosition: -1, // used by stream-controller
defaultAudioCodec: undefined, // used by stream-controller
debug: false, // used by logger
capLevelOnFPSDrop: false, // used by fps-controller
capLevelToPlayerSize: false, // used by cap-level-controller
initialLiveManifestSize: 1, // used by stream-controller
maxBufferLength: 30, // used by stream-controller
maxBufferSize: 60 * 1000 * 1000, // used by stream-controller
maxBufferHole: 0.5, // used by stream-controller
lowBufferWatchdogPeriod: 0.5, // used by stream-controller
highBufferWatchdogPeriod: 3, // used by stream-controller
nudgeOffset: 0.1, // used by stream-controller
nudgeMaxRetry: 3, // used by stream-controller
maxFragLookUpTolerance: 0.25, // used by stream-controller
share/public_html/static/hls.js view on Meta::CPAN
fragLoadingRetryDelay: 1000, // used by fragment-loader
fragLoadingMaxRetryTimeout: 64000, // used by fragment-loader
startFragPrefetch: false, // used by stream-controller
fpsDroppedMonitoringPeriod: 5000, // used by fps-controller
fpsDroppedMonitoringThreshold: 0.2, // used by fps-controller
appendErrorMaxRetry: 3, // used by buffer-controller
loader: xhr_loader,
// loader: FetchLoader,
fLoader: undefined, // used by fragment-loader
pLoader: undefined, // used by playlist-loader
xhrSetup: undefined, // used by xhr-loader
licenseXhrSetup: undefined, // used by eme-controller
// fetchSetup: undefined,
abrController: abr_controller,
bufferController: buffer_controller,
capLevelController: cap_level_controller,
fpsController: fps_controller,
stretchShortVideoTrack: false, // used by mp4-remuxer
maxAudioFramesDrift: 1, // used by mp4-remuxer
forceKeyFrameOnDiscontinuity: true, // used by ts-demuxer
abrEwmaFastLive: 3, // used by abr-controller
abrEwmaSlowLive: 9, // used by abr-controller
abrEwmaFastVoD: 3, // used by abr-controller
abrEwmaSlowVoD: 9, // used by abr-controller
abrEwmaDefaultEstimate: 5e5, // 500 kbps // used by abr-controller
abrBandWidthFactor: 0.95, // used by abr-controller
abrBandWidthUpFactor: 0.7, // used by abr-controller
abrMaxWithRealBitrate: false, // used by abr-controller
maxStarvationDelay: 4, // used by abr-controller
maxLoadingDelay: 4, // used by abr-controller
minAutoBitrate: 0, // used by hls
emeEnabled: false, // used by eme-controller
widevineLicenseUrl: undefined, // used by eme-controller
requestMediaKeySystemAccessFunc: requestMediaKeySystemAccess // used by eme-controller
};
if (true) {
hlsDefaultConfig.subtitleStreamController = subtitle_stream_controller;
hlsDefaultConfig.subtitleTrackController = subtitle_track_controller;
hlsDefaultConfig.timelineController = timeline_controller;
hlsDefaultConfig.cueHandler = cues_namespaceObject; // used by timeline-controller
hlsDefaultConfig.enableCEA708Captions = true; // used by timeline-controller
hlsDefaultConfig.enableWebVTT = true; // used by timeline-controller
hlsDefaultConfig.captionsTextTrack1Label = 'English'; // used by timeline-controller
hlsDefaultConfig.captionsTextTrack1LanguageCode = 'en'; // used by timeline-controller
hlsDefaultConfig.captionsTextTrack2Label = 'Spanish'; // used by timeline-controller
hlsDefaultConfig.captionsTextTrack2LanguageCode = 'es'; // used by timeline-controller
}
if (true) {
hlsDefaultConfig.audioStreamController = audio_stream_controller;
hlsDefaultConfig.audioTrackController = audio_track_controller;
}
if (true) {
hlsDefaultConfig.emeController = eme_controller;
}
// CONCATENATED MODULE: ./src/hls.js
var hls__createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in...
function hls__classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
// polyfill for IE11
__webpack_require__(13);
/**
* @module Hls
* @class
* @constructor
*/
var hls_Hls = function () {
/**
* @type {boolean}
*/
Hls.isSupported = function isSupported() {
return is_supported_isSupported();
};
/**
* @type {HlsEvents}
*/
hls__createClass(Hls, null, [{
key: 'version',
/**
* @type {string}
*/
get: function get() {
return "0.10.1";
}
}, {
key: 'Events',
get: function get() {
return events["a" /* default */];
}
/**
* @type {HlsErrorTypes}
*/
}, {
key: 'ErrorTypes',
get: function get() {
return errors["b" /* ErrorTypes */];
}
/**
* @type {HlsErrorDetails}
*/
}, {
key: 'ErrorDetails',
get: function get() {
return errors["a" /* ErrorDetails */];
}
/**
* @type {HlsConfig}
*/
}, {
key: 'DefaultConfig',
get: function get() {
if (!Hls.defaultConfig) {
return hlsDefaultConfig;
}
return Hls.defaultConfig;
}
/**
* @type {HlsConfig}
*/
,
set: function set(defaultConfig) {
Hls.defaultConfig = defaultConfig;
}
/**
* Creates an instance of an HLS client that can attach to exactly one `HTMLMediaElement`.
*
* @constructs Hls
* @param {HlsConfig} config
*/
}]);
function Hls() {
var _this = this;
var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
hls__classCallCheck(this, Hls);
var defaultConfig = Hls.DefaultConfig;
if ((config.liveSyncDurationCount || config.liveMaxLatencyDurationCount) && (config.liveSyncDuration || config.liveMaxLatencyDuration)) {
throw new Error('Illegal hls.js config: don\'t mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration');
}
for (var prop in defaultConfig) {
if (prop in config) continue;
config[prop] = defaultConfig[prop];
}
if (config.liveMaxLatencyDurationCount !== undefined && config.liveMaxLatencyDurationCount <= config.liveSyncDurationCount) {
throw new Error('Illegal hls.js config: "liveMaxLatencyDurationCount" must be gt "liveSyncDurationCount"');
}
if (config.liveMaxLatencyDuration !== undefined && (config.liveMaxLatencyDuration <= config.liveSyncDuration || config.liveSyncDuration === undefined)) {
throw new Error('Illegal hls.js config: "liveMaxLatencyDuration" must be gt "liveSyncDuration"');
}
Object(logger["a" /* enableLogs */])(config.debug);
this.config = config;
this._autoLevelCapping = -1;
// observer setup
var observer = this.observer = new events_default.a();
observer.trigger = function trigger(event) {
for (var _len = arguments.length, data = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
data[_key - 1] = arguments[_key];
}
observer.emit.apply(observer, [event, event].concat(data));
};
observer.off = function off(event) {
for (var _len2 = arguments.length, data = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
data[_key2 - 1] = arguments[_key2];
}
observer.removeListener.apply(observer, [event].concat(data));
};
this.on = observer.on.bind(observer);
this.off = observer.off.bind(observer);
this.once = observer.once.bind(observer);
this.trigger = observer.trigger.bind(observer);
// core controllers and network loaders
/**
* @member {AbrController} abrController
*/
var abrController = this.abrController = new config.abrController(this);
var bufferController = new config.bufferController(this);
var capLevelController = new config.capLevelController(this);
var fpsController = new config.fpsController(this);
var playListLoader = new playlist_loader(this);
var fragmentLoader = new fragment_loader(this);
var keyLoader = new key_loader(this);
var id3TrackController = new id3_track_controller(this);
// network controllers
/**
* @member {LevelController} levelController
*/
var levelController = this.levelController = new level_controller(this);
// FIXME: FragmentTracker must be defined before StreamController because the order of event handling is important
var fragmentTracker = new fragment_tracker_FragmentTracker(this);
/**
* @member {StreamController} streamController
*/
var streamController = this.streamController = new stream_controller(this, fragmentTracker);
var networkControllers = [levelController, streamController];
// optional audio stream controller
share/public_html/static/hls.js view on Meta::CPAN
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/ // on error function for async loading
/******/ __webpack_require__.oe = function(err) { console.error(err); throw err; };
var f = __webpack_require__(__webpack_require__.s = ENTRY_MODULE)
return f.default || f // try to call default if defined to also support babel esmodule exports
}
var moduleNameReqExp = '[\\.|\\-|\\+|\\w|\/|@]+'
var dependencyRegExp = '\\((\/\\*.*?\\*\/)?\s?.*?(' + moduleNameReqExp + ').*?\\)' // additional chars when output.pathinfo is true
// http://stackoverflow.com/a/2593661/130442
function quoteRegExp (str) {
return (str + '').replace(/[.?*+^$[\]\\(){}|-]/g, '\\$&')
}
function getModuleDependencies (sources, module, queueName) {
var retval = {}
retval[queueName] = []
var fnString = module.toString()
var wrapperSignature = fnString.match(/^function\s?\(\w+,\s*\w+,\s*(\w+)\)/)
if (!wrapperSignature) return retval
var webpackRequireName = wrapperSignature[1]
// main bundle deps
var re = new RegExp('(\\\\n|\\W)' + quoteRegExp(webpackRequireName) + dependencyRegExp, 'g')
var match
while ((match = re.exec(fnString))) {
if (match[3] === 'dll-reference') continue
retval[queueName].push(match[3])
}
// dll deps
re = new RegExp('\\(' + quoteRegExp(webpackRequireName) + '\\("(dll-reference\\s(' + moduleNameReqExp + '))"\\)\\)' + dependencyRegExp, 'g')
while ((match = re.exec(fnString))) {
if (!sources[match[2]]) {
retval[queueName].push(match[1])
sources[match[2]] = __webpack_require__(match[1]).m
}
retval[match[2]] = retval[match[2]] || []
retval[match[2]].push(match[4])
}
return retval
}
function hasValuesInQueues (queues) {
var keys = Object.keys(queues)
return keys.reduce(function (hasValues, key) {
return hasValues || queues[key].length > 0
}, false)
}
function getRequiredModules (sources, moduleId) {
var modulesQueue = {
main: [moduleId]
}
var requiredModules = {
main: []
}
var seenModules = {
main: {}
share/public_html/static/hls.js view on Meta::CPAN
// signal end of worker init
forwardMessage('init', null);
break;
case 'demux':
self.demuxer.push(data.data, data.decryptdata, data.initSegment, data.audioCodec, data.videoCodec, data.timeOffset, data.discontinuity, data.trackSwitch, data.contiguous, data.duration, data.accurateTimeOffset, data.defaultInitPTS);
break;
default:
break;
}
});
// forward events to main thread
observer.on(__WEBPACK_IMPORTED_MODULE_1__events__["a" /* default */].FRAG_DECRYPTED, forwardMessage);
observer.on(__WEBPACK_IMPORTED_MODULE_1__events__["a" /* default */].FRAG_PARSING_INIT_SEGMENT, forwardMessage);
observer.on(__WEBPACK_IMPORTED_MODULE_1__events__["a" /* default */].FRAG_PARSED, forwardMessage);
observer.on(__WEBPACK_IMPORTED_MODULE_1__events__["a" /* default */].ERROR, forwardMessage);
observer.on(__WEBPACK_IMPORTED_MODULE_1__events__["a" /* default */].FRAG_PARSING_METADATA, forwardMessage);
observer.on(__WEBPACK_IMPORTED_MODULE_1__events__["a" /* default */].FRAG_PARSING_USERDATA, forwardMessage);
observer.on(__WEBPACK_IMPORTED_MODULE_1__events__["a" /* default */].INIT_PTS_FOUND, forwardMessage);
// special case for FRAG_PARSING_DATA: pass data1/data2 as transferable object (no copy)
observer.on(__WEBPACK_IMPORTED_MODULE_1__events__["a" /* default */].FRAG_PARSING_DATA, function (ev, data) {
var transferable = [];
var message = { event: ev, data: data };
if (data.data1) {
message.data1 = data.data1.buffer;
transferable.push(data.data1.buffer);
delete data.data1;
}
if (data.data2) {
message.data2 = data.data2.buffer;
transferable.push(data.data2.buffer);
delete data.data2;
}
self.postMessage(message, transferable);
});
};
/* harmony default export */ __webpack_exports__["default"] = (DemuxerWorker);
/***/ }),
/* 13 */
/***/ (function(module, exports) {
/*! http://mths.be/endswith v0.2.0 by @mathias */
if (!String.prototype.endsWith) {
(function() {
'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
var defineProperty = (function() {
// IE 8 only supports `Object.defineProperty` on DOM elements
try {
var object = {};
var $defineProperty = Object.defineProperty;
var result = $defineProperty(object, object, object) && $defineProperty;
} catch(error) {}
return result;
}());
var toString = {}.toString;
var endsWith = function(search) {
if (this == null) {
throw TypeError();
}
var string = String(this);
if (search && toString.call(search) == '[object RegExp]') {
throw TypeError();
}
var stringLength = string.length;
var searchString = String(search);
var searchLength = searchString.length;
var pos = stringLength;
if (arguments.length > 1) {
var position = arguments[1];
if (position !== undefined) {
// `ToInteger`
pos = position ? Number(position) : 0;
if (pos != pos) { // better `isNaN`
pos = 0;
}
}
}
var end = Math.min(Math.max(pos, 0), stringLength);
var start = end - searchLength;
if (start < 0) {
return false;
}
var index = -1;
while (++index < searchLength) {
if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
return false;
}
}
return true;
};
if (defineProperty) {
defineProperty(String.prototype, 'endsWith', {
'value': endsWith,
'configurable': true,
'writable': true
});
} else {
String.prototype.endsWith = endsWith;
}
}());
}
/***/ })
/******/ ])["default"];
});
//# sourceMappingURL=hls.js.map