64bbbe93 by David LaPalomento

@dmlap quicker quality switches when bandwidth changes. Closes #285.

2 parents 93d4e050 54977aa4
...@@ -10,6 +10,7 @@ CHANGELOG ...@@ -10,6 +10,7 @@ CHANGELOG
10 * @mikrohard: Trim whitespace in playlist. ([view](https://github.com/videojs/videojs-contrib-hls/pull/282)) 10 * @mikrohard: Trim whitespace in playlist. ([view](https://github.com/videojs/videojs-contrib-hls/pull/282))
11 * @dmlap add a contrib option to merge PRs without squashing ([view](https://github.com/videojs/videojs-contrib-hls/pull/287)) 11 * @dmlap add a contrib option to merge PRs without squashing ([view](https://github.com/videojs/videojs-contrib-hls/pull/287))
12 * @mikrohard allow playback of TS files with NITs. Don't warn about PCR PIDs. ([view](https://github.com/videojs/videojs-contrib-hls/pull/284)) 12 * @mikrohard allow playback of TS files with NITs. Don't warn about PCR PIDs. ([view](https://github.com/videojs/videojs-contrib-hls/pull/284))
13 * @dmlap quicker quality switches when bandwidth changes. ([view](https://github.com/videojs/videojs-contrib-hls/pull/285))
13 14
14 -------------------- 15 --------------------
15 16
......
...@@ -315,6 +315,12 @@ videojs.Hls.prototype.setCurrentTime = function(currentTime) { ...@@ -315,6 +315,12 @@ videojs.Hls.prototype.setCurrentTime = function(currentTime) {
315 return 0; 315 return 0;
316 } 316 }
317 317
318 // it's clearly an edge-case but don't thrown an error if asked to
319 // seek within an empty playlist
320 if (!this.playlists.media().segments) {
321 return 0;
322 }
323
318 // save the seek target so currentTime can report it correctly 324 // save the seek target so currentTime can report it correctly
319 // while the seek is pending 325 // while the seek is pending
320 this.lastSeekedTime_ = currentTime; 326 this.lastSeekedTime_ = currentTime;
...@@ -578,6 +584,11 @@ videojs.Hls.prototype.fillBuffer = function(offset) { ...@@ -578,6 +584,11 @@ videojs.Hls.prototype.fillBuffer = function(offset) {
578 return; 584 return;
579 } 585 }
580 586
587 // if a playlist switch is in progress, wait for it to finish
588 if (this.playlists.state === 'SWITCHING_MEDIA') {
589 return;
590 }
591
581 // if the video has finished downloading, stop trying to buffer 592 // if the video has finished downloading, stop trying to buffer
582 segment = this.playlists.media().segments[this.mediaIndex]; 593 segment = this.playlists.media().segments[this.mediaIndex];
583 if (!segment) { 594 if (!segment) {
......
...@@ -976,6 +976,35 @@ test('only appends one segment at a time', function() { ...@@ -976,6 +976,35 @@ test('only appends one segment at a time', function() {
976 equal(appends, 0, 'did not append while updating'); 976 equal(appends, 0, 'did not append while updating');
977 }); 977 });
978 978
979 test('waits to download new segments until the media playlist is stable', function() {
980 var media;
981 player.src({
982 src: 'manifest/master.m3u8',
983 type: 'application/vnd.apple.mpegurl'
984 });
985 openMediaSource(player);
986 standardXHRResponse(requests.shift()); // master
987 player.hls.bandwidth = 1; // make sure we stay on the lowest variant
988 standardXHRResponse(requests.shift()); // media
989
990 // mock a playlist switch
991 media = player.hls.playlists.media();
992 player.hls.playlists.media = function() {
993 return media;
994 };
995 player.hls.playlists.state = 'SWITCHING_MEDIA';
996
997 standardXHRResponse(requests.shift()); // segment 0
998
999 equal(requests.length, 0, 'no requests outstanding');
1000 player.hls.checkBuffer_();
1001 equal(requests.length, 0, 'delays segment fetching');
1002
1003 player.hls.playlists.state = 'LOADED_METADATA';
1004 player.hls.checkBuffer_();
1005 equal(requests.length, 1, 'resumes segment fetching');
1006 });
1007
979 test('cancels outstanding XHRs when seeking', function() { 1008 test('cancels outstanding XHRs when seeking', function() {
980 player.src({ 1009 player.src({
981 src: 'manifest/media.m3u8', 1010 src: 'manifest/media.m3u8',
...@@ -1321,6 +1350,19 @@ test('segment 500 should trigger MEDIA_ERR_ABORTED', function () { ...@@ -1321,6 +1350,19 @@ test('segment 500 should trigger MEDIA_ERR_ABORTED', function () {
1321 equal(4, player.hls.error.code, 'Player error code should be set to MediaError.MEDIA_ERR_ABORTED'); 1350 equal(4, player.hls.error.code, 'Player error code should be set to MediaError.MEDIA_ERR_ABORTED');
1322 }); 1351 });
1323 1352
1353 test('seeking in an empty playlist is a non-erroring noop', function() {
1354 player.src({
1355 src: 'manifest/empty-live.m3u8',
1356 type: 'application/vnd.apple.mpegurl'
1357 });
1358 openMediaSource(player);
1359
1360 requests.shift().respond(200, null, '#EXTM3U\n');
1361
1362 player.currentTime(183);
1363 equal(player.currentTime(), 0, 'remains at time zero');
1364 });
1365
1324 test('duration is Infinity for live playlists', function() { 1366 test('duration is Infinity for live playlists', function() {
1325 player.src({ 1367 player.src({
1326 src: 'http://example.com/manifest/missingEndlist.m3u8', 1368 src: 'http://example.com/manifest/missingEndlist.m3u8',
......