2020-01-02 11:06:52 +03:00
|
|
|
/*
|
2020-01-20 13:01:23 +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
|
|
|
*/
|
|
|
|
|
2020-01-20 13:01:23 +03:00
|
|
|
/*
|
|
|
|
* Stream Controller
|
|
|
|
*/
|
2020-01-02 11:06:52 +03:00
|
|
|
|
2020-01-20 13:01:23 +03:00
|
|
|
import Event from '../events.js';
|
|
|
|
import EventHandler from '../event-handler.js';
|
2020-01-02 11:06:52 +03:00
|
|
|
|
2020-01-20 13:01:23 +03:00
|
|
|
class StreamController extends EventHandler {
|
|
|
|
constructor(hls) {
|
2020-01-02 11:06:52 +03:00
|
|
|
super(hls,
|
|
|
|
Event.LEVEL_LOADED,
|
2020-01-20 13:01:23 +03:00
|
|
|
Event.FRAG_LOADED);
|
|
|
|
this.hls = hls;
|
2020-01-02 11:06:52 +03:00
|
|
|
this.config = hls.config;
|
|
|
|
this.audioCodecSwap = false;
|
|
|
|
this.stallReported = false;
|
|
|
|
this.gapController = null;
|
2020-01-20 13:01:23 +03:00
|
|
|
this.currentFrag = 0;
|
2020-01-02 11:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-01-20 13:01:23 +03:00
|
|
|
_fetchPayloadOrEos(levelDetails) {
|
|
|
|
this.fragments = levelDetails.fragments;
|
|
|
|
this._loadFragment();
|
2020-01-02 11:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-01-20 13:01:23 +03:00
|
|
|
_loadFragment() {
|
|
|
|
let fragLen = this.fragments.length;
|
|
|
|
if (this.currentFrag >= fragLen) {
|
2020-01-02 11:06:52 +03:00
|
|
|
return;
|
|
|
|
}
|
2020-01-20 13:01:23 +03:00
|
|
|
this.hls.trigger(Event.FRAG_LOADING, { frag: this.fragments[this.currentFrag++] });
|
2020-01-02 11:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-01-20 13:01:23 +03:00
|
|
|
onLevelLoaded(data) {
|
2020-01-02 11:06:52 +03:00
|
|
|
const newDetails = data.details;
|
|
|
|
const newLevelId = data.level;
|
2020-01-20 13:01:23 +03:00
|
|
|
const levelDetails = data.details;
|
2020-01-02 11:06:52 +03:00
|
|
|
const duration = newDetails.totalduration;
|
|
|
|
let sliding = 0;
|
|
|
|
|
2020-01-20 13:01:23 +03:00
|
|
|
console.log(`level ${newLevelId} loaded [${newDetails.startSN},${newDetails.endSN}],duration:${duration}`);
|
2020-01-02 11:06:52 +03:00
|
|
|
|
|
|
|
if (newDetails.live) {
|
2020-01-20 13:01:23 +03:00
|
|
|
console.log("handling of this case is not implemented");
|
2020-01-02 11:06:52 +03:00
|
|
|
} else {
|
|
|
|
newDetails.PTSKnown = false;
|
|
|
|
}
|
|
|
|
// override level info
|
|
|
|
this.levelLastLoaded = newLevelId;
|
|
|
|
this.hls.trigger(Event.LEVEL_UPDATED, { details: newDetails, level: newLevelId });
|
|
|
|
|
|
|
|
if (this.startFragRequested === false) {
|
2020-01-20 13:01:23 +03:00
|
|
|
// compute start position if set to -1. use it straight away if value is defined
|
2020-01-02 11:06:52 +03:00
|
|
|
if (this.startPosition === -1 || this.lastCurrentTime === -1) {
|
|
|
|
// first, check if start time offset has been set in playlist, if yes, use this value
|
|
|
|
let startTimeOffset = newDetails.startTimeOffset;
|
|
|
|
if (Number.isFinite(startTimeOffset)) {
|
|
|
|
if (startTimeOffset < 0) {
|
2020-01-20 13:01:23 +03:00
|
|
|
console.log(`negative start time offset ${startTimeOffset}, count from end of last fragment`);
|
2020-01-02 11:06:52 +03:00
|
|
|
startTimeOffset = sliding + duration + startTimeOffset;
|
|
|
|
}
|
2020-01-20 13:01:23 +03:00
|
|
|
console.log(`start time offset found in playlist, adjust startPosition to ${startTimeOffset}`);
|
2020-01-02 11:06:52 +03:00
|
|
|
this.startPosition = startTimeOffset;
|
|
|
|
} else {
|
|
|
|
// if live playlist, set start position to be fragment N-this.config.liveSyncDurationCount (usually 3)
|
|
|
|
if (newDetails.live) {
|
2020-01-20 13:01:23 +03:00
|
|
|
console.log("handling of this case is not implemented");
|
2020-01-02 11:06:52 +03:00
|
|
|
} else {
|
|
|
|
this.startPosition = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.lastCurrentTime = this.startPosition;
|
|
|
|
}
|
|
|
|
this.nextLoadPosition = this.startPosition;
|
|
|
|
}
|
|
|
|
|
2020-01-20 13:01:23 +03:00
|
|
|
this._fetchPayloadOrEos(levelDetails);
|
2020-01-02 11:06:52 +03:00
|
|
|
}
|
|
|
|
|
2020-01-20 13:01:23 +03:00
|
|
|
onFragLoaded(data) {
|
|
|
|
this.hls.loadSuccess(data.payload);
|
|
|
|
this._loadFragment();
|
2020-01-02 11:06:52 +03:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
export default StreamController;
|