update shared components
This commit is contained in:
parent
fb269362ff
commit
71811cb9e3
221 changed files with 32936 additions and 101 deletions
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "hls.js",
|
||||
"version": "0.5.8",
|
||||
"version": "0.5.9",
|
||||
"license": "Apache-2.0",
|
||||
"description": "Media Source Extension - HLS library, by/for Dailymotion",
|
||||
"homepage": "https://github.com/dailymotion/hls.js",
|
||||
|
@ -16,11 +16,11 @@
|
|||
"test",
|
||||
"tests"
|
||||
],
|
||||
"_release": "0.5.8",
|
||||
"_release": "0.5.9",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v0.5.8",
|
||||
"commit": "688cec5b83fc596fb91944ad4934ae84ee40abb9"
|
||||
"tag": "v0.5.9",
|
||||
"commit": "b1579c58d1893c0b64ec7cd59973fea0581c3256"
|
||||
},
|
||||
"_source": "git://github.com/dailymotion/hls.js.git",
|
||||
"_target": "~0.5.7",
|
||||
|
|
29
dashboard-ui/bower_components/hls.js/API.md
vendored
29
dashboard-ui/bower_components/hls.js/API.md
vendored
|
@ -257,7 +257,7 @@ this is the guaranteed buffer length hls.js will try to reach, regardless of max
|
|||
#### ```maxBufferHole```
|
||||
(default 0.3s)
|
||||
|
||||
'maximum' inter-fragment buffer hole tolerance that hls.js can cope with.
|
||||
'maximum' inter-fragment buffer hole tolerance that hls.js can cope with when searching for the next fragment to load.
|
||||
When switching between quality level, fragments might not be perfectly aligned.
|
||||
This could result in small overlapping or hole in media buffer. This tolerance factor helps cope with this.
|
||||
|
||||
|
@ -295,6 +295,23 @@ if set to 10, the player will seek back to ```liveSyncDurationCount``` whenever
|
|||
If set, this value must be stricly superior to ```liveSyncDurationCount```
|
||||
a value too close from ```liveSyncDurationCount``` is likely to cause playback stalls.
|
||||
|
||||
#### ```liveSyncDuration```
|
||||
(default undefined)
|
||||
|
||||
Alternative parameter to ```liveSyncDurationCount```, expressed in seconds vs number of segments.
|
||||
If defined in the configuration object, ```liveSyncDuration``` will take precedence over the default```liveSyncDurationCount```.
|
||||
You can't define this parameter and either ```liveSyncDurationCount``` or ```liveMaxLatencyDurationCount``` in your configuration object at the same time.
|
||||
A value too low (inferior to ~3 segment durations) is likely to cause playback stalls.
|
||||
|
||||
#### ```liveMaxLatencyDuration```
|
||||
(default undefined)
|
||||
|
||||
Alternative parameter to ```liveMaxLatencyDurationCount```, expressed in seconds vs number of segments.
|
||||
If defined in the configuration object, ```liveMaxLatencyDuration``` will take precedence over the default```liveMaxLatencyDurationCount```.
|
||||
If set, this value must be stricly superior to ```liveSyncDuration``` which must be defined as well.
|
||||
You can't define this parameter and either ```liveSyncDurationCount``` or ```liveMaxLatencyDurationCount``` in your configuration object at the same time.
|
||||
A value too close from ```liveSyncDuration``` is likely to cause playback stalls.
|
||||
|
||||
#### ```enableWorker```
|
||||
(default true)
|
||||
|
||||
|
@ -603,9 +620,15 @@ full list of Errors is described below:
|
|||
- ```Hls.ErrorDetails.FRAG_PARSING_ERROR```raised when fragment parsing fails
|
||||
- data: { type : ```NETWORK_ERROR```, details : ```Hls.ErrorDetails.FRAG_PARSING_ERROR```, fatal : ```true/false```, reason : failure reason}
|
||||
- ```Hls.ErrorDetails.BUFFER_APPEND_ERROR```raised when exception is raised while calling buffer append
|
||||
- data: { type : ```NETWORK_ERROR```, details : ```Hls.ErrorDetails.BUFFER_APPEND_ERROR```, fatal : ```true```, frag : fragment object}
|
||||
- data: { type : ```MEDIA_ERROR```, details : ```Hls.ErrorDetails.BUFFER_APPEND_ERROR```, fatal : ```true```, frag : fragment object}
|
||||
- ```Hls.ErrorDetails.BUFFER_APPENDING_ERROR```raised when exception is raised during buffer appending
|
||||
- data: { type : ```NETWORK_ERROR```, details : ```Hls.ErrorDetails.BUFFER_APPENDING_ERROR```, fatal : ```false```, frag : fragment object}
|
||||
- data: { type : ```MEDIA_ERROR```, details : ```Hls.ErrorDetails.BUFFER_APPENDING_ERROR```, fatal : ```false```}
|
||||
- ```Hls.ErrorDetails.BUFFER_STALLED_ERROR```raised when playback is stuck because buffer is running out of data
|
||||
- data: { type : ```MEDIA_ERROR```, details : ```Hls.ErrorDetails.BUFFER_STALLED_ERROR```, fatal : ```false```}
|
||||
- ```Hls.ErrorDetails.BUFFER_FULL_ERROR```raised when no data can be appended anymore in media buffer because it is full. this error is recovered automatically by performing a smooth level switching that empty buffers (without disrupting the playback) and reducing the max buffer length.
|
||||
- data: { type : ```MEDIA_ERROR```, details : ```Hls.ErrorDetails.BUFFER_FULL_ERROR```, fatal : ```false```}
|
||||
- ```Hls.ErrorDetails.BUFFER_SEEK_OVER_HOLE```raised after hls.js seeks over a buffer hole to unstuck the playback,
|
||||
- data: { type : ```MEDIA_ERROR```, details : ```Hls.ErrorDetails.BUFFER_SEEK_OVER_HOLE```, fatal : ```false```}
|
||||
|
||||
## Objects
|
||||
### Level
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "hls.js",
|
||||
"version": "0.5.8",
|
||||
"version": "0.5.9",
|
||||
"license": "Apache-2.0",
|
||||
"description": "Media Source Extension - HLS library, by/for Dailymotion",
|
||||
"homepage": "https://github.com/dailymotion/hls.js",
|
||||
|
|
18
dashboard-ui/bower_components/hls.js/design.md
vendored
18
dashboard-ui/bower_components/hls.js/design.md
vendored
|
@ -14,23 +14,27 @@ design idea is pretty simple :
|
|||
- [src/errors.js][]
|
||||
- definition of Hls.ErrorTypes and Hls.ErrorDetails
|
||||
- [src/controller/stream-controller.js][]
|
||||
- in charge of:
|
||||
- ensuring that buffer is filled as per defined quality selection logic.
|
||||
- stream controller actions are scheduled by a tick timer (invoked every 100ms) and actions are controlled by a state machine.
|
||||
- stream controller is in charge of:
|
||||
- **ensuring that buffer is filled as per defined quality selection logic**.
|
||||
- if buffer is not filled up appropriately (i.e. as per defined maximum buffer size, or as per defined quality level), buffer controller will trigger the following actions:
|
||||
- retrieve "not buffered" media position greater then current playback position. this is performed by comparing video.buffered and video.currentTime.
|
||||
- if there are holes in video.buffered, smaller than config.maxBufferHole, they will be ignored.
|
||||
- retrieve URL of fragment matching with this media position, and appropriate quality level
|
||||
- trigger FRAG_LOADING event
|
||||
- monitor fragment loading speed (by monitoring data received from FRAG_LOAD_PROGRESS event)
|
||||
- **monitor fragment loading speed** (by monitoring data received from FRAG_LOAD_PROGRESS event)
|
||||
- "expected time of fragment load completion" is computed using "fragment loading instant bandwidth".
|
||||
- this time is compared to the "expected time of buffer starvation".
|
||||
- if we have less than 2 fragments buffered and if "expected time of fragment load completion" is bigger than "expected time of buffer starvation" and also bigger than duration needed to load fragment at next quality level (determined by auto quality switch algorithm), current fragment loading is aborted, and an emergency switch down is triggered.
|
||||
- trigger fragment demuxing on FRAG_LOADED
|
||||
- if we have less than 2 fragments buffered and if "expected time of fragment load completion" is bigger than "expected time of buffer starvation" and also bigger than duration needed to load fragment at next quality level (determined by auto quality switch algorithm), current fragment loading is aborted, stream-controller will **trigger an emergency switch down**.
|
||||
- **trigger fragment demuxing** on FRAG_LOADED
|
||||
- trigger BUFFER_RESET on MANIFEST_PARSED or startLoad()
|
||||
- trigger BUFFER_CODECS on FRAG_PARSING_INIT_SEGMENT
|
||||
- trigger BUFFER_APPENDING on FRAG_PARSING_DATA
|
||||
- once FRAG_PARSED is received an all segments have been appended (BUFFER_APPENDED) then buffer controller will recheck whether it needs to buffer more data.
|
||||
- monitor current playback quality level (buffer controller maintains a map between media position and quality level)
|
||||
stream controller actions are scheduled by a tick timer (invoked every 100ms) and actions are controlled by a state machine.
|
||||
- **monitor current playback quality level** (buffer controller maintains a map between media position and quality level)
|
||||
- **monitor playback progress** : if playhead is not moving anymore although it should (video metadata is known and video is not ended, nor paused, nor in seeking state) and if we have less than 400ms buffered upfront, and if there is a new buffer range available upfront, less than config.maxSeekHole from currentTime, then hls.js will **jump over the buffer hole** and seek to the beginning of this new buffered range, to "unstuck" the playback.
|
||||
400 ms is a "magic number" that has been set to overcome browsers not always stopping playback at the exact end of a buffered range.
|
||||
these holes in media buffered are often encountered on stream discontinuity or on quality level switch. holes could be "large" especially if fragments are not starting with a keyframe.
|
||||
- [src/controller/buffer-controller.js][]
|
||||
- in charge of:
|
||||
- resetting media buffer upon BUFFER_RESET event reception
|
||||
|
|
88
dashboard-ui/bower_components/hls.js/dist/hls.js
vendored
88
dashboard-ui/bower_components/hls.js/dist/hls.js
vendored
|
@ -578,6 +578,7 @@ var BufferController = function (_EventHandler) {
|
|||
ms.removeEventListener('sourceclose', this.onmsc);
|
||||
// unlink MediaSource from video tag
|
||||
this.media.src = '';
|
||||
this.media.removeAttribute('src');
|
||||
this.mediaSource = null;
|
||||
this.media = null;
|
||||
this.pendingTracks = null;
|
||||
|
@ -810,9 +811,9 @@ var BufferController = function (_EventHandler) {
|
|||
}
|
||||
} else {
|
||||
// QuotaExceededError: http://www.w3.org/TR/html5/infrastructure.html#quotaexceedederror
|
||||
// let's stop appending any segments, and report BUFFER_FULL error
|
||||
// let's stop appending any segments, and report BUFFER_FULL_ERROR error
|
||||
segments = [];
|
||||
event.details = _errors.ErrorDetails.BUFFER_FULL;
|
||||
event.details = _errors.ErrorDetails.BUFFER_FULL_ERROR;
|
||||
hls.trigger(_events2.default.ERROR, event);
|
||||
}
|
||||
}
|
||||
|
@ -1417,8 +1418,11 @@ var StreamController = function (_EventHandler) {
|
|||
if (levelDetails.live) {
|
||||
// check if requested position is within seekable boundaries :
|
||||
//logger.log(`start/pos/bufEnd/seeking:${start.toFixed(3)}/${pos.toFixed(3)}/${bufferEnd.toFixed(3)}/${this.media.seeking}`);
|
||||
if (bufferEnd < Math.max(start, end - config.liveMaxLatencyDurationCount * levelDetails.targetduration)) {
|
||||
this.seekAfterBuffered = start + Math.max(0, levelDetails.totalduration - config.liveSyncDurationCount * levelDetails.targetduration);
|
||||
var maxLatency = config.liveMaxLatencyDuration !== undefined ? config.liveMaxLatencyDuration : config.liveMaxLatencyDurationCount * levelDetails.targetduration;
|
||||
|
||||
if (bufferEnd < Math.max(start, end - maxLatency)) {
|
||||
var targetLatency = config.liveSyncDuration !== undefined ? config.liveSyncDuration : config.liveSyncDurationCount * levelDetails.targetduration;
|
||||
this.seekAfterBuffered = start + Math.max(0, levelDetails.totalduration - targetLatency);
|
||||
_logger.logger.log('buffer end: ' + bufferEnd + ' is located too far from the end of live sliding playlist, media position will be reseted to: ' + this.seekAfterBuffered.toFixed(3));
|
||||
bufferEnd = this.seekAfterBuffered;
|
||||
}
|
||||
|
@ -1662,7 +1666,7 @@ var StreamController = function (_EventHandler) {
|
|||
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 + maxHoleDuration;
|
||||
bufferEnd = end;
|
||||
bufferLen = bufferEnd - pos;
|
||||
} else if (pos + maxHoleDuration < start) {
|
||||
bufferStartNext = start;
|
||||
|
@ -1674,11 +1678,15 @@ var StreamController = function (_EventHandler) {
|
|||
}, {
|
||||
key: 'getBufferRange',
|
||||
value: function getBufferRange(position) {
|
||||
var i, range;
|
||||
for (i = this.bufferRange.length - 1; i >= 0; i--) {
|
||||
range = this.bufferRange[i];
|
||||
if (position >= range.start && position <= range.end) {
|
||||
return range;
|
||||
var i,
|
||||
range,
|
||||
bufferRange = this.bufferRange;
|
||||
if (bufferRange) {
|
||||
for (i = bufferRange.length - 1; i >= 0; i--) {
|
||||
range = bufferRange[i];
|
||||
if (position >= range.start && position <= range.end) {
|
||||
return range;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -1995,7 +2003,8 @@ var StreamController = function (_EventHandler) {
|
|||
if (this.startFragRequested === false) {
|
||||
// if live playlist, set start position to be fragment N-this.config.liveSyncDurationCount (usually 3)
|
||||
if (newDetails.live) {
|
||||
this.startPosition = Math.max(0, sliding + duration - this.config.liveSyncDurationCount * newDetails.targetduration);
|
||||
var targetLatency = this.config.liveSyncDuration !== undefined ? this.config.liveSyncDuration : this.config.liveSyncDurationCount * newDetails.targetduration;
|
||||
this.startPosition = Math.max(0, sliding + duration - targetLatency);
|
||||
}
|
||||
this.nextLoadPosition = this.startPosition;
|
||||
}
|
||||
|
@ -2249,7 +2258,7 @@ var StreamController = function (_EventHandler) {
|
|||
_logger.logger.warn('mediaController: ' + data.details + ' while loading frag,switch to ' + (data.fatal ? 'ERROR' : 'IDLE') + ' state ...');
|
||||
this.state = data.fatal ? State.ERROR : State.IDLE;
|
||||
break;
|
||||
case _errors.ErrorDetails.BUFFER_FULL:
|
||||
case _errors.ErrorDetails.BUFFER_FULL_ERROR:
|
||||
// trigger a smooth level switch to empty buffers
|
||||
// also reduce max buffer length as it might be too high. we do this to avoid loop flushing ...
|
||||
this.config.maxMaxBufferLength /= 2;
|
||||
|
@ -2296,8 +2305,9 @@ var StreamController = function (_EventHandler) {
|
|||
}
|
||||
var bufferInfo = this.bufferInfo(currentTime, 0),
|
||||
expectedPlaying = !(media.paused || media.ended || media.seeking || readyState < 2),
|
||||
jumpThreshold = 0.2,
|
||||
playheadMoving = currentTime > media.playbackRate * this.lastCurrentTime;
|
||||
jumpThreshold = 0.4,
|
||||
// tolerance needed as some browsers stalls playback before reaching buffered range end
|
||||
playheadMoving = currentTime > media.playbackRate * this.lastCurrentTime;
|
||||
|
||||
if (this.stalled && playheadMoving) {
|
||||
this.stalled = false;
|
||||
|
@ -2319,14 +2329,15 @@ var StreamController = function (_EventHandler) {
|
|||
}
|
||||
// if we are below threshold, try to jump if next buffer range is close
|
||||
if (bufferInfo.len <= jumpThreshold) {
|
||||
// no buffer available @ currentTime, check if next buffer is close (more than 5ms diff but within a config.maxSeekHole second range)
|
||||
// no buffer available @ currentTime, check if next buffer is close (within a config.maxSeekHole second range)
|
||||
var nextBufferStart = bufferInfo.nextStart,
|
||||
delta = nextBufferStart - currentTime;
|
||||
if (nextBufferStart && delta < this.config.maxSeekHole && delta > 0.005 && !media.seeking) {
|
||||
if (nextBufferStart && delta < this.config.maxSeekHole && delta > 0 && !media.seeking) {
|
||||
// next buffer is close ! adjust currentTime to nextBufferStart
|
||||
// this will ensure effective video decoding
|
||||
_logger.logger.log('adjust currentTime from ' + media.currentTime + ' to next buffered @ ' + nextBufferStart);
|
||||
media.currentTime = nextBufferStart;
|
||||
this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.BUFFER_SEEK_OVER_HOLE, fatal: false });
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -4920,8 +4931,10 @@ var ErrorDetails = exports.ErrorDetails = {
|
|||
BUFFER_APPENDING_ERROR: 'bufferAppendingError',
|
||||
// Identifier for a buffer stalled error event
|
||||
BUFFER_STALLED_ERROR: 'bufferStalledError',
|
||||
// Identifier for a buffer full error event
|
||||
BUFFER_FULL_ERROR: 'bufferFullError'
|
||||
// Identifier for a buffer full event
|
||||
BUFFER_FULL_ERROR: 'bufferFullError',
|
||||
// Identifier for a buffer seek over hole event
|
||||
BUFFER_SEEK_OVER_HOLE: 'bufferSeekOverHole'
|
||||
};
|
||||
|
||||
},{}],20:[function(require,module,exports){
|
||||
|
@ -5340,6 +5353,8 @@ var Hls = function () {
|
|||
maxSeekHole: 2,
|
||||
liveSyncDurationCount: 3,
|
||||
liveMaxLatencyDurationCount: Infinity,
|
||||
liveSyncDuration: undefined,
|
||||
liveMaxLatencyDuration: undefined,
|
||||
maxMaxBufferLength: 600,
|
||||
enableWorker: true,
|
||||
enableSoftwareAES: true,
|
||||
|
@ -5381,6 +5396,11 @@ var Hls = function () {
|
|||
_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;
|
||||
|
@ -5392,6 +5412,10 @@ var Hls = function () {
|
|||
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"');
|
||||
}
|
||||
|
||||
(0, _logger.enableLogs)(config.debug);
|
||||
this.config = config;
|
||||
// observer setup
|
||||
|
@ -5706,13 +5730,17 @@ var FragmentLoader = function (_EventHandler) {
|
|||
}, {
|
||||
key: 'loaderror',
|
||||
value: function loaderror(event) {
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: _errors.ErrorDetails.FRAG_LOAD_ERROR, fatal: false, frag: this.frag, response: event });
|
||||
}
|
||||
}, {
|
||||
key: 'loadtimeout',
|
||||
value: function loadtimeout() {
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: _errors.ErrorDetails.FRAG_LOAD_TIMEOUT, fatal: false, frag: this.frag });
|
||||
}
|
||||
}, {
|
||||
|
@ -5810,13 +5838,17 @@ var KeyLoader = function (_EventHandler) {
|
|||
}, {
|
||||
key: 'loaderror',
|
||||
value: function loaderror(event) {
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: _errors.ErrorDetails.KEY_LOAD_ERROR, fatal: false, frag: this.frag, response: event });
|
||||
}
|
||||
}, {
|
||||
key: 'loadtimeout',
|
||||
value: function loadtimeout() {
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: _errors.ErrorDetails.KEY_LOAD_TIMEOUT, fatal: false, frag: this.frag });
|
||||
}
|
||||
}, {
|
||||
|
@ -5907,7 +5939,7 @@ var PlaylistLoader = function (_EventHandler) {
|
|||
this.url = url;
|
||||
this.id = id1;
|
||||
this.id2 = id2;
|
||||
if (this.id === undefined) {
|
||||
if (this.id === null) {
|
||||
retry = config.manifestLoadingMaxRetry;
|
||||
timeout = config.manifestLoadingTimeOut;
|
||||
retryDelay = config.manifestLoadingRetryDelay;
|
||||
|
@ -6141,7 +6173,9 @@ var PlaylistLoader = function (_EventHandler) {
|
|||
details = _errors.ErrorDetails.LEVEL_LOAD_ERROR;
|
||||
fatal = false;
|
||||
}
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, response: event.currentTarget, level: this.id, id: this.id2 });
|
||||
}
|
||||
}, {
|
||||
|
@ -6155,7 +6189,9 @@ var PlaylistLoader = function (_EventHandler) {
|
|||
details = _errors.ErrorDetails.LEVEL_LOAD_TIMEOUT;
|
||||
fatal = false;
|
||||
}
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, level: this.id, id: this.id2 });
|
||||
}
|
||||
}]);
|
||||
|
@ -7951,7 +7987,7 @@ var URLHelper = {
|
|||
baseURL = baseURLQuerySplit[1];
|
||||
}
|
||||
|
||||
var baseURLDomainSplit = /^((([a-z]+):)?\/\/[a-z0-9\.-]+(:[0-9]+)?\/)(.*)$/i.exec(baseURL);
|
||||
var baseURLDomainSplit = /^((([a-z]+):)?\/\/[a-z0-9\.\-_~]+(:[0-9]+)?\/)(.*)$/i.exec(baseURL);
|
||||
var baseURLProtocol = baseURLDomainSplit[3];
|
||||
var baseURLDomain = baseURLDomainSplit[1];
|
||||
var baseURLPath = baseURLDomainSplit[5];
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "hls.js",
|
||||
"version": "0.5.8",
|
||||
"version": "0.5.9",
|
||||
"license": "Apache-2.0",
|
||||
"description": "Media Source Extension - HLS library, by/for Dailymotion",
|
||||
"homepage": "https://github.com/dailymotion/hls.js",
|
||||
|
|
|
@ -63,6 +63,7 @@ class BufferController extends EventHandler {
|
|||
ms.removeEventListener('sourceclose', this.onmsc);
|
||||
// unlink MediaSource from video tag
|
||||
this.media.src = '';
|
||||
this.media.removeAttribute('src');
|
||||
this.mediaSource = null;
|
||||
this.media = null;
|
||||
this.pendingTracks = null;
|
||||
|
@ -280,9 +281,9 @@ class BufferController extends EventHandler {
|
|||
}
|
||||
} else {
|
||||
// QuotaExceededError: http://www.w3.org/TR/html5/infrastructure.html#quotaexceedederror
|
||||
// let's stop appending any segments, and report BUFFER_FULL error
|
||||
// let's stop appending any segments, and report BUFFER_FULL_ERROR error
|
||||
segments = [];
|
||||
event.details = ErrorDetails.BUFFER_FULL;
|
||||
event.details = ErrorDetails.BUFFER_FULL_ERROR;
|
||||
hls.trigger(Event.ERROR,event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -196,8 +196,11 @@ class StreamController extends EventHandler {
|
|||
if (levelDetails.live) {
|
||||
// check if requested position is within seekable boundaries :
|
||||
//logger.log(`start/pos/bufEnd/seeking:${start.toFixed(3)}/${pos.toFixed(3)}/${bufferEnd.toFixed(3)}/${this.media.seeking}`);
|
||||
if (bufferEnd < Math.max(start,end-config.liveMaxLatencyDurationCount*levelDetails.targetduration)) {
|
||||
this.seekAfterBuffered = start + Math.max(0, levelDetails.totalduration - config.liveSyncDurationCount * levelDetails.targetduration);
|
||||
let maxLatency = config.liveMaxLatencyDuration !== undefined ? config.liveMaxLatencyDuration : config.liveMaxLatencyDurationCount*levelDetails.targetduration;
|
||||
|
||||
if (bufferEnd < Math.max(start, end - maxLatency)) {
|
||||
let targetLatency = config.liveSyncDuration !== undefined ? config.liveSyncDuration : config.liveSyncDurationCount * levelDetails.targetduration;
|
||||
this.seekAfterBuffered = start + Math.max(0, levelDetails.totalduration - targetLatency);
|
||||
logger.log(`buffer end: ${bufferEnd} is located too far from the end of live sliding playlist, media position will be reseted to: ${this.seekAfterBuffered.toFixed(3)}`);
|
||||
bufferEnd = this.seekAfterBuffered;
|
||||
}
|
||||
|
@ -433,7 +436,7 @@ class StreamController extends EventHandler {
|
|||
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 + maxHoleDuration;
|
||||
bufferEnd = end;
|
||||
bufferLen = bufferEnd - pos;
|
||||
} else if ((pos + maxHoleDuration) < start) {
|
||||
bufferStartNext = start;
|
||||
|
@ -444,11 +447,14 @@ class StreamController extends EventHandler {
|
|||
}
|
||||
|
||||
getBufferRange(position) {
|
||||
var i, range;
|
||||
for (i = this.bufferRange.length - 1; i >=0; i--) {
|
||||
range = this.bufferRange[i];
|
||||
if (position >= range.start && position <= range.end) {
|
||||
return range;
|
||||
var i, range,
|
||||
bufferRange = this.bufferRange;
|
||||
if (bufferRange) {
|
||||
for (i = bufferRange.length - 1; i >=0; i--) {
|
||||
range = bufferRange[i];
|
||||
if (position >= range.start && position <= range.end) {
|
||||
return range;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -770,7 +776,8 @@ class StreamController extends EventHandler {
|
|||
if (this.startFragRequested === false) {
|
||||
// if live playlist, set start position to be fragment N-this.config.liveSyncDurationCount (usually 3)
|
||||
if (newDetails.live) {
|
||||
this.startPosition = Math.max(0, sliding + duration - this.config.liveSyncDurationCount * newDetails.targetduration);
|
||||
let targetLatency = this.config.liveSyncDuration !== undefined ? this.config.liveSyncDuration : this.config.liveSyncDurationCount * newDetails.targetduration;
|
||||
this.startPosition = Math.max(0, sliding + duration - targetLatency);
|
||||
}
|
||||
this.nextLoadPosition = this.startPosition;
|
||||
}
|
||||
|
@ -1014,7 +1021,7 @@ class StreamController extends EventHandler {
|
|||
logger.warn(`mediaController: ${data.details} while loading frag,switch to ${data.fatal ? 'ERROR' : 'IDLE'} state ...`);
|
||||
this.state = data.fatal ? State.ERROR : State.IDLE;
|
||||
break;
|
||||
case ErrorDetails.BUFFER_FULL:
|
||||
case ErrorDetails.BUFFER_FULL_ERROR:
|
||||
// trigger a smooth level switch to empty buffers
|
||||
// also reduce max buffer length as it might be too high. we do this to avoid loop flushing ...
|
||||
this.config.maxMaxBufferLength/=2;
|
||||
|
@ -1060,7 +1067,7 @@ _checkBuffer() {
|
|||
}
|
||||
var bufferInfo = this.bufferInfo(currentTime,0),
|
||||
expectedPlaying = !(media.paused || media.ended || media.seeking || readyState < 2),
|
||||
jumpThreshold = 0.2,
|
||||
jumpThreshold = 0.4, // tolerance needed as some browsers stalls playback before reaching buffered range end
|
||||
playheadMoving = currentTime > media.playbackRate*this.lastCurrentTime;
|
||||
|
||||
if (this.stalled && playheadMoving) {
|
||||
|
@ -1083,16 +1090,17 @@ _checkBuffer() {
|
|||
}
|
||||
// if we are below threshold, try to jump if next buffer range is close
|
||||
if(bufferInfo.len <= jumpThreshold) {
|
||||
// no buffer available @ currentTime, check if next buffer is close (more than 5ms diff but within a config.maxSeekHole second range)
|
||||
// no buffer available @ currentTime, check if next buffer is close (within a config.maxSeekHole second range)
|
||||
var nextBufferStart = bufferInfo.nextStart, delta = nextBufferStart-currentTime;
|
||||
if(nextBufferStart &&
|
||||
(delta < this.config.maxSeekHole) &&
|
||||
(delta > 0.005) &&
|
||||
(delta > 0) &&
|
||||
!media.seeking) {
|
||||
// next buffer is close ! adjust currentTime to nextBufferStart
|
||||
// this will ensure effective video decoding
|
||||
logger.log(`adjust currentTime from ${media.currentTime} to next buffered @ ${nextBufferStart}`);
|
||||
media.currentTime = nextBufferStart;
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.BUFFER_SEEK_OVER_HOLE, fatal: false});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -40,6 +40,8 @@ export const ErrorDetails = {
|
|||
BUFFER_APPENDING_ERROR: 'bufferAppendingError',
|
||||
// Identifier for a buffer stalled error event
|
||||
BUFFER_STALLED_ERROR: 'bufferStalledError',
|
||||
// Identifier for a buffer full error event
|
||||
BUFFER_FULL_ERROR: 'bufferFullError'
|
||||
// Identifier for a buffer full event
|
||||
BUFFER_FULL_ERROR: 'bufferFullError',
|
||||
// Identifier for a buffer seek over hole event
|
||||
BUFFER_SEEK_OVER_HOLE: 'bufferSeekOverHole'
|
||||
};
|
||||
|
|
11
dashboard-ui/bower_components/hls.js/src/hls.js
vendored
11
dashboard-ui/bower_components/hls.js/src/hls.js
vendored
|
@ -47,6 +47,8 @@ class Hls {
|
|||
maxSeekHole: 2,
|
||||
liveSyncDurationCount:3,
|
||||
liveMaxLatencyDurationCount: Infinity,
|
||||
liveSyncDuration: undefined,
|
||||
liveMaxLatencyDuration: undefined,
|
||||
maxMaxBufferLength: 600,
|
||||
enableWorker: true,
|
||||
enableSoftwareAES: true,
|
||||
|
@ -84,6 +86,11 @@ class Hls {
|
|||
|
||||
constructor(config = {}) {
|
||||
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];
|
||||
|
@ -93,6 +100,10 @@ class Hls {
|
|||
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"');
|
||||
}
|
||||
|
||||
enableLogs(config.debug);
|
||||
this.config = config;
|
||||
// observer setup
|
||||
|
|
|
@ -38,12 +38,16 @@ class FragmentLoader extends EventHandler {
|
|||
}
|
||||
|
||||
loaderror(event) {
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.FRAG_LOAD_ERROR, fatal: false, frag: this.frag, response: event});
|
||||
}
|
||||
|
||||
loadtimeout() {
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.FRAG_LOAD_TIMEOUT, fatal: false, frag: this.frag});
|
||||
}
|
||||
|
||||
|
|
|
@ -49,12 +49,16 @@ class KeyLoader extends EventHandler {
|
|||
}
|
||||
|
||||
loaderror(event) {
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.KEY_LOAD_ERROR, fatal: false, frag: this.frag, response: event});
|
||||
}
|
||||
|
||||
loadtimeout() {
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.KEY_LOAD_TIMEOUT, fatal: false, frag: this.frag});
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ class PlaylistLoader extends EventHandler {
|
|||
this.url = url;
|
||||
this.id = id1;
|
||||
this.id2 = id2;
|
||||
if(this.id === undefined) {
|
||||
if(this.id === null) {
|
||||
retry = config.manifestLoadingMaxRetry;
|
||||
timeout = config.manifestLoadingTimeOut;
|
||||
retryDelay = config.manifestLoadingRetryDelay;
|
||||
|
@ -265,7 +265,9 @@ class PlaylistLoader extends EventHandler {
|
|||
details = ErrorDetails.LEVEL_LOAD_ERROR;
|
||||
fatal = false;
|
||||
}
|
||||
this.loader.abort();
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, response: event.currentTarget, level: this.id, id: this.id2});
|
||||
}
|
||||
|
||||
|
@ -278,8 +280,10 @@ class PlaylistLoader extends EventHandler {
|
|||
details = ErrorDetails.LEVEL_LOAD_TIMEOUT;
|
||||
fatal = false;
|
||||
}
|
||||
this.loader.abort();
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, level: this.id, id: this.id2});
|
||||
if (this.loader) {
|
||||
this.loader.abort();
|
||||
}
|
||||
this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, level: this.id, id: this.id2});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ var URLHelper = {
|
|||
baseURL = baseURLQuerySplit[1];
|
||||
}
|
||||
|
||||
var baseURLDomainSplit = /^((([a-z]+):)?\/\/[a-z0-9\.-]+(:[0-9]+)?\/)(.*)$/i.exec(baseURL);
|
||||
var baseURLDomainSplit = /^((([a-z]+):)?\/\/[a-z0-9\.\-_~]+(:[0-9]+)?\/)(.*)$/i.exec(baseURL);
|
||||
var baseURLProtocol = baseURLDomainSplit[3];
|
||||
var baseURLDomain = baseURLDomainSplit[1];
|
||||
var baseURLPath = baseURLDomainSplit[5];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue