UNPKG

3.96 kBJavaScriptView Raw
1import { module, test } from 'qunit';
2import {
3 movingAverageBandwidthSelector,
4 minRebufferMaxBandwidthSelector
5} from '../src/playlist-selectors';
6import Config from '../src/config';
7
8module('Playlist Selectors', {
9 beforeEach(assert) {
10 const video = document.createElement('video');
11
12 this.hls = {
13 tech_: {
14 el() {
15 return video;
16 }
17 },
18 playlists: {
19 master: {
20 playlists: []
21 }
22 }
23 };
24 },
25 afterEach() {
26
27 }
28});
29
30test('Exponential moving average has a configurable decay parameter', function(assert) {
31 let playlist;
32 const instantAverage = movingAverageBandwidthSelector(1.0);
33
34 this.hls.playlists.master.playlists = [
35 { attributes: { BANDWIDTH: 1 } },
36 { attributes: { BANDWIDTH: 50 } },
37 { attributes: { BANDWIDTH: 100 } }
38 ];
39 this.hls.systemBandwidth = 50 * Config.BANDWIDTH_VARIANCE + 1;
40 playlist = instantAverage.call(this.hls);
41 assert.equal(playlist.attributes.BANDWIDTH, 50, 'selected the middle playlist');
42
43 this.hls.systemBandwidth = 100 * Config.BANDWIDTH_VARIANCE + 1;
44 playlist = instantAverage.call(this.hls);
45 assert.equal(playlist.attributes.BANDWIDTH, 100, 'selected the top playlist');
46
47 const fiftyPercentDecay = movingAverageBandwidthSelector(0.5);
48
49 this.hls.systemBandwidth = 100 * Config.BANDWIDTH_VARIANCE + 1;
50 playlist = fiftyPercentDecay.call(this.hls);
51 assert.equal(playlist.attributes.BANDWIDTH, 100, 'selected the top playlist');
52
53 // average = decay * systemBandwidth + (1 - decay) * average
54 // bandwidth = 0.5 * systemBandwidth + 0.5 * (100 * variance + 1)
55 // 50 * variance + 1 = 0.5 * (systemBandwidth + (100 * variance + 1))
56 // 2 * 50 * variance + 2 = systemBandwidth + (100 * variance + 1)
57 // 100 * variance + 2 - (100 * variance + 1) = systemBandwidth
58 // 1 = systemBandwidth
59 this.hls.systemBandwidth = 1;
60 playlist = fiftyPercentDecay.call(this.hls);
61 assert.equal(playlist.attributes.BANDWIDTH, 50, 'selected the middle playlist');
62});
63
64test('minRebufferMaxBandwidthSelector picks highest rendition without rebuffering',
65function(assert) {
66 let master = this.hls.playlists.master;
67 let currentTime = 0;
68 let bandwidth = 2000;
69 let duration = 100;
70 let segmentDuration = 10;
71 let timeUntilRebuffer = 5;
72 let currentTimeline = 0;
73 let syncController = {
74 getSyncPoint: (playlist) => playlist.syncPoint
75 };
76
77 const settings = () => {
78 return {
79 master,
80 currentTime,
81 bandwidth,
82 duration,
83 segmentDuration,
84 timeUntilRebuffer,
85 currentTimeline,
86 syncController
87 };
88 };
89
90 master.playlists = [
91 { attributes: { BANDWIDTH: 100 }, syncPoint: false },
92 { attributes: { BANDWIDTH: 500 }, syncPoint: false },
93 { attributes: { BANDWIDTH: 1000 }, syncPoint: false },
94 { attributes: { BANDWIDTH: 2000 }, syncPoint: true },
95 { attributes: { BANDWIDTH: 5000 }, syncPoint: false }
96 ];
97
98 let result = minRebufferMaxBandwidthSelector(settings());
99
100 assert.equal(result.playlist, master.playlists[1], 'selected the correct playlist');
101 assert.equal(result.rebufferingImpact, 0, 'impact on rebuffering is 0');
102
103 master.playlists = [
104 { attributes: { BANDWIDTH: 100 }, syncPoint: false },
105 { attributes: { BANDWIDTH: 500 }, syncPoint: false },
106 { attributes: { BANDWIDTH: 1000 }, syncPoint: true },
107 { attributes: { BANDWIDTH: 2000 }, syncPoint: true },
108 { attributes: { BANDWIDTH: 5000 }, syncPoint: false }
109 ];
110
111 result = minRebufferMaxBandwidthSelector(settings());
112
113 assert.equal(result.playlist, master.playlists[2], 'selected the corerct playlist');
114 assert.equal(result.rebufferingImpact, 0, 'impact on rebuffering is 0');
115
116 bandwidth = 500;
117 timeUntilRebuffer = 3;
118
119 result = minRebufferMaxBandwidthSelector(settings());
120
121 assert.equal(result.playlist, master.playlists[0], 'selected the correct playlist');
122 assert.equal(result.rebufferingImpact, 1, 'impact on rebuffering is 1 second');
123});