Skip to content
This repository has been archived by the owner on Dec 17, 2020. It is now read-only.

Commit

Permalink
abr-controller: fine tune ABR params using best combination found for…
Browse files Browse the repository at this point in the history
… VoD and Live through AB testing

related to https://github.com/dailymotion/hls.js/pull/467
  • Loading branch information
mangui committed Jun 23, 2016
1 parent 79b1fa9 commit ed28873
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 27 deletions.
36 changes: 26 additions & 10 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -520,21 +520,37 @@ this helps playback continue in certain cases that might otherwise get stuck.
parameter should be a boolean
#### `abrEwmaFast`
#### ```abrEwmaFastLive```
(default : 5.0)
Fast bitrate Exponential moving average half-life , used to compute average bitrate for Live streams
Half of the estimate is based on the last abrEwmaFastLive seconds of sample history.
Each of the sample is weighted by the fragment loading duration.
parameter should be a float greater than 0
(default: `0.0`)
#### ```abrEwmaSlowLive```
(default : 9.0)
Slow bitrate Exponential moving average half-life , used to compute average bitrate for Live streams
Half of the estimate is based on the last abrEwmaSlowLive seconds of sample history.
Each of the sample is weighted by the fragment loading duration.
parameter should be a float greater than abrEwmaFastLive
Fast bitrate Exponential moving average half-life , used to compute average bitrate
Half of the estimate is based on the last abrEwmaFast seconds of sample history.
parameter should be a float greater than 0
#### `abrEwmaSlow`
#### ```abrEwmaFastVoD```
(default : 4.0)
Fast bitrate Exponential moving average half-life , used to compute average bitrate for VoD streams
Half of the estimate is based on the last abrEwmaFastVoD seconds of sample history.
Each of the sample is weighted by the fragment loading duration.
parameter should be a float greater than 0
(default: `0.0`)
#### ```abrEwmaSlowVoD```
(default : 15.0)
Slow bitrate Exponential moving average half-life , used to compute average bitrate
Half of the estimate is based on the last abrEwmaFast seconds of sample history.
parameter should be a float greater than abrEwmaFast
Slow bitrate Exponential moving average half-life , used to compute average bitrate for VoD streams
Half of the estimate is based on the last abrEwmaSlowVoD seconds of sample history.
Each of the sample is weighted by the fragment loading duration.
parameter should be a float greater than abrEwmaFastVoD
#### `abrBandWidthFactor`
Expand Down
2 changes: 1 addition & 1 deletion design.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ design idea is pretty simple :
- "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, stream-controller will **trigger an emergency switch down**.
- 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)
- auto quality switch algorithm is bitrate based : fragment loading bitrate is monitored and smoothed using 2 exponential weighted moving average (a fast one, to adapt quickly on bandwidth drop and a slow one, to avoid ramping up to quickly on bandwidth increase)
- [src/controller/cap-level-controller.js][]
- in charge of determining best quality level to actual size (dimensions: width and height) of the player
- [src/controller/timeline-controller.js][]
Expand Down
19 changes: 18 additions & 1 deletion src/controller/abr-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -36,6 +35,24 @@ 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);
}
frag.trequest = performance.now();
this.fragCurrent = frag;
}
Expand Down
20 changes: 7 additions & 13 deletions src/controller/ewma-bandwidth-estimator.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}


Expand Down
6 changes: 4 additions & 2 deletions src/hls.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,10 @@ class Hls {
enableCEA708Captions: true,
enableMP2TPassThrough : false,
stretchShortVideoTrack: false,
abrEwmaFast: 0,
abrEwmaSlow: 0,
abrEwmaFastLive: 5,
abrEwmaSlowLive: 9,
abrEwmaFastVoD: 4,
abrEwmaSlowVoD: 15,
abrBandWidthFactor : 0.8,
abrBandWidthUpFactor : 0.7
};
Expand Down

0 comments on commit ed28873

Please sign in to comment.