c0045796 by David LaPalomento

Scale the initial bandwidth estimate

Multiply the bandwidth measurement from the master playlist by five to account for the higher ratio of latency to throughput for this request relative to segments. Using the bandwidth number directly was almost always resulting in very low initial bandwidth estimates and poorer quality startup than necessary. The scaling factor was obtained by testing a number of videos from a high throughput/low latency connection as an upper bound and the same connection throttled to "DSL" levels with Network Link Conditioner for the lower bound. Update the playlist switching simulator to apply initial bandwidth estimates and reduce the simulation duration a bit so that the early behavior is more visible.
1 parent bc2d1c4d
...@@ -138,7 +138,14 @@ videojs.Hls.prototype.handleSourceOpen = function() { ...@@ -138,7 +138,14 @@ videojs.Hls.prototype.handleSourceOpen = function() {
138 }; 138 };
139 139
140 oldMediaPlaylist = this.playlists.media(); 140 oldMediaPlaylist = this.playlists.media();
141 this.setBandwidth(this.playlists); 141 // the bandwidth estimate for the first segment is based on round trip
142 // time for the master playlist. the master playlist is almost always
143 // tiny so the round trip time is dominated by latency and so the
144 // computed bandwidth is much lower than steady-state. to account for
145 // this, we scale the bandwidth estimate from the master playlist.
146 this.setBandwidth({
147 bandwidth: this.playlists.bandwidth * 5
148 });
142 149
143 selectedPlaylist = this.selectPlaylist(); 150 selectedPlaylist = this.selectPlaylist();
144 oldBitrate = oldMediaPlaylist.attributes && 151 oldBitrate = oldMediaPlaylist.attributes &&
......
...@@ -94,11 +94,11 @@ ...@@ -94,11 +94,11 @@
94 </p> 94 </p>
95 The video is available at 95 The video is available at
96 <ul> 96 <ul>
97 <li><input class=bitrate type=number min=1 value=65536> bits per second</li> 97 <li><input class=bitrate type=number min=1 value=312000> bits per second</li>
98 <li><input class=bitrate type=number min=1 value=153600> bits per second</li> 98 <li><input class=bitrate type=number min=1 value=524000> bits per second</li>
99 <li><input class=bitrate type=number min=1 value=450560> bits per second</li> 99 <li><input class=bitrate type=number min=1 value=1296000> bits per second</li>
100 <li><input class=bitrate type=number min=1 value=921600> bits per second</li> 100 <li><input class=bitrate type=number min=1 value=2125000> bits per second</li>
101 <li><input class=bitrate type=number min=1 value=1536000> bits per second</li> 101 <li><input class=bitrate type=number min=1 value=3125000> bits per second</li>
102 </ul> 102 </ul>
103 </form> 103 </form>
104 </section> 104 </section>
......
1 (function(window, document) { 1 (function(window, document) {
2 'use strict'; 2 'use strict';
3 var segmentDuration = 9, // seconds 3 var segmentDuration = 9, // seconds
4 segmentCount = 100, 4 segmentCount = 10,
5 duration = segmentDuration * segmentCount, 5 duration = segmentDuration * segmentCount,
6 propagationDelay = 0.5, 6 propagationDelay = 0.5,
7 7
...@@ -171,13 +171,21 @@ ...@@ -171,13 +171,21 @@
171 return currentTime; 171 return currentTime;
172 }; 172 };
173 173
174 bandwidths.sort(function(left, right) {
175 return left.time - right.time;
176 });
177
174 // respond to the playlist requests 178 // respond to the playlist requests
179 requests[0].bandwidth = bandwidths[0].bandwidth;
175 requests.shift().respond(200, null, master); 180 requests.shift().respond(200, null, master);
181 requests[0].bandwidth = bandwidths[0].bandwidth;
176 requests[0].respond(200, null, playlistResponse(+requests[0].url.match(/\d+$/))); 182 requests[0].respond(200, null, playlistResponse(+requests[0].url.match(/\d+$/)));
177 requests.shift(); 183 requests.shift();
178 184
179 bandwidths.sort(function(left, right) { 185 // record the measured bandwidth for the playlist requests
180 return left.time - right.time; 186 results.effectiveBandwidth.push({
187 time: 0,
188 bandwidth: player.hls.bandwidth
181 }); 189 });
182 190
183 // pre-calculate the bandwidth at each second 191 // pre-calculate the bandwidth at each second
......
...@@ -618,6 +618,21 @@ test('selects a playlist below the current bandwidth', function() { ...@@ -618,6 +618,21 @@ test('selects a playlist below the current bandwidth', function() {
618 'the low bitrate stream is selected'); 618 'the low bitrate stream is selected');
619 }); 619 });
620 620
621 test('scales the bandwidth estimate for the first segment', function() {
622 player.src({
623 src: 'manifest/master.m3u8',
624 type: 'application/vnd.apple.mpegurl'
625 });
626 openMediaSource(player);
627
628 requests[0].bandwidth = 500;
629 requests.shift().respond(200, null,
630 '#EXTM3U\n' +
631 '#EXT-X-PLAYLIST-TYPE:VOD\n' +
632 '#EXT-X-TARGETDURATION:10\n');
633 equal(player.hls.bandwidth, 500 * 5, 'scaled the bandwidth estimate by 5');
634 });
635
621 test('raises the minimum bitrate for a stream proportionially', function() { 636 test('raises the minimum bitrate for a stream proportionially', function() {
622 var playlist; 637 var playlist;
623 player.src({ 638 player.src({
......