2020-01-20 12:50:03 +03:00
|
|
|
/*
|
|
|
|
AUTHOR
|
|
|
|
Trek Hopton <trek@ausocean.org>
|
|
|
|
|
|
|
|
LICENSE
|
|
|
|
This file is Copyright (C) 2020 the Australian Ocean Lab (AusOcean)
|
|
|
|
|
|
|
|
It is free software: you can redistribute it and/or modify them
|
|
|
|
under the terms of the GNU General Public License as published by the
|
|
|
|
Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
option) any later version.
|
|
|
|
|
|
|
|
It is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License in gpl.txt.
|
|
|
|
If not, see http://www.gnu.org/licenses.
|
|
|
|
|
|
|
|
For hls.js Copyright notice and license, see LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2020-01-02 11:06:52 +03:00
|
|
|
/*
|
|
|
|
* Fragment Loader
|
|
|
|
*/
|
|
|
|
|
2020-01-20 12:50:03 +03:00
|
|
|
import Event from '../events.js';
|
|
|
|
import EventHandler from '../event-handler.js';
|
2020-01-02 11:06:52 +03:00
|
|
|
|
|
|
|
class FragmentLoader extends EventHandler {
|
2020-01-20 12:50:03 +03:00
|
|
|
constructor(hls) {
|
2020-01-02 11:06:52 +03:00
|
|
|
super(hls, Event.FRAG_LOADING);
|
|
|
|
this.loaders = {};
|
|
|
|
}
|
|
|
|
|
2020-01-20 12:50:03 +03:00
|
|
|
destroy() {
|
2020-01-02 11:06:52 +03:00
|
|
|
let loaders = this.loaders;
|
|
|
|
for (let loaderName in loaders) {
|
|
|
|
let loader = loaders[loaderName];
|
|
|
|
if (loader) {
|
|
|
|
loader.destroy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.loaders = {};
|
|
|
|
|
|
|
|
super.destroy();
|
|
|
|
}
|
|
|
|
|
2020-01-20 12:50:03 +03:00
|
|
|
onFragLoading(data) {
|
2020-01-02 11:06:52 +03:00
|
|
|
const 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;
|
|
|
|
|
|
|
|
let loader = loaders[type];
|
|
|
|
if (loader) {
|
2020-01-20 12:50:03 +03:00
|
|
|
console.warn(`abort previous fragment loader for type: ${type}`);
|
2020-01-02 11:06:52 +03:00
|
|
|
loader.abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
loader = loaders[type] = frag.loader =
|
|
|
|
config.fLoader ? new FragmentILoader(config) : new DefaultILoader(config);
|
|
|
|
|
|
|
|
let loaderContext, loaderConfig, loaderCallbacks;
|
|
|
|
|
|
|
|
loaderContext = { url: frag.url, frag: frag, responseType: 'arraybuffer', progressData: false };
|
|
|
|
|
|
|
|
let start = frag.byteRangeStartOffset,
|
|
|
|
end = frag.byteRangeEndOffset;
|
|
|
|
|
|
|
|
if (Number.isFinite(start) && Number.isFinite(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);
|
|
|
|
}
|
|
|
|
|
2020-01-20 12:50:03 +03:00
|
|
|
loadsuccess(response, stats, context, networkDetails = null) {
|
2020-01-02 11:06:52 +03:00
|
|
|
let payload = response.data, frag = context.frag;
|
|
|
|
// detach fragment loader on load success
|
|
|
|
frag.loader = undefined;
|
|
|
|
this.loaders[frag.type] = undefined;
|
|
|
|
this.hls.trigger(Event.FRAG_LOADED, { payload: payload, frag: frag, stats: stats, networkDetails: networkDetails });
|
|
|
|
}
|
|
|
|
|
2020-01-20 12:50:03 +03:00
|
|
|
loaderror(response, context, networkDetails = null) {
|
2020-01-02 11:06:52 +03:00
|
|
|
const frag = context.frag;
|
|
|
|
let loader = frag.loader;
|
|
|
|
if (loader) {
|
|
|
|
loader.abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.loaders[frag.type] = undefined;
|
|
|
|
this.hls.trigger(Event.ERROR, { type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.FRAG_LOAD_ERROR, fatal: false, frag: context.frag, response: response, networkDetails: networkDetails });
|
|
|
|
}
|
|
|
|
|
2020-01-20 12:50:03 +03:00
|
|
|
loadtimeout(stats, context, networkDetails = null) {
|
2020-01-02 11:06:52 +03:00
|
|
|
const frag = context.frag;
|
|
|
|
let loader = frag.loader;
|
|
|
|
if (loader) {
|
|
|
|
loader.abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
this.loaders[frag.type] = undefined;
|
|
|
|
this.hls.trigger(Event.ERROR, { type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.FRAG_LOAD_TIMEOUT, fatal: false, frag: context.frag, networkDetails: networkDetails });
|
|
|
|
}
|
|
|
|
|
|
|
|
// data will be used for progressive parsing
|
2020-01-20 12:50:03 +03:00
|
|
|
loadprogress(stats, context, data, networkDetails = null) { // jshint ignore:line
|
2020-01-02 11:06:52 +03:00
|
|
|
let frag = context.frag;
|
|
|
|
frag.loaded = stats.loaded;
|
|
|
|
this.hls.trigger(Event.FRAG_LOAD_PROGRESS, { frag: frag, stats: stats, networkDetails: networkDetails });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default FragmentLoader;
|