c6b4a49f by David LaPalomento

Don't abort a playlist request just to re-issue the same request

Check the outstanding request URL before aborting playlist requests when a switch is requested. Don't filter out requests that are generated as a result of another request finishing in the switcher simulator. Actual playlist switching is showing up in the graph now.
1 parent 6038397b
...@@ -147,10 +147,17 @@ ...@@ -147,10 +147,17 @@
147 return; 147 return;
148 } 148 }
149 149
150
151
150 loader.state = 'SWITCHING_MEDIA'; 152 loader.state = 'SWITCHING_MEDIA';
151 153
152 // abort any outstanding playlist refreshes 154 // there is already an outstanding playlist request
153 if (request) { 155 if (request) {
156 if (resolveUrl(loader.master.uri, playlist.uri) === request.url) {
157 // requesting to switch to the same playlist multiple times
158 // has no effect after the first
159 return;
160 }
154 request.abort(); 161 request.abort();
155 request = null; 162 request = null;
156 } 163 }
......
...@@ -563,6 +563,7 @@ xhr = videojs.Hls.xhr = function(url, callback) { ...@@ -563,6 +563,7 @@ xhr = videojs.Hls.xhr = function(url, callback) {
563 563
564 request = new window.XMLHttpRequest(); 564 request = new window.XMLHttpRequest();
565 request.open(options.method, url); 565 request.open(options.method, url);
566 request.url = url;
566 567
567 if (options.responseType) { 568 if (options.responseType) {
568 request.responseType = options.responseType; 569 request.responseType = options.responseType;
......
...@@ -349,6 +349,27 @@ ...@@ -349,6 +349,27 @@
349 strictEqual(requests.length, 0, 'no requests is sent'); 349 strictEqual(requests.length, 0, 'no requests is sent');
350 }); 350 });
351 351
352 test('does not abort requests when the same playlist is re-requested', function() {
353 var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
354 requests.pop().respond(200, null,
355 '#EXTM3U\n' +
356 '#EXT-X-STREAM-INF:BANDWIDTH=1\n' +
357 'low.m3u8\n' +
358 '#EXT-X-STREAM-INF:BANDWIDTH=2\n' +
359 'high.m3u8\n');
360 requests.pop().respond(200, null,
361 '#EXTM3U\n' +
362 '#EXT-X-MEDIA-SEQUENCE:0\n' +
363 '#EXTINF:10,\n' +
364 'low-0.ts\n' +
365 '#EXT-X-ENDLIST\n');
366 loader.media('high.m3u8');
367 loader.media('high.m3u8');
368
369 strictEqual(requests.length, 1, 'made only one request');
370 ok(!requests[0].aborted, 'request not aborted');
371 });
372
352 test('throws an error if a media switch is initiated too early', function() { 373 test('throws an error if a media switch is initiated too early', function() {
353 var loader = new videojs.Hls.PlaylistLoader('master.m3u8'); 374 var loader = new videojs.Hls.PlaylistLoader('master.m3u8');
354 375
......
...@@ -135,7 +135,7 @@ ...@@ -135,7 +135,7 @@
135 var master = '#EXTM3U\n' + 135 var master = '#EXTM3U\n' +
136 options.playlists.reduce(function(playlists, value) { 136 options.playlists.reduce(function(playlists, value) {
137 return playlists + 137 return playlists +
138 '#EXT-X-STREAM-INF:' + value + '\n' + 138 '#EXT-X-STREAM-INF:BANDWIDTH=' + value + '\n' +
139 'playlist-' + value + '\n'; 139 'playlist-' + value + '\n';
140 }, ''), 140 }, ''),
141 buffered = 0, 141 buffered = 0,
...@@ -171,26 +171,23 @@ ...@@ -171,26 +171,23 @@
171 }); 171 });
172 172
173 // deliver responses if they're ready 173 // deliver responses if they're ready
174 requests = requests.reduce(function(remaining, request) { 174 requests.forEach(function(request, i) {
175 var arrival = request.startTime + propagationDelay, 175 var arrival = request.startTime + propagationDelay,
176 segmentSize = +request.url.match(/(\d+)-\d+$/)[1] * segmentDuration; 176 segmentSize;
177 177
178 // playlist responses 178 // playlist responses
179 if (/playlist-\d+$/.test(request.url)) { 179 if (/playlist-\d+$/.test(request.url)) {
180 // playlist responses have no trasmission time 180 // for simplicity, playlist responses have zero trasmission time
181 if (t === arrival) { 181 if (t === arrival) {
182 request.respond(200, null, playlistResponse(+requests[0].url.match(/\d+$/))); 182 request.respond(200, null, playlistResponse(+requests[0].url.match(/\d+$/)));
183 return remaining; 183 // the request is completed
184 return requests.splice(requests.indexOf(request), 1);
184 } 185 }
185 // the response has not arrived. re-enqueue it for later. 186 return;
186 return remaining.concat(request);
187 } 187 }
188 188
189 // segment responses 189 // segment responses
190 if (t >= arrival) { 190 segmentSize = +request.url.match(/(\d+)-\d+$/)[1] * segmentDuration;
191 request.delivered += results.bandwidth[t].bandwidth;
192
193 }
194 // segment response headers arrive after the propogation delay 191 // segment response headers arrive after the propogation delay
195 if (t === arrival) { 192 if (t === arrival) {
196 results.playlists.push({ 193 results.playlists.push({
...@@ -205,12 +202,18 @@ ...@@ -205,12 +202,18 @@
205 if (request.delivered >= segmentSize) { 202 if (request.delivered >= segmentSize) {
206 buffered += segmentDuration; 203 buffered += segmentDuration;
207 request.status = 200; 204 request.status = 200;
208 request.response = new Uint8Array(segmentSize); 205 request.response = new Uint8Array(segmentSize * 0.125);
209 request.setResponseBody(''); 206 request.setResponseBody('');
210 return remaining; 207 // the request is completed
208 return requests.splice(requests.indexOf(request), 1);
209 }
210 // transmit the bits for this tick
211 if (t >= arrival) {
212 request.delivered += results.bandwidth[t].bandwidth;
213
211 } 214 }
212 // response has not arrived fully, re-enqueue it for later 215 // response has not arrived fully
213 return remaining.concat(request); 216 return;
214 }, []); 217 }, []);
215 218
216 // simulate playback 219 // simulate playback
......