Fix buffer trimming so that it doesn't use seekable.start if it has a value grea…
…ter than the currentTime
Showing
2 changed files
with
56 additions
and
9 deletions
... | @@ -1052,7 +1052,8 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) { | ... | @@ -1052,7 +1052,8 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) { |
1052 | self = this, | 1052 | self = this, |
1053 | segment = segmentInfo.playlist.segments[segmentInfo.mediaIndex], | 1053 | segment = segmentInfo.playlist.segments[segmentInfo.mediaIndex], |
1054 | removeToTime = 0, | 1054 | removeToTime = 0, |
1055 | seekable = this.seekable(); | 1055 | seekable = this.seekable(), |
1056 | currentTime = this.tech_.currentTime(); | ||
1056 | 1057 | ||
1057 | // Chrome has a hard limit of 150mb of buffer and a very conservative "garbage collector" | 1058 | // Chrome has a hard limit of 150mb of buffer and a very conservative "garbage collector" |
1058 | // We manually clear out the old buffer to ensure we don't trigger the QuotaExceeded error | 1059 | // We manually clear out the old buffer to ensure we don't trigger the QuotaExceeded error |
... | @@ -1060,10 +1061,10 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) { | ... | @@ -1060,10 +1061,10 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) { |
1060 | if (this.sourceBuffer && !this.sourceBuffer.updating) { | 1061 | if (this.sourceBuffer && !this.sourceBuffer.updating) { |
1061 | // If we have a seekable range use that as the limit for what can be removed safely | 1062 | // If we have a seekable range use that as the limit for what can be removed safely |
1062 | // otherwise remove anything older than 1 minute before the current play head | 1063 | // otherwise remove anything older than 1 minute before the current play head |
1063 | if (seekable.length && seekable.start(0) > 0) { | 1064 | if (seekable.length && seekable.start(0) > 0 && seekable.start(0) < currentTime) { |
1064 | removeToTime = seekable.start(0); | 1065 | removeToTime = seekable.start(0); |
1065 | } else { | 1066 | } else { |
1066 | removeToTime = this.tech_.currentTime() - 60; | 1067 | removeToTime = currentTime - 60; |
1067 | } | 1068 | } |
1068 | 1069 | ||
1069 | if (removeToTime > 0) { | 1070 | 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