Merge pull request #549 from videojs/live-remove
Fix buffer trimming so that it doesn't use seekable.start if it has a…
Showing
2 changed files
with
56 additions
and
9 deletions
... | @@ -1130,7 +1130,8 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) { | ... | @@ -1130,7 +1130,8 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) { |
1130 | self = this, | 1130 | self = this, |
1131 | segment = segmentInfo.playlist.segments[segmentInfo.mediaIndex], | 1131 | segment = segmentInfo.playlist.segments[segmentInfo.mediaIndex], |
1132 | removeToTime = 0, | 1132 | removeToTime = 0, |
1133 | seekable = this.seekable(); | 1133 | seekable = this.seekable(), |
1134 | currentTime = this.tech_.currentTime(); | ||
1134 | 1135 | ||
1135 | // Chrome has a hard limit of 150mb of buffer and a very conservative "garbage collector" | 1136 | // Chrome has a hard limit of 150mb of buffer and a very conservative "garbage collector" |
1136 | // We manually clear out the old buffer to ensure we don't trigger the QuotaExceeded error | 1137 | // We manually clear out the old buffer to ensure we don't trigger the QuotaExceeded error |
... | @@ -1138,10 +1139,10 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) { | ... | @@ -1138,10 +1139,10 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) { |
1138 | if (this.sourceBuffer && !this.sourceBuffer.updating) { | 1139 | if (this.sourceBuffer && !this.sourceBuffer.updating) { |
1139 | // If we have a seekable range use that as the limit for what can be removed safely | 1140 | // If we have a seekable range use that as the limit for what can be removed safely |
1140 | // otherwise remove anything older than 1 minute before the current play head | 1141 | // otherwise remove anything older than 1 minute before the current play head |
1141 | if (seekable.length && seekable.start(0) > 0) { | 1142 | if (seekable.length && seekable.start(0) > 0 && seekable.start(0) < currentTime) { |
1142 | removeToTime = seekable.start(0); | 1143 | removeToTime = seekable.start(0); |
1143 | } else { | 1144 | } else { |
1144 | removeToTime = this.tech_.currentTime() - 60; | 1145 | removeToTime = currentTime - 60; |
1145 | } | 1146 | } |
1146 | 1147 | ||
1147 | if (removeToTime > 0) { | 1148 | if (removeToTime > 0) { | ... | ... |
... | @@ -427,7 +427,7 @@ test('duration is set when the source opens after the playlist is loaded', funct | ... | @@ -427,7 +427,7 @@ test('duration is set when the source opens after the playlist is loaded', funct |
427 | equal(player.tech_.hls.mediaSource.duration , 40, 'set the duration'); | 427 | equal(player.tech_.hls.mediaSource.duration , 40, 'set the duration'); |
428 | }); | 428 | }); |
429 | 429 | ||
430 | test('calls `remove` on sourceBuffer to when loading a live segment', function() { | 430 | test('calls `remove` based on seekable when loading a live segment', function() { |
431 | var | 431 | var |
432 | removes = [], | 432 | removes = [], |
433 | seekable = videojs.createTimeRanges([[60, 120]]); | 433 | seekable = videojs.createTimeRanges([[60, 120]]); |
... | @@ -471,7 +471,53 @@ test('calls `remove` on sourceBuffer to when loading a live segment', function() | ... | @@ -471,7 +471,53 @@ test('calls `remove` on sourceBuffer to when loading a live segment', function() |
471 | deepEqual(removes[0], [0, seekable.start(0)], 'remove called with the right range'); | 471 | deepEqual(removes[0], [0, seekable.start(0)], 'remove called with the right range'); |
472 | }); | 472 | }); |
473 | 473 | ||
474 | test('calls `remove` on sourceBuffer to when loading a vod segment', function() { | 474 | test('calls `remove` based on currentTime when loading a live segment '+ |
475 | 'if seekable start is after currentTime', function() { | ||
476 | var | ||
477 | removes = [], | ||
478 | seekable = videojs.createTimeRanges([[0, 80]]); | ||
479 | |||
480 | player.src({ | ||
481 | src: 'liveStart30sBefore.m3u8', | ||
482 | type: 'application/vnd.apple.mpegurl' | ||
483 | }); | ||
484 | openMediaSource(player); | ||
485 | player.tech_.hls.seekable = function(){ | ||
486 | return seekable; | ||
487 | }; | ||
488 | |||
489 | openMediaSource(player); | ||
490 | player.tech_.hls.mediaSource.addSourceBuffer = function() { | ||
491 | return new (videojs.extend(videojs.EventTarget, { | ||
492 | constructor: function() {}, | ||
493 | abort: function() {}, | ||
494 | buffered: videojs.createTimeRange(), | ||
495 | appendBuffer: function() {}, | ||
496 | remove: function(start, end) { | ||
497 | removes.push([start, end]); | ||
498 | } | ||
499 | }))(); | ||
500 | }; | ||
501 | player.tech_.hls.bandwidth = 20e10; | ||
502 | player.tech_.triggerReady(); | ||
503 | standardXHRResponse(requests[0]); | ||
504 | player.tech_.hls.playlists.trigger('loadedmetadata'); | ||
505 | player.tech_.trigger('canplay'); | ||
506 | player.tech_.paused = function() { return false; }; | ||
507 | player.tech_.readyState = function(){return 1;}; | ||
508 | player.tech_.trigger('play'); | ||
509 | clock.tick(1); | ||
510 | // Change seekable so that it starts *after* the currentTime which was set | ||
511 | // based on the previous seekable range (the end of 80) | ||
512 | seekable = videojs.createTimeRanges([[100, 120]]); | ||
513 | standardXHRResponse(requests[1]); | ||
514 | |||
515 | strictEqual(requests[0].url, 'liveStart30sBefore.m3u8', 'master playlist requested'); | ||
516 | equal(removes.length, 1, 'remove called'); | ||
517 | deepEqual(removes[0], [0, 80 - 60], 'remove called with the right range'); | ||
518 | }); | ||
519 | |||
520 | test('calls `remove` based on currentTime when loading a vod segment', function() { | ||
475 | var removes = []; | 521 | var removes = []; |
476 | player.src({ | 522 | player.src({ |
477 | src: 'manifest/master.m3u8', | 523 | src: 'manifest/master.m3u8', |
... | @@ -1308,13 +1354,13 @@ test('After an initial media playlist 404s, we fire loadedmetadata once we succe | ... | @@ -1308,13 +1354,13 @@ test('After an initial media playlist 404s, we fire loadedmetadata once we succe |
1308 | count += 1; | 1354 | count += 1; |
1309 | }); | 1355 | }); |
1310 | standardXHRResponse(requests.shift()); //master | 1356 | standardXHRResponse(requests.shift()); //master |
1311 | equal(count, 0, | 1357 | equal(count, 0, |
1312 | 'loadedMedia not triggered before requesting playlist'); | 1358 | 'loadedMedia not triggered before requesting playlist'); |
1313 | requests.shift().respond(404); //media | 1359 | requests.shift().respond(404); //media |
1314 | equal(count, 0, | 1360 | equal(count, 0, |
1315 | 'loadedMedia not triggered after playlist 404'); | 1361 | 'loadedMedia not triggered after playlist 404'); |
1316 | standardXHRResponse(requests.shift()); //media | 1362 | standardXHRResponse(requests.shift()); //media |
1317 | equal(count, 1, | 1363 | equal(count, 1, |
1318 | 'loadedMedia triggered after successful recovery from 404'); | 1364 | 'loadedMedia triggered after successful recovery from 404'); |
1319 | }); | 1365 | }); |
1320 | 1366 | ... | ... |
-
Please register or sign in to post a comment