update components

This commit is contained in:
Luke Pulverenti 2016-03-25 12:35:19 -04:00
parent beae29d407
commit b0d117ad5b
16 changed files with 800 additions and 382 deletions

View file

@ -16,12 +16,12 @@
},
"devDependencies": {},
"ignore": [],
"version": "1.1.89",
"_release": "1.1.89",
"version": "1.1.90",
"_release": "1.1.90",
"_resolution": {
"type": "version",
"tag": "1.1.89",
"commit": "63bd5720079d9ba97f1288c37e5f0180b0ebcdfb"
"tag": "1.1.90",
"commit": "9e93842e8a97af43376a73089a4a0a87c18c0e6b"
},
"_source": "git://github.com/MediaBrowser/emby-webcomponents.git",
"_target": "~1.1.5",

View file

@ -75,7 +75,13 @@ define(['connectionManager', 'userSettings', 'events'], function (connectionMana
}
}
return culture.toLowerCase();
var lower = culture.toLowerCase();
if (lower == 'ca-es') {
return 'ca';
}
return lower;
}
function getDictionary(module) {

View file

@ -1,6 +1,6 @@
{
"name": "hls.js",
"version": "0.5.15",
"version": "0.5.16",
"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.15",
"_release": "0.5.16",
"_resolution": {
"type": "version",
"tag": "v0.5.15",
"commit": "59d52b9e7661e3d97f8ec580de923d406e5a641f"
"tag": "v0.5.16",
"commit": "a7df764cb21cf306bf4fe7c54ae68c8e4cd30f51"
},
"_source": "git://github.com/dailymotion/hls.js.git",
"_target": "~0.5.7",

View file

@ -183,6 +183,7 @@ configuration parameters could be provided to hls.js upon instantiation of Hls O
var config = {
autoStartLoad : true,
capLevelToPlayerSize: false,
debug : false,
defaultAudioCodec : undefined,
maxBufferLength : 30,
@ -223,6 +224,12 @@ var hls = new Hls(config);
this getter/setter allows to retrieve and override Hls default configuration.
this configuration will be applied by default to all instances.
#### ```capLevelToPlayerSize```
(default false)
- if set to true, the adaptive algorithm with limit levels usable in auto-quality by the HTML video element dimensions (width and height)
- if set to false, levels will not be limited. All available levels could be used in auto-quality mode taking only bandwidth into consideration.
#### ```debug```
(default false)
@ -397,7 +404,7 @@ var customLoader = function() {
maxRetry : max nb of load retry
retryDelay : delay between an I/O error and following connection retry (ms). this to avoid spamming the server.
*/
this.load = function(url,responseType,onSuccess,onError,timeout,maxRetry,retryDelay) {}
this.load = function(url,responseType,onSuccess,onError,onTimeOut,timeout,maxRetry,retryDelay) {}
/* abort any loading in progress */
this.abort = function() {}

View file

@ -1,6 +1,6 @@
{
"name": "hls.js",
"version": "0.5.15",
"version": "0.5.16",
"license": "Apache-2.0",
"description": "Media Source Extension - HLS library, by/for Dailymotion",
"homepage": "https://github.com/dailymotion/hls.js",

View file

@ -53,6 +53,8 @@ design idea is pretty simple :
- [src/controller/abr-controller.js][]
- in charge of determining auto quality level.
- auto quality switch algorithm is pretty naive and simple ATM and similar to the one that could be found in google [StageFright](https://android.googlesource.com/platform/frameworks/av/+/master/media/libstagefright/httplive/LiveSession.cpp)
- [src/controller/cap-level-controller.js][]
- in charge of determining best quality level to actual size (dimensions: width and height) of the player
- [src/crypt/aes.js][]
- AES 128 software decryption routine, low level class handling decryption of 128 bit of data.
- [src/crypt/aes128-decrypter.js][]
@ -132,6 +134,7 @@ design idea is pretty simple :
[src/stats.js]: src/stats.js
[src/controller/abr-controller.js]: src/controller/abr-controller.js
[src/controller/buffer-controller.js]: src/controller/buffer-controller.js
[src/controller/cap-level-controller.js]: src/controller/cap-level-controller.js
[src/controller/fps-controller.js]: src/controller/fps-controller.js
[src/controller/level-controller.js]: src/controller/level-controller.js
[src/controller/stream-controller.js]: src/controller/stream-controller.js

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
{
"name": "hls.js",
"version": "0.5.15",
"version": "0.5.16",
"license": "Apache-2.0",
"description": "Media Source Extension - HLS library, by/for Dailymotion",
"homepage": "https://github.com/dailymotion/hls.js",

View file

@ -1,23 +1,39 @@
/*
* simple ABR Controller
* - compute next level based on last fragment bw heuristics
* - implement an abandon rules triggered if we have less than 2 frag buffered and if computed bw shows that we risk buffer stalling
*/
import Event from '../events';
import EventHandler from '../event-handler';
import BufferHelper from '../helper/buffer-helper';
import {ErrorDetails} from '../errors';
import {logger} from '../utils/logger';
class AbrController extends EventHandler {
constructor(hls) {
super(hls, Event.FRAG_LOAD_PROGRESS);
this.lastfetchlevel = 0;
super(hls, Event.FRAG_LOADING,
Event.FRAG_LOAD_PROGRESS,
Event.FRAG_LOADED,
Event.ERROR);
this.lastLoadedFragLevel = 0;
this._autoLevelCapping = -1;
this._nextAutoLevel = -1;
this.hls = hls;
this.onCheck = this.abandonRulesCheck.bind(this);
}
destroy() {
this.clearTimer();
EventHandler.prototype.destroy.call(this);
}
onFragLoading(data) {
this.timer = setInterval(this.onCheck, 100);
this.fragCurrent = data.frag;
}
onFragLoadProgress(data) {
var stats = data.stats;
// only update stats if first frag loading
@ -25,12 +41,96 @@ class AbrController extends EventHandler {
// and leading to wrong bw estimation
if (stats.aborted === undefined && data.frag.loadCounter === 1) {
this.lastfetchduration = (performance.now() - stats.trequest) / 1000;
this.lastfetchlevel = data.frag.level;
this.lastbw = (stats.loaded * 8) / this.lastfetchduration;
//console.log(`fetchDuration:${this.lastfetchduration},bw:${(this.lastbw/1000).toFixed(0)}/${stats.aborted}`);
}
}
abandonRulesCheck() {
/*
monitor fragment retrieval time...
we compute expected time of arrival of the complete fragment.
we compare it to expected time of buffer starvation
*/
let hls = this.hls, v = hls.media,frag = this.fragCurrent;
/* only monitor frag retrieval time if
(video not paused OR first fragment being loaded(ready state === HAVE_NOTHING = 0)) AND autoswitching enabled AND not lowest level (=> means that we have several levels) */
if (v && (!v.paused || !v.readyState) && frag.autoLevel && frag.level) {
let requestDelay = performance.now() - frag.trequest;
// monitor fragment load progress after half of expected fragment duration,to stabilize bitrate
if (requestDelay > (500 * frag.duration)) {
let loadRate = Math.max(1,frag.loaded * 1000 / requestDelay); // byte/s; at least 1 byte/s to avoid division by zero
if (frag.expectedLen < frag.loaded) {
frag.expectedLen = frag.loaded;
}
let pos = v.currentTime;
let fragLoadedDelay = (frag.expectedLen - frag.loaded) / loadRate;
let bufferStarvationDelay = BufferHelper.bufferInfo(v,pos,hls.config.maxBufferHole).end - pos;
// consider emergency switch down only if we have less than 2 frag buffered AND
// time to finish loading current fragment is bigger than buffer starvation delay
// ie if we risk buffer starvation if bw does not increase quickly
if (bufferStarvationDelay < 2*frag.duration && fragLoadedDelay > bufferStarvationDelay) {
let fragLevelNextLoadedDelay, nextLoadLevel;
// lets iterate through lower level and try to find the biggest one that could avoid rebuffering
// we start from current level - 1 and we step down , until we find a matching level
for (nextLoadLevel = frag.level - 1 ; nextLoadLevel >=0 ; nextLoadLevel--) {
// compute time to load next fragment at lower level
// 0.8 : consider only 80% of current bw to be conservative
// 8 = bits per byte (bps/Bps)
fragLevelNextLoadedDelay = frag.duration * hls.levels[nextLoadLevel].bitrate / (8 * 0.8 * loadRate);
logger.log(`fragLoadedDelay/bufferStarvationDelay/fragLevelNextLoadedDelay[${nextLoadLevel}] :${fragLoadedDelay.toFixed(1)}/${bufferStarvationDelay.toFixed(1)}/${fragLevelNextLoadedDelay.toFixed(1)}`);
if (fragLevelNextLoadedDelay < bufferStarvationDelay) {
// we found a lower level that be rebuffering free with current estimated bw !
break;
}
}
// only emergency switch down if it takes less time to load new fragment at lowest level instead
// of finishing loading current one ...
if (fragLevelNextLoadedDelay < fragLoadedDelay) {
// ensure nextLoadLevel is not negative
nextLoadLevel = Math.max(0,nextLoadLevel);
// force next load level in auto mode
hls.nextLoadLevel = nextLoadLevel;
// abort fragment loading ...
logger.warn(`loading too slow, abort fragment loading and switch to level ${nextLoadLevel}`);
//abort fragment loading
frag.loader.abort();
this.clearTimer();
hls.trigger(Event.FRAG_LOAD_EMERGENCY_ABORTED, {frag: frag});
}
}
}
}
}
onFragLoaded(data) {
// stop monitoring bw once frag loaded
this.clearTimer();
// store level id after successful fragment load
this.lastLoadedFragLevel = data.frag.level;
// reset forced auto level value so that next level will be selected
this._nextAutoLevel = -1;
}
onError(data) {
// stop timer in case of frag loading error
switch(data.details) {
case ErrorDetails.FRAG_LOAD_ERROR:
case ErrorDetails.FRAG_LOAD_TIMEOUT:
this.clearTimer();
break;
default:
break;
}
}
clearTimer() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
}
/** Return the capping/max level value that could be used by automatic level selection algorithm **/
get autoLevelCapping() {
return this._autoLevelCapping;
@ -49,13 +149,9 @@ class AbrController extends EventHandler {
maxAutoLevel = this._autoLevelCapping;
}
// in case next auto level has been forced, return it straight-away (but capped)
if (this._nextAutoLevel !== -1) {
var nextLevel = Math.min(this._nextAutoLevel,maxAutoLevel);
if (nextLevel === this.lastfetchlevel) {
this._nextAutoLevel = -1;
} else {
return nextLevel;
}
return Math.min(this._nextAutoLevel,maxAutoLevel);
}
// follow algorithm captured from stagefright :
@ -65,7 +161,7 @@ class AbrController extends EventHandler {
// consider only 80% of the available bandwidth, but if we are switching up,
// be even more conservative (70%) to avoid overestimating and immediately
// switching back.
if (i <= this.lastfetchlevel) {
if (i <= this.lastLoadedFragLevel) {
adjustedbw = 0.8 * lastbw;
} else {
adjustedbw = 0.7 * lastbw;

View file

@ -0,0 +1,106 @@
/*
* cap stream level to media size dimension controller
*/
import Event from '../events';
import EventHandler from '../event-handler';
class CapLevelController extends EventHandler {
constructor(hls) {
super(hls,
Event.MEDIA_ATTACHING,
Event.MANIFEST_PARSED);
}
destroy() {
if (this.hls.config.capLevelToPlayerSize) {
this.media = null;
this.autoLevelCapping = Number.POSITIVE_INFINITY;
if (this.timer) {
this.timer = clearInterval(this.timer);
}
}
}
onMediaAttaching(data) {
this.media = data.media instanceof HTMLVideoElement ? data.media : null;
}
onManifestParsed(data) {
if (this.hls.config.capLevelToPlayerSize) {
this.autoLevelCapping = Number.POSITIVE_INFINITY;
this.levels = data.levels;
this.hls.firstLevel = this.getMaxLevel(data.firstLevel);
clearInterval(this.timer);
this.timer = setInterval(this.detectPlayerSize.bind(this), 1000);
this.detectPlayerSize();
}
}
detectPlayerSize() {
if (this.media) {
let levelsLength = this.levels ? this.levels.length : 0;
if (levelsLength) {
this.hls.autoLevelCapping = this.getMaxLevel(levelsLength - 1);
if (this.hls.autoLevelCapping > this.autoLevelCapping) {
// if auto level capping has a higher value for the previous one, flush the buffer using nextLevelSwitch
// usually happen when the user go to the fullscreen mode.
this.hls.streamController.nextLevelSwitch();
}
this.autoLevelCapping = this.hls.autoLevelCapping;
}
}
}
/*
* returns level should be the one with the dimensions equal or greater than the media (player) dimensions (so the video will be downscaled)
*/
getMaxLevel(capLevelIndex) {
let result,
i,
level,
mWidth = this.mediaWidth,
mHeight = this.mediaHeight,
lWidth = 0,
lHeight = 0;
for (i = 0; i <= capLevelIndex; i++) {
level = this.levels[i];
result = i;
lWidth = level.width;
lHeight = level.height;
if (mWidth <= lWidth || mHeight <= lHeight) {
break;
}
}
return result;
}
get contentScaleFactor() {
let pixelRatio = 1;
try {
pixelRatio = window.devicePixelRatio;
} catch(e) {}
return pixelRatio;
}
get mediaWidth() {
let width;
if (this.media) {
width = this.media.width || this.media.clientWidth || this.media.offsetWidth;
width *= this.contentScaleFactor;
}
return width;
}
get mediaHeight() {
let height;
if (this.media) {
height = this.media.height || this.media.clientHeight || this.media.offsetHeight;
height *= this.contentScaleFactor;
}
return height;
}
}
export default CapLevelController;

View file

@ -7,6 +7,7 @@ import Event from '../events';
import EventHandler from '../event-handler';
import {logger} from '../utils/logger';
import BinarySearch from '../utils/binary-search';
import BufferHelper from '../helper/buffer-helper';
import LevelHelper from '../helper/level-helper';
import {ErrorTypes, ErrorDetails} from '../errors';
@ -36,6 +37,7 @@ class StreamController extends EventHandler {
Event.LEVEL_LOADED,
Event.KEY_LOADED,
Event.FRAG_LOADED,
Event.FRAG_LOAD_EMERGENCY_ABORTED,
Event.FRAG_PARSING_INIT_SEGMENT,
Event.FRAG_PARSING_DATA,
Event.FRAG_PARSED,
@ -162,7 +164,7 @@ class StreamController extends EventHandler {
// we are not at playback start, get next load level from level Controller
level = hls.nextLoadLevel;
}
var bufferInfo = this.bufferInfo(pos,config.maxBufferHole),
var bufferInfo = BufferHelper.bufferInfo(this.media,pos,config.maxBufferHole),
bufferLen = bufferInfo.len,
bufferEnd = bufferInfo.end,
fragPrevious = this.fragPrevious,
@ -330,63 +332,6 @@ class StreamController extends EventHandler {
this.state = State.IDLE;
}
break;
case State.FRAG_LOADING:
/*
monitor fragment retrieval time...
we compute expected time of arrival of the complete fragment.
we compare it to expected time of buffer starvation
*/
let v = this.media,frag = this.fragCurrent;
/* only monitor frag retrieval time if
(video not paused OR first fragment being loaded) AND autoswitching enabled AND not lowest level AND multiple levels */
if (v && (!v.paused || this.loadedmetadata === false) && frag.autoLevel && this.level && this.levels.length > 1) {
let requestDelay = performance.now() - frag.trequest;
// monitor fragment load progress after half of expected fragment duration,to stabilize bitrate
if (requestDelay > (500 * frag.duration)) {
let loadRate = Math.max(1,frag.loaded * 1000 / requestDelay); // byte/s; at least 1 byte/s to avoid division by zero
if (frag.expectedLen < frag.loaded) {
frag.expectedLen = frag.loaded;
}
pos = v.currentTime;
let fragLoadedDelay = (frag.expectedLen - frag.loaded) / loadRate;
let bufferStarvationDelay = this.bufferInfo(pos,config.maxBufferHole).end - pos;
// consider emergency switch down only if we have less than 2 frag buffered AND
// time to finish loading current fragment is bigger than buffer starvation delay
// ie if we risk buffer starvation if bw does not increase quickly
if (bufferStarvationDelay < 2*frag.duration && fragLoadedDelay > bufferStarvationDelay) {
let fragLevelNextLoadedDelay, nextLoadLevel;
// lets iterate through lower level and try to find the biggest one that could avoid rebuffering
// we start from current level - 1 and we step down , until we find a matching level
for (nextLoadLevel = this.level - 1 ; nextLoadLevel >=0 ; nextLoadLevel--) {
// compute time to load next fragment at lower level
// 0.8 : consider only 80% of current bw to be conservative
// 8 = bits per byte (bps/Bps)
fragLevelNextLoadedDelay = frag.duration * this.levels[nextLoadLevel].bitrate / (8 * 0.8 * loadRate);
logger.log(`fragLoadedDelay/bufferStarvationDelay/fragLevelNextLoadedDelay[${nextLoadLevel}] :${fragLoadedDelay.toFixed(1)}/${bufferStarvationDelay.toFixed(1)}/${fragLevelNextLoadedDelay.toFixed(1)}`);
if (fragLevelNextLoadedDelay < bufferStarvationDelay) {
// we found a lower level that be rebuffering free with current estimated bw !
break;
}
}
// only emergency switch down if it takes less time to load new fragment at lowest level instead
// of finishing loading current one ...
if (fragLevelNextLoadedDelay < fragLoadedDelay) {
// ensure nextLoadLevel is not negative
nextLoadLevel = Math.max(0,nextLoadLevel);
// force next load level in auto mode
hls.nextLoadLevel = nextLoadLevel;
// abort fragment loading ...
logger.warn(`loading too slow, abort fragment loading and switch to level ${nextLoadLevel}`);
//abort fragment loading
frag.loader.abort();
hls.trigger(Event.FRAG_LOAD_EMERGENCY_ABORTED, {frag: frag});
// switch back to IDLE state to request new fragment at lower level
this.state = State.IDLE;
}
}
}
}
break;
case State.FRAG_LOADING_WAITING_RETRY:
var now = performance.now();
var retryDate = this.retryDate;
@ -398,12 +343,10 @@ class StreamController extends EventHandler {
this.state = State.IDLE;
}
break;
case State.STOPPED:
case State.FRAG_LOADING:
case State.PARSING:
// nothing to do, wait for fragment being parsed
break;
case State.PARSED:
// nothing to do, wait for all buffers to be appended
break;
case State.ENDED:
break;
default:
@ -416,73 +359,7 @@ class StreamController extends EventHandler {
}
bufferInfo(pos,maxHoleDuration) {
var media = this.media;
if (media) {
var vbuffered = media.buffered, buffered = [],i;
for (i = 0; i < vbuffered.length; i++) {
buffered.push({start: vbuffered.start(i), end: vbuffered.end(i)});
}
return this.bufferedInfo(buffered,pos,maxHoleDuration);
} else {
return {len: 0, start: 0, end: 0, nextStart : undefined} ;
}
}
bufferedInfo(buffered,pos,maxHoleDuration) {
var buffered2 = [],
// bufferStart and bufferEnd are buffer boundaries around current video position
bufferLen,bufferStart, bufferEnd,bufferStartNext,i;
// sort on buffer.start/smaller end (IE does not always return sorted buffered range)
buffered.sort(function (a, b) {
var diff = a.start - b.start;
if (diff) {
return diff;
} else {
return b.end - a.end;
}
});
// there might be some small holes between buffer time range
// consider that holes smaller than maxHoleDuration are irrelevant and build another
// buffer time range representations that discards those holes
for (i = 0; i < buffered.length; i++) {
var buf2len = buffered2.length;
if(buf2len) {
var buf2end = buffered2[buf2len - 1].end;
// if small hole (value between 0 or maxHoleDuration ) or overlapping (negative)
if((buffered[i].start - buf2end) < maxHoleDuration) {
// merge overlapping time ranges
// update lastRange.end only if smaller than item.end
// e.g. [ 1, 15] with [ 2,8] => [ 1,15] (no need to modify lastRange.end)
// whereas [ 1, 8] with [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15])
if(buffered[i].end > buf2end) {
buffered2[buf2len - 1].end = buffered[i].end;
}
} else {
// big hole
buffered2.push(buffered[i]);
}
} else {
// first value
buffered2.push(buffered[i]);
}
}
for (i = 0, bufferLen = 0, bufferStart = bufferEnd = pos; i < buffered2.length; i++) {
var start = buffered2[i].start,
end = buffered2[i].end;
//logger.log('buf start/end:' + buffered.start(i) + '/' + buffered.end(i));
if ((pos + maxHoleDuration) >= start && pos < end) {
// play position is inside this buffer TimeRange, retrieve end of buffer position and buffer length
bufferStart = start;
bufferEnd = end;
bufferLen = bufferEnd - pos;
} else if ((pos + maxHoleDuration) < start) {
bufferStartNext = start;
break;
}
}
return {len: bufferLen, start: bufferStart, end: bufferEnd, nextStart : bufferStartNext};
}
getBufferRange(position) {
var i, range,
@ -712,7 +589,7 @@ class StreamController extends EventHandler {
if (this.state === State.FRAG_LOADING) {
// check if currently loaded fragment is inside buffer.
//if outside, cancel fragment loading, otherwise do nothing
if (this.bufferInfo(this.media.currentTime,this.config.maxBufferHole).len === 0) {
if (BufferHelper.bufferInfo(this.media,this.media.currentTime,this.config.maxBufferHole).len === 0) {
logger.log('seeking outside of buffer while fragment load in progress, cancel fragment load');
var fragCurrent = this.fragCurrent;
if (fragCurrent) {
@ -1114,7 +991,7 @@ _checkBuffer() {
currentTime = targetSeekPosition;
logger.log(`target seek position:${targetSeekPosition}`);
}
var bufferInfo = this.bufferInfo(currentTime,0),
var bufferInfo = BufferHelper.bufferInfo(media,currentTime,0),
expectedPlaying = !(media.paused || media.ended || media.seeking || readyState < 2),
jumpThreshold = 0.4, // tolerance needed as some browsers stalls playback before reaching buffered range end
playheadMoving = currentTime > media.playbackRate*this.lastCurrentTime;
@ -1163,6 +1040,11 @@ _checkBuffer() {
}
}
onFragLoadEmergencyAborted() {
this.state = State.IDLE;
this.tick();
}
onBufferFlushed() {
/* after successful buffer flushing, rebuild buffer Range array
loop through existing buffer range and check if

View file

@ -0,0 +1,77 @@
/**
* Buffer Helper class, providing methods dealing buffer length retrieval
*/
class BufferHelper {
static bufferInfo(media, pos,maxHoleDuration) {
if (media) {
var vbuffered = media.buffered, buffered = [],i;
for (i = 0; i < vbuffered.length; i++) {
buffered.push({start: vbuffered.start(i), end: vbuffered.end(i)});
}
return this.bufferedInfo(buffered,pos,maxHoleDuration);
} else {
return {len: 0, start: 0, end: 0, nextStart : undefined} ;
}
}
static bufferedInfo(buffered,pos,maxHoleDuration) {
var buffered2 = [],
// bufferStart and bufferEnd are buffer boundaries around current video position
bufferLen,bufferStart, bufferEnd,bufferStartNext,i;
// sort on buffer.start/smaller end (IE does not always return sorted buffered range)
buffered.sort(function (a, b) {
var diff = a.start - b.start;
if (diff) {
return diff;
} else {
return b.end - a.end;
}
});
// there might be some small holes between buffer time range
// consider that holes smaller than maxHoleDuration are irrelevant and build another
// buffer time range representations that discards those holes
for (i = 0; i < buffered.length; i++) {
var buf2len = buffered2.length;
if(buf2len) {
var buf2end = buffered2[buf2len - 1].end;
// if small hole (value between 0 or maxHoleDuration ) or overlapping (negative)
if((buffered[i].start - buf2end) < maxHoleDuration) {
// merge overlapping time ranges
// update lastRange.end only if smaller than item.end
// e.g. [ 1, 15] with [ 2,8] => [ 1,15] (no need to modify lastRange.end)
// whereas [ 1, 8] with [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15])
if(buffered[i].end > buf2end) {
buffered2[buf2len - 1].end = buffered[i].end;
}
} else {
// big hole
buffered2.push(buffered[i]);
}
} else {
// first value
buffered2.push(buffered[i]);
}
}
for (i = 0, bufferLen = 0, bufferStart = bufferEnd = pos; i < buffered2.length; i++) {
var start = buffered2[i].start,
end = buffered2[i].end;
//logger.log('buf start/end:' + buffered.start(i) + '/' + buffered.end(i));
if ((pos + maxHoleDuration) >= start && pos < end) {
// play position is inside this buffer TimeRange, retrieve end of buffer position and buffer length
bufferStart = start;
bufferEnd = end;
bufferLen = bufferEnd - pos;
} else if ((pos + maxHoleDuration) < start) {
bufferStartNext = start;
break;
}
}
return {len: bufferLen, start: bufferStart, end: bufferEnd, nextStart : bufferStartNext};
}
}
export default BufferHelper;

View file

@ -9,6 +9,7 @@ import PlaylistLoader from './loader/playlist-loader';
import FragmentLoader from './loader/fragment-loader';
import AbrController from './controller/abr-controller';
import BufferController from './controller/buffer-controller';
import CapLevelController from './controller/cap-level-controller';
import StreamController from './controller/stream-controller';
import LevelController from './controller/level-controller';
import TimelineController from './controller/timeline-controller';
@ -41,6 +42,7 @@ class Hls {
Hls.defaultConfig = {
autoStartLoad: true,
debug: false,
capLevelToPlayerSize: false,
maxBufferLength: 30,
maxBufferSize: 60 * 1000 * 1000,
maxBufferHole: 0.5,
@ -72,6 +74,7 @@ class Hls {
pLoader: undefined,
abrController : AbrController,
bufferController : BufferController,
capLevelController : CapLevelController,
streamController: StreamController,
timelineController: TimelineController,
enableCEA708Captions: true,
@ -124,6 +127,7 @@ class Hls {
this.levelController = new LevelController(this);
this.abrController = new config.abrController(this);
this.bufferController = new config.bufferController(this);
this.capLevelController = new config.capLevelController(this);
this.streamController = new config.streamController(this);
this.timelineController = new config.timelineController(this);
this.keyLoader = new KeyLoader(this);
@ -138,6 +142,7 @@ class Hls {
this.fragmentLoader.destroy();
this.levelController.destroy();
this.bufferController.destroy();
this.capLevelController.destroy();
this.streamController.destroy();
this.timelineController.destroy();
this.keyLoader.destroy();

View file

@ -36,7 +36,7 @@
"tag": "v1.3.0",
"commit": "1662093611cda3fd29125cdab94a61d3d88093da"
},
"_source": "git://github.com/polymerelements/iron-selector.git",
"_source": "git://github.com/PolymerElements/iron-selector.git",
"_target": "^1.0.0",
"_originalSource": "polymerelements/iron-selector"
"_originalSource": "PolymerElements/iron-selector"
}