App-MHFS
view release on metacpan or search on metacpan
share/public_html/static/hls.js view on Meta::CPAN
loader.destroy();
}
this.resetInternalLoader(contextType);
}
};
PlaylistLoader.prototype.destroy = function destroy() {
this.destroyInternalLoaders();
_EventHandler.prototype.destroy.call(this);
};
PlaylistLoader.prototype.onManifestLoading = function onManifestLoading(data) {
this.load(data.url, { type: ContextType.MANIFEST, level: 0, id: null });
};
PlaylistLoader.prototype.onLevelLoading = function onLevelLoading(data) {
this.load(data.url, { type: ContextType.LEVEL, level: data.level, id: data.id });
};
PlaylistLoader.prototype.onAudioTrackLoading = function onAudioTrackLoading(data) {
this.load(data.url, { type: ContextType.AUDIO_TRACK, level: 0, id: data.id });
};
PlaylistLoader.prototype.onSubtitleTrackLoading = function onSubtitleTrackLoading(data) {
this.load(data.url, { type: ContextType.SUBTITLE_TRACK, level: 0, id: data.id });
};
PlaylistLoader.prototype.load = function load(url, context) {
var config = this.hls.config;
logger["b" /* logger */].debug('Loading playlist of type ' + context.type + ', level: ' + context.level + ', id: ' + context.id);
// Check if a loader for this context already exists
var loader = this.getInternalLoader(context);
if (loader) {
var loaderContext = loader.context;
if (loaderContext && loaderContext.url === url) {
// same URL can't overlap
logger["b" /* logger */].trace('playlist request ongoing');
return false;
} else {
logger["b" /* logger */].warn('aborting previous loader for type: ' + context.type);
loader.abort();
}
}
var maxRetry = void 0,
timeout = void 0,
retryDelay = void 0,
maxRetryDelay = void 0;
// apply different configs for retries depending on
// context (manifest, level, audio/subs playlist)
switch (context.type) {
case ContextType.MANIFEST:
maxRetry = config.manifestLoadingMaxRetry;
timeout = config.manifestLoadingTimeOut;
retryDelay = config.manifestLoadingRetryDelay;
maxRetryDelay = config.manifestLoadingMaxRetryTimeout;
break;
case ContextType.LEVEL:
// Disable internal loader retry logic, since we are managing retries in Level Controller
maxRetry = 0;
timeout = config.levelLoadingTimeOut;
// TODO Introduce retry settings for audio-track and subtitle-track, it should not use level retry config
break;
default:
maxRetry = config.levelLoadingMaxRetry;
timeout = config.levelLoadingTimeOut;
retryDelay = config.levelLoadingRetryDelay;
maxRetryDelay = config.levelLoadingMaxRetryTimeout;
break;
}
loader = this.createInternalLoader(context);
context.url = url;
context.responseType = context.responseType || ''; // FIXME: (should not be necessary to do this)
var loaderConfig = {
timeout: timeout,
maxRetry: maxRetry,
retryDelay: retryDelay,
maxRetryDelay: maxRetryDelay
};
var loaderCallbacks = {
onSuccess: this.loadsuccess.bind(this),
onError: this.loaderror.bind(this),
onTimeout: this.loadtimeout.bind(this)
};
logger["b" /* logger */].debug('Calling internal loader delegate for URL: ' + url);
loader.load(context, loaderConfig, loaderCallbacks);
return true;
};
PlaylistLoader.prototype.loadsuccess = function loadsuccess(response, stats, context) {
var networkDetails = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
if (context.isSidxRequest) {
this._handleSidxRequest(response, context);
this._handlePlaylistLoaded(response, stats, context, networkDetails);
return;
}
this.resetInternalLoader(context.type);
var string = response.data;
stats.tload = performance.now();
// stats.mtime = new Date(target.getResponseHeader('Last-Modified'));
// Validate if it is an M3U8 at all
if (string.indexOf('#EXTM3U') !== 0) {
this._handleManifestParsingError(response, context, 'no EXTM3U delimiter', networkDetails);
return;
}
// Check if chunk-list or master. handle empty chunk list case (first EXTINF not signaled, but TARGETDURATION present)
if (string.indexOf('#EXTINF:') > 0 || string.indexOf('#EXT-X-TARGETDURATION:') > 0) {
this._handleTrackOrLevelPlaylist(response, stats, context, networkDetails);
} else {
this._handleMasterPlaylist(response, stats, context, networkDetails);
}
};
PlaylistLoader.prototype.loaderror = function loaderror(response, context) {
var networkDetails = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
this._handleNetworkError(context, networkDetails);
};
PlaylistLoader.prototype.loadtimeout = function loadtimeout(stats, context) {
var networkDetails = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
this._handleNetworkError(context, networkDetails, true);
};
PlaylistLoader.prototype._handleMasterPlaylist = function _handleMasterPlaylist(response, stats, context, networkDetails) {
var hls = this.hls;
var string = response.data;
var url = PlaylistLoader.getResponseUrl(response, context);
var levels = m3u8_parser.parseMasterPlaylist(string, url);
if (!levels.length) {
this._handleManifestParsingError(response, context, 'no level found in manifest', networkDetails);
share/public_html/static/hls.js view on Meta::CPAN
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 };
var start = frag.byteRangeStartOffset,
end = frag.byteRangeEndOffset;
if (!isNaN(start) && !isNaN(end)) {
loaderContext.rangeStart = start;
loaderContext.rangeEnd = end;
}
loaderConfig = {
timeout: config.fragLoadingTimeOut,
maxRetry: 0,
retryDelay: 0,
maxRetryDelay: config.fragLoadingMaxRetryTimeout
};
loaderCallbacks = {
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'
};
share/public_html/static/hls.js view on Meta::CPAN
TaskLoop.prototype.hasNextTick = function hasNextTick() {
return !!this._tickTimer;
};
/**
* @param {number} millis Interval time (ms)
* @returns {boolean} True when interval has been scheduled, false when already scheduled (no effect)
*/
TaskLoop.prototype.setInterval = function (_setInterval) {
function setInterval(_x) {
return _setInterval.apply(this, arguments);
}
setInterval.toString = function () {
return _setInterval.toString();
};
return setInterval;
}(function (millis) {
if (!this._tickInterval) {
this._tickInterval = setInterval(this._boundTick, millis);
return true;
}
return false;
});
/**
* @returns {boolean} True when interval was cleared, false when none was set (no effect)
*/
TaskLoop.prototype.clearInterval = function (_clearInterval) {
function clearInterval() {
return _clearInterval.apply(this, arguments);
}
clearInterval.toString = function () {
return _clearInterval.toString();
};
return clearInterval;
}(function () {
if (this._tickInterval) {
clearInterval(this._tickInterval);
this._tickInterval = null;
return true;
}
return false;
});
/**
* @returns {boolean} True when timeout was cleared, false when none was set (no effect)
*/
TaskLoop.prototype.clearNextTick = function clearNextTick() {
if (this._tickTimer) {
clearTimeout(this._tickTimer);
this._tickTimer = null;
return true;
}
return false;
};
/**
* Will call the subclass doTick implementation in this main loop tick
* or in the next one (via setTimeout(,0)) in case it has already been called
* in this tick (in case this is a re-entrant call).
*/
TaskLoop.prototype.tick = function tick() {
this._tickCallCount++;
if (this._tickCallCount === 1) {
this.doTick();
// re-entrant call to tick from previous doTick call stack
// -> schedule a call on the next main loop iteration to process this task processing request
if (this._tickCallCount > 1) {
// make sure only one timer exists at any time at max
this.clearNextTick();
this._tickTimer = setTimeout(this._boundTick, 0);
}
this._tickCallCount = 0;
}
};
/**
* For subclass to implement task logic
* @abstract
*/
TaskLoop.prototype.doTick = function doTick() {};
return TaskLoop;
}(event_handler);
/* harmony default export */ var task_loop = (TaskLoop);
// CONCATENATED MODULE: ./src/controller/fragment-finders.js
/**
* Calculates the PDT of the next load position.
* bufferEnd in this function is usually the position of the playhead.
* @param {number} [start = 0] - The PTS of the first fragment within the level
* @param {number} [bufferEnd = 0] - The end of the contiguous buffered range the playhead is currently within
* @param {*} levelDetails - An object containing the parsed and computed properties of the currently playing level
* @returns {number} nextPdt - The computed PDT
*/
function calculateNextPDT() {
var start = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var bufferEnd = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var levelDetails = arguments[2];
var pdt = 0;
if (levelDetails.programDateTime) {
var parsedDateInt = Date.parse(levelDetails.programDateTime);
if (!isNaN(parsedDateInt)) {
pdt = bufferEnd * 1000 + parsedDateInt - 1000 * start;
}
}
return pdt;
}
/**
* Finds the first fragment whose endPDT value exceeds the given PDT.
* @param {Array<Fragment>} fragments - The array of candidate fragments
* @param {number|null} [PDTValue = null] - The PDT value which must be exceeded
* @returns {*|null} fragment - The best matching fragment
*/
function findFragmentByPDT(fragments) {
var PDTValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
if (!Array.isArray(fragments) || !fragments.length || PDTValue === null) {
return null;
}
// if less than start
var firstSegment = fragments[0];
if (PDTValue < firstSegment.pdt) {
share/public_html/static/hls.js view on Meta::CPAN
} else {
alternate = true;
}
}
if (alternate && mediaTrack) {
logger["b" /* logger */].log('alternate track found, use ' + name + '.buffered to schedule main fragment loading');
this.mediaBuffer = mediaTrack.buffer;
} else {
this.mediaBuffer = this.media;
}
};
StreamController.prototype.onBufferAppended = function onBufferAppended(data) {
if (data.parent === 'main') {
var state = this.state;
if (state === State.PARSING || state === State.PARSED) {
// check if all buffers have been appended
this.pendingBuffering = data.pending > 0;
this._checkAppendedParsed();
}
}
};
StreamController.prototype._checkAppendedParsed = function _checkAppendedParsed() {
// trigger handler right now
if (this.state === State.PARSED && (!this.appended || !this.pendingBuffering)) {
var frag = this.fragCurrent;
if (frag) {
var media = this.mediaBuffer ? this.mediaBuffer : this.media;
logger["b" /* logger */].log('main buffered : ' + time_ranges.toString(media.buffered));
this.fragPrevious = frag;
var stats = this.stats;
stats.tbuffered = window.performance.now();
// we should get rid of this.fragLastKbps
this.fragLastKbps = Math.round(8 * stats.total / (stats.tbuffered - stats.tfirst));
this.hls.trigger(events["a" /* default */].FRAG_BUFFERED, { stats: stats, frag: frag, id: 'main' });
this.state = State.IDLE;
}
this.tick();
}
};
StreamController.prototype.onError = function onError(data) {
var frag = data.frag || this.fragCurrent;
// don't handle frag error not related to main fragment
if (frag && frag.type !== 'main') {
return;
}
// 0.5 : tolerance needed as some browsers stalls playback before reaching buffered end
var mediaBuffered = !!this.media && BufferHelper.isBuffered(this.media, this.media.currentTime) && BufferHelper.isBuffered(this.media, this.media.currentTime + 0.5);
switch (data.details) {
case errors["a" /* ErrorDetails */].FRAG_LOAD_ERROR:
case errors["a" /* ErrorDetails */].FRAG_LOAD_TIMEOUT:
case errors["a" /* ErrorDetails */].KEY_LOAD_ERROR:
case errors["a" /* ErrorDetails */].KEY_LOAD_TIMEOUT:
if (!data.fatal) {
// keep retrying until the limit will be reached
if (this.fragLoadError + 1 <= this.config.fragLoadingMaxRetry) {
// exponential backoff capped to config.fragLoadingMaxRetryTimeout
var delay = Math.min(Math.pow(2, this.fragLoadError) * this.config.fragLoadingRetryDelay, this.config.fragLoadingMaxRetryTimeout);
logger["b" /* logger */].warn('mediaController: frag loading failed, retry in ' + delay + ' ms');
this.retryDate = window.performance.now() + delay;
// retry loading state
// if loadedmetadata is not set, it means that we are emergency switch down on first frag
// in that case, reset startFragRequested flag
if (!this.loadedmetadata) {
this.startFragRequested = false;
this.nextLoadPosition = this.startPosition;
}
this.fragLoadError++;
this.state = State.FRAG_LOADING_WAITING_RETRY;
} else {
logger["b" /* logger */].error('mediaController: ' + data.details + ' reaches max retry, redispatch as fatal ...');
// switch error to fatal
data.fatal = true;
this.state = State.ERROR;
}
}
break;
case errors["a" /* ErrorDetails */].LEVEL_LOAD_ERROR:
case errors["a" /* ErrorDetails */].LEVEL_LOAD_TIMEOUT:
if (this.state !== State.ERROR) {
if (data.fatal) {
// if fatal error, stop processing
this.state = State.ERROR;
logger["b" /* logger */].warn('streamController: ' + data.details + ',switch to ' + this.state + ' state ...');
} else {
// in case of non fatal error while loading level, if level controller is not retrying to load level , switch back to IDLE
if (!data.levelRetry && this.state === State.WAITING_LEVEL) {
this.state = State.IDLE;
}
}
}
break;
case errors["a" /* ErrorDetails */].BUFFER_FULL_ERROR:
// if in appending state
if (data.parent === 'main' && (this.state === State.PARSING || this.state === State.PARSED)) {
// reduce max buf len if current position is buffered
if (mediaBuffered) {
this._reduceMaxBufferLength(this.config.maxBufferLength);
this.state = State.IDLE;
} else {
// current position is not buffered, but browser is still complaining about buffer full error
// this happens on IE/Edge, refer to https://github.com/video-dev/hls.js/pull/708
// in that case flush the whole buffer to recover
logger["b" /* logger */].warn('buffer full error also media.currentTime is not buffered, flush everything');
this.fragCurrent = null;
// flush everything
this.flushMainBuffer(0, Number.POSITIVE_INFINITY);
}
}
break;
default:
break;
}
};
StreamController.prototype._reduceMaxBufferLength = function _reduceMaxBufferLength(minLength) {
var config = this.config;
if (config.maxMaxBufferLength >= minLength) {
share/public_html/static/hls.js view on Meta::CPAN
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) {
this.loadLevel();
}
};
LevelController.prototype.stopLoad = function stopLoad() {
this.canload = false;
};
LevelController.prototype.onManifestLoaded = function onManifestLoaded(data) {
var levels = [];
var bitrateStart = void 0;
var levelSet = {};
var levelFromSet = null;
var videoCodecFound = false;
var audioCodecFound = false;
var chromeOrFirefox = /chrome|firefox/.test(navigator.userAgent.toLowerCase());
var audioTracks = [];
// regroup redundant levels together
data.levels.forEach(function (level) {
level.loadError = 0;
level.fragmentError = false;
videoCodecFound = videoCodecFound || !!level.videoCodec;
audioCodecFound = audioCodecFound || !!level.audioCodec || !!(level.attrs && level.attrs.AUDIO);
// erase audio codec info if browser does not support mp4a.40.34.
// demuxer will autodetect codec and fallback to mpeg/audio
if (chromeOrFirefox && level.audioCodec && level.audioCodec.indexOf('mp4a.40.34') !== -1) {
level.audioCodec = undefined;
}
levelFromSet = levelSet[level.bitrate]; // FIXME: we would also have to match the resolution here
if (!levelFromSet) {
level.url = [level.url];
level.urlId = 0;
levelSet[level.bitrate] = level;
share/public_html/static/hls.js view on Meta::CPAN
}
var levelError = false,
fragmentError = false;
var levelIndex = void 0;
// try to recover not fatal errors
switch (data.details) {
case errors["a" /* ErrorDetails */].FRAG_LOAD_ERROR:
case errors["a" /* ErrorDetails */].FRAG_LOAD_TIMEOUT:
case errors["a" /* ErrorDetails */].KEY_LOAD_ERROR:
case errors["a" /* ErrorDetails */].KEY_LOAD_TIMEOUT:
levelIndex = data.frag.level;
fragmentError = true;
break;
case errors["a" /* ErrorDetails */].LEVEL_LOAD_ERROR:
case errors["a" /* ErrorDetails */].LEVEL_LOAD_TIMEOUT:
levelIndex = data.context.level;
levelError = true;
break;
case errors["a" /* ErrorDetails */].REMUX_ALLOC_ERROR:
levelIndex = data.level;
levelError = true;
break;
}
if (levelIndex !== undefined) {
this.recoverLevel(data, levelIndex, levelError, fragmentError);
}
};
/**
* Switch to a redundant stream if any available.
* If redundant stream is not available, emergency switch down if ABR mode is enabled.
*
* @param {Object} errorEvent
* @param {Number} levelIndex current level index
* @param {Boolean} levelError
* @param {Boolean} fragmentError
*/
// FIXME Find a better abstraction where fragment/level retry management is well decoupled
LevelController.prototype.recoverLevel = function recoverLevel(errorEvent, levelIndex, levelError, fragmentError) {
var _this2 = this;
var config = this.hls.config;
var errorDetails = errorEvent.details;
var level = this._levels[levelIndex];
var redundantLevels = void 0,
delay = void 0,
nextLevel = void 0;
level.loadError++;
level.fragmentError = fragmentError;
if (levelError) {
if (this.levelRetryCount + 1 <= config.levelLoadingMaxRetry) {
// exponential backoff capped to max retry timeout
delay = Math.min(Math.pow(2, this.levelRetryCount) * config.levelLoadingRetryDelay, config.levelLoadingMaxRetryTimeout);
// Schedule level reload
this.timer = setTimeout(function () {
return _this2.loadLevel();
}, delay);
// boolean used to inform stream controller not to switch back to IDLE on non fatal error
errorEvent.levelRetry = true;
this.levelRetryCount++;
logger["b" /* logger */].warn('level controller, ' + errorDetails + ', retry in ' + delay + ' ms, current retry count is ' + this.levelRetryCount);
} else {
logger["b" /* logger */].error('level controller, cannot recover from ' + errorDetails + ' error');
this.currentLevelIndex = null;
// stopping live reloading timer if any
this.clearTimer();
// switch error to fatal
errorEvent.fatal = true;
return;
}
}
// Try any redundant streams if available for both errors: level and fragment
// If level.loadError reaches redundantLevels it means that we tried them all, no hope => let's switch down
if (levelError || fragmentError) {
redundantLevels = level.url.length;
if (redundantLevels > 1 && level.loadError < redundantLevels) {
level.urlId = (level.urlId + 1) % redundantLevels;
level.details = undefined;
logger["b" /* logger */].warn('level controller, ' + errorDetails + ' for level ' + levelIndex + ': switching to redundant URL-id ' + level.urlId);
// console.log('Current audio track group ID:', this.hls.audioTracks[this.hls.audioTrack].groupId);
// console.log('New video quality level audio group id:', level.attrs.AUDIO);
} else {
// Search for available level
if (this.manualLevelIndex === -1) {
// When lowest level has been reached, let's start hunt from the top
nextLevel = levelIndex === 0 ? this._levels.length - 1 : levelIndex - 1;
logger["b" /* logger */].warn('level controller, ' + errorDetails + ': switch to ' + nextLevel);
this.hls.nextAutoLevel = this.currentLevelIndex = nextLevel;
} else if (fragmentError) {
// Allow fragment retry as long as configuration allows.
// reset this._level so that another call to set level() will trigger again a frag load
logger["b" /* logger */].warn('level controller, ' + errorDetails + ': reload a fragment');
this.currentLevelIndex = null;
}
}
}
};
// reset errors on the successful load of a fragment
LevelController.prototype.onFragLoaded = function onFragLoaded(_ref3) {
var frag = _ref3.frag;
if (frag !== undefined && frag.type === 'main') {
var level = this._levels[frag.level];
if (level !== undefined) {
level.fragmentError = false;
level.loadError = 0;
this.levelRetryCount = 0;
}
}
};
LevelController.prototype.onLevelLoaded = function onLevelLoaded(data) {
var _this3 = this;
var levelId = data.level;
// only process level loaded events matching with expected level
if (levelId !== this.currentLevelIndex) {
return;
}
var curLevel = this._levels[levelId];
// reset level load error counter on successful level loaded only if there is no issues with fragments
if (!curLevel.fragmentError) {
curLevel.loadError = 0;
this.levelRetryCount = 0;
}
var newDetails = data.details;
// if current playlist is a live playlist, arm a timer to reload it
if (newDetails.live) {
var targetdurationMs = 1000 * (newDetails.averagetargetduration ? newDetails.averagetargetduration : newDetails.targetduration);
var reloadInterval = targetdurationMs,
curDetails = curLevel.details;
if (curDetails && newDetails.endSN === curDetails.endSN) {
// follow HLS Spec, If the client reloads a Playlist file and finds that it has not
// changed then it MUST wait for a period of one-half the target
// duration before retrying.
reloadInterval /= 2;
logger["b" /* logger */].log('same live playlist, reload twice faster');
}
// decrement reloadInterval with level loading delay
reloadInterval -= level_controller_performance.now() - data.stats.trequest;
// in any case, don't reload more than half of target duration
reloadInterval = Math.max(targetdurationMs / 2, Math.round(reloadInterval));
logger["b" /* logger */].log('live playlist, reload in ' + Math.round(reloadInterval) + ' ms');
this.timer = setTimeout(function () {
return _this3.loadLevel();
}, reloadInterval);
} else {
this.clearTimer();
}
};
LevelController.prototype.onAudioTrackSwitched = function onAudioTrackSwitched(data) {
var audioGroupId = this.hls.audioTracks[data.id].groupId;
var currentLevel = this.hls.levels[this.currentLevelIndex];
if (!currentLevel) {
return;
}
if (currentLevel.audioGroupIds) {
var urlId = currentLevel.audioGroupIds.findIndex(function (groupId) {
return groupId === audioGroupId;
});
if (urlId !== currentLevel.urlId) {
currentLevel.urlId = urlId;
this.startLoad();
}
}
};
LevelController.prototype.loadLevel = function loadLevel() {
logger["b" /* logger */].debug('call to loadLevel');
if (this.currentLevelIndex !== null && this.canload) {
var levelObject = this._levels[this.currentLevelIndex];
if ((typeof levelObject === 'undefined' ? 'undefined' : level_controller__typeof(levelObject)) === 'object' && levelObject.url.length > 0) {
var level = this.currentLevelIndex;
var id = levelObject.urlId;
var url = levelObject.url[id];
logger["b" /* logger */].log('Attempt loading level index ' + level + ' with URL-id ' + id);
// console.log('Current audio track group ID:', this.hls.audioTracks[this.hls.audioTrack].groupId);
// console.log('New video quality level audio group id:', levelObject.attrs.AUDIO, level);
this.hls.trigger(events["a" /* default */].LEVEL_LOADING, { url: url, level: level, id: id });
}
}
};
level_controller__createClass(LevelController, [{
key: 'levels',
get: function get() {
return this._levels;
}
}, {
key: 'level',
get: function get() {
return this.currentLevelIndex;
},
set: function set(newLevel) {
var levels = this._levels;
if (levels) {
share/public_html/static/hls.js view on Meta::CPAN
}
}
}
}
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);
share/public_html/static/hls.js view on Meta::CPAN
AudioStreamController.prototype.onBufferAppended = function onBufferAppended(data) {
if (data.parent === 'audio') {
var state = this.state;
if (state === audio_stream_controller_State.PARSING || state === audio_stream_controller_State.PARSED) {
// check if all buffers have been appended
this.pendingBuffering = data.pending > 0;
this._checkAppendedParsed();
}
}
};
AudioStreamController.prototype._checkAppendedParsed = function _checkAppendedParsed() {
// trigger handler right now
if (this.state === audio_stream_controller_State.PARSED && (!this.appended || !this.pendingBuffering)) {
var frag = this.fragCurrent,
stats = this.stats,
hls = this.hls;
if (frag) {
this.fragPrevious = frag;
stats.tbuffered = audio_stream_controller_performance.now();
hls.trigger(events["a" /* default */].FRAG_BUFFERED, { stats: stats, frag: frag, id: 'audio' });
var media = this.mediaBuffer ? this.mediaBuffer : this.media;
logger["b" /* logger */].log('audio buffered : ' + time_ranges.toString(media.buffered));
if (this.audioSwitch && this.appended) {
this.audioSwitch = false;
hls.trigger(events["a" /* default */].AUDIO_TRACK_SWITCHED, { id: this.trackId });
}
this.state = audio_stream_controller_State.IDLE;
}
this.tick();
}
};
AudioStreamController.prototype.onError = function onError(data) {
var frag = data.frag;
// don't handle frag error not related to audio fragment
if (frag && frag.type !== 'audio') {
return;
}
switch (data.details) {
case errors["a" /* ErrorDetails */].FRAG_LOAD_ERROR:
case errors["a" /* ErrorDetails */].FRAG_LOAD_TIMEOUT:
var _frag = data.frag;
// don't handle frag error not related to audio fragment
if (_frag && _frag.type !== 'audio') {
break;
}
if (!data.fatal) {
var loadError = this.fragLoadError;
if (loadError) {
loadError++;
} else {
loadError = 1;
}
var config = this.config;
if (loadError <= config.fragLoadingMaxRetry) {
this.fragLoadError = loadError;
// exponential backoff capped to config.fragLoadingMaxRetryTimeout
var delay = Math.min(Math.pow(2, loadError - 1) * config.fragLoadingRetryDelay, config.fragLoadingMaxRetryTimeout);
logger["b" /* logger */].warn('AudioStreamController: frag loading failed, retry in ' + delay + ' ms');
this.retryDate = audio_stream_controller_performance.now() + delay;
// retry loading state
this.state = audio_stream_controller_State.FRAG_LOADING_WAITING_RETRY;
} else {
logger["b" /* logger */].error('AudioStreamController: ' + data.details + ' reaches max retry, redispatch as fatal ...');
// switch error to fatal
data.fatal = true;
this.state = audio_stream_controller_State.ERROR;
}
}
break;
case errors["a" /* ErrorDetails */].AUDIO_TRACK_LOAD_ERROR:
case errors["a" /* ErrorDetails */].AUDIO_TRACK_LOAD_TIMEOUT:
case errors["a" /* ErrorDetails */].KEY_LOAD_ERROR:
case errors["a" /* ErrorDetails */].KEY_LOAD_TIMEOUT:
// when in ERROR state, don't switch back to IDLE state in case a non-fatal error is received
if (this.state !== audio_stream_controller_State.ERROR) {
// if fatal error, stop processing, otherwise move to IDLE to retry loading
this.state = data.fatal ? audio_stream_controller_State.ERROR : audio_stream_controller_State.IDLE;
logger["b" /* logger */].warn('AudioStreamController: ' + data.details + ' while loading frag, now switching to ' + this.state + ' state ...');
}
break;
case errors["a" /* ErrorDetails */].BUFFER_FULL_ERROR:
// if in appending state
if (data.parent === 'audio' && (this.state === audio_stream_controller_State.PARSING || this.state === audio_stream_controller_State.PARSED)) {
var media = this.mediaBuffer,
currentTime = this.media.currentTime,
mediaBuffered = media && BufferHelper.isBuffered(media, currentTime) && BufferHelper.isBuffered(media, currentTime + 0.5);
// reduce max buf len if current position is buffered
if (mediaBuffered) {
var _config = this.config;
if (_config.maxMaxBufferLength >= _config.maxBufferLength) {
// reduce max buffer length as it might be too high. we do this to avoid loop flushing ...
_config.maxMaxBufferLength /= 2;
logger["b" /* logger */].warn('AudioStreamController: reduce max buffer length to ' + _config.maxMaxBufferLength + 's');
}
this.state = audio_stream_controller_State.IDLE;
} else {
// current position is not buffered, but browser is still complaining about buffer full error
// this happens on IE/Edge, refer to https://github.com/video-dev/hls.js/pull/708
// in that case flush the whole audio buffer to recover
logger["b" /* logger */].warn('AudioStreamController: buffer full error also media.currentTime is not buffered, flush audio buffer');
this.fragCurrent = null;
// flush everything
this.state = audio_stream_controller_State.BUFFER_FLUSHING;
this.hls.trigger(events["a" /* default */].BUFFER_FLUSHING, { startOffset: 0, endOffset: Number.POSITIVE_INFINITY, type: 'audio' });
}
}
break;
default:
break;
}
};
AudioStreamController.prototype.onBufferFlushed = function onBufferFlushed() {
var _this3 = this;
var pendingData = this.pendingData;
if (pendingData && pendingData.length) {
share/public_html/static/hls.js view on Meta::CPAN
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
liveSyncDurationCount: 3, // used by stream-controller
liveMaxLatencyDurationCount: Infinity, // used by stream-controller
liveSyncDuration: undefined, // used by stream-controller
liveMaxLatencyDuration: undefined, // used by stream-controller
liveDurationInfinity: false, // used by buffer-controller
maxMaxBufferLength: 600, // used by stream-controller
enableWorker: true, // used by demuxer
enableSoftwareAES: true, // used by decrypter
manifestLoadingTimeOut: 10000, // used by playlist-loader
manifestLoadingMaxRetry: 1, // used by playlist-loader
manifestLoadingRetryDelay: 1000, // used by playlist-loader
manifestLoadingMaxRetryTimeout: 64000, // used by playlist-loader
startLevel: undefined, // used by level-controller
levelLoadingTimeOut: 10000, // used by playlist-loader
levelLoadingMaxRetry: 4, // used by playlist-loader
levelLoadingRetryDelay: 1000, // used by playlist-loader
levelLoadingMaxRetryTimeout: 64000, // used by playlist-loader
fragLoadingTimeOut: 20000, // used by fragment-loader
fragLoadingMaxRetry: 6, // used by fragment-loader
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"); } }
( run in 1.726 second using v1.01-cache-2.11-cpan-39bf76dae61 )