1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

update components

This commit is contained in:
Luke Pulverenti 2016-06-25 02:04:53 -04:00
parent 2d86f49653
commit ab58f98cc1
27 changed files with 276 additions and 129 deletions

View file

@ -21,7 +21,6 @@ class AbrController extends EventHandler {
this._autoLevelCapping = -1;
this._nextAutoLevel = -1;
this.hls = hls;
this.bwEstimator = new EwmaBandWidthEstimator(hls);
this.onCheck = this.abandonRulesCheck.bind(this);
}
@ -34,6 +33,26 @@ class AbrController extends EventHandler {
if (!this.timer) {
this.timer = setInterval(this.onCheck, 100);
}
// lazy init of bw Estimator, rationale is that we use different params for Live/VoD
// so we need to wait for stream manifest / playlist type to instantiate it.
if (!this.bwEstimator) {
let hls = this.hls,
level = data.frag.level,
isLive = hls.levels[level].details.live,
config = hls.config,
ewmaFast, ewmaSlow;
if (isLive) {
ewmaFast = config.abrEwmaFastLive;
ewmaSlow = config.abrEwmaSlowLive;
} else {
ewmaFast = config.abrEwmaFastVoD;
ewmaSlow = config.abrEwmaSlowVoD;
}
this.bwEstimator = new EwmaBandWidthEstimator(hls,ewmaSlow,ewmaFast);
}
let frag = data.frag;
frag.trequest = performance.now();
this.fragCurrent = frag;

View file

@ -338,9 +338,10 @@ 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 error
segments = [];
this.segments = [];
event.details = ErrorDetails.BUFFER_FULL_ERROR;
hls.trigger(Event.ERROR,event);
return;
}
}
}

View file

@ -11,29 +11,23 @@ import EWMA from '../utils/ewma';
class EwmaBandWidthEstimator {
constructor(hls) {
constructor(hls,slow,fast) {
this.hls = hls;
this.defaultEstimate_ = 5e5; // 500kbps
this.minWeight_ = 0.001;
this.minDelayMs_ = 50;
this.slow_ = new EWMA(slow);
this.fast_ = new EWMA(fast);
}
sample(durationMs,numBytes) {
durationMs = Math.max(durationMs, this.minDelayMs_);
var bandwidth = 8000* numBytes / durationMs;
var bandwidth = 8000* numBytes / durationMs,
//console.log('instant bw:'+ Math.round(bandwidth));
// we weight sample using loading duration....
var weigth = durationMs / 1000;
// lazy initialization. this allows to take into account config param changes that could happen after Hls instantiation,
// but before first fragment loading. this is useful to A/B tests those params
if(!this.fast_) {
let config = this.hls.config;
this.fast_ = new EWMA(config.abrEwmaFast);
this.slow_ = new EWMA(config.abrEwmaSlow);
}
this.fast_.sample(weigth,bandwidth);
this.slow_.sample(weigth,bandwidth);
weight = durationMs / 1000;
this.fast_.sample(weight,bandwidth);
this.slow_.sample(weight,bandwidth);
}

View file

@ -285,8 +285,21 @@ class StreamController extends EventHandler {
//logger.log('find SN matching with pos:' + bufferEnd + ':' + frag.sn);
if (fragPrevious && frag.level === fragPrevious.level && frag.sn === fragPrevious.sn) {
if (frag.sn < levelDetails.endSN) {
frag = fragments[frag.sn + 1 - levelDetails.startSN];
logger.log(`SN just loaded, load next one: ${frag.sn}`);
let deltaPTS = fragPrevious.deltaPTS,
curSNIdx = frag.sn - levelDetails.startSN;
// if there is a significant delta between audio and video, larger than max allowed hole,
// it might be because video fragment does not start with a keyframe.
// let's try to load previous fragment again to get last keyframe
// then we will reload again current fragment (that way we should be able to fill the buffer hole ...)
if (deltaPTS && deltaPTS > config.maxBufferHole) {
frag = fragments[curSNIdx-1];
logger.warn(`SN just loaded, with large PTS gap between audio and video, maybe frag is not starting with a keyframe ? load previous one to try to overcome this`);
// decrement previous frag load counter to avoid frag loop loading error when next fragment will get reloaded
fragPrevious.loadCounter--;
} else {
frag = fragments[curSNIdx+1];
logger.log(`SN just loaded, load next one: ${frag.sn}`);
}
} else {
// have we reached end of VOD playlist ?
if (!levelDetails.live) {
@ -299,7 +312,7 @@ class StreamController extends EventHandler {
this.state = State.ENDED;
}
}
return;
break;
}
}
//logger.log(' loading frag ' + i +',pos/bufEnd:' + pos.toFixed(3) + '/' + bufferEnd.toFixed(3));
@ -974,11 +987,15 @@ class StreamController extends EventHandler {
}
break;
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;
logger.warn(`reduce max buffer length to ${this.config.maxMaxBufferLength}s and trigger a nextLevelSwitch to flush old buffer and fix QuotaExceededError`);
this.nextLevelSwitch();
// only reduce max buf len if in appending state
if (this.state === State.PARSING || this.state === State.PARSED) {
// reduce max buffer length as it might be too high. we do this to avoid loop flushing ...
this.config.maxMaxBufferLength/=2;
logger.warn(`reduce max buffer length to ${this.config.maxMaxBufferLength}s and switch to IDLE state`);
// increase fragment load Index to avoid frag loop loading error after buffer flush
this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold;
this.state = State.IDLE;
}
break;
default:
break;