forked from video-dev/hls.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathabr-controller.js
84 lines (71 loc) · 2.44 KB
/
abr-controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*
* simple ABR Controller
*/
import Event from '../events';
class AbrController {
constructor(hls) {
this.hls = hls;
this.lastfetchlevel = 0;
this._autoLevelCapping = -1;
this._nextAutoLevel = -1;
this.onflp = this.onFragmentLoadProgress.bind(this);
hls.on(Event.FRAG_LOAD_PROGRESS, this.onflp);
}
destroy() {
this.hls.off(Event.FRAG_LOAD_PROGRESS, this.onflp);
}
onFragmentLoadProgress(event, data) {
var stats = data.stats;
if (stats.aborted === undefined) {
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}`);
}
}
/** Return the capping/max level value that could be used by automatic level selection algorithm **/
get autoLevelCapping() {
return this._autoLevelCapping;
}
/** set the capping/max level value that could be used by automatic level selection algorithm **/
set autoLevelCapping(newLevel) {
this._autoLevelCapping = newLevel;
}
get nextAutoLevel() {
var lastbw = this.lastbw, hls = this.hls,adjustedbw, i, maxAutoLevel;
if (this._autoLevelCapping === -1) {
maxAutoLevel = hls.levels.length - 1;
} else {
maxAutoLevel = this._autoLevelCapping;
}
if (this._nextAutoLevel !== -1) {
var nextLevel = Math.min(this._nextAutoLevel,maxAutoLevel);
if (nextLevel === this.lastfetchlevel) {
this._nextAutoLevel = -1;
} else {
return nextLevel;
}
}
// follow algorithm captured from stagefright :
// https://android.googlesource.com/platform/frameworks/av/+/master/media/libstagefright/httplive/LiveSession.cpp
// Pick the highest bandwidth stream below or equal to estimated bandwidth.
for (i = 0; i <= maxAutoLevel; i++) {
// 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) {
adjustedbw = 0.8 * lastbw;
} else {
adjustedbw = 0.7 * lastbw;
}
if (adjustedbw < hls.levels[i].bitrate) {
return Math.max(0, i - 1);
}
}
return i - 1;
}
set nextAutoLevel(nextLevel) {
this._nextAutoLevel = nextLevel;
}
}
export default AbrController;