From 67cadfbef55fb3929b7ee667bd0886f2d5fe869c Mon Sep 17 00:00:00 2001 From: jrivera Date: Wed, 10 Feb 2016 16:09:45 -0500 Subject: [PATCH] Fix buffer trimming so that it doesn't use seekable.start if it has a value greater than the currentTime --- src/videojs-hls.js | 7 ++--- test/videojs-hls_test.js | 58 +++++++++++++++++++++++++++++++++++----- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/videojs-hls.js b/src/videojs-hls.js index 9c0a68e4..dda32cc3 100644 --- a/src/videojs-hls.js +++ b/src/videojs-hls.js @@ -1052,7 +1052,8 @@ videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) { self = this, segment = segmentInfo.playlist.segments[segmentInfo.mediaIndex], removeToTime = 0, - seekable = this.seekable(); + seekable = this.seekable(), + currentTime = this.tech_.currentTime(); // Chrome has a hard limit of 150mb of buffer and a very conservative "garbage collector" // 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) { if (this.sourceBuffer && !this.sourceBuffer.updating) { // If we have a seekable range use that as the limit for what can be removed safely // otherwise remove anything older than 1 minute before the current play head - if (seekable.length && seekable.start(0) > 0) { + if (seekable.length && seekable.start(0) > 0 && seekable.start(0) < currentTime) { removeToTime = seekable.start(0); } else { - removeToTime = this.tech_.currentTime() - 60; + removeToTime = currentTime - 60; } if (removeToTime > 0) { diff --git a/test/videojs-hls_test.js b/test/videojs-hls_test.js index 531fd98b..90972e54 100644 --- a/test/videojs-hls_test.js +++ b/test/videojs-hls_test.js @@ -427,7 +427,7 @@ test('duration is set when the source opens after the playlist is loaded', funct equal(player.tech_.hls.mediaSource.duration , 40, 'set the duration'); }); -test('calls `remove` on sourceBuffer to when loading a live segment', function() { +test('calls `remove` based on seekable when loading a live segment', function() { var removes = [], seekable = videojs.createTimeRanges([[60, 120]]); @@ -471,7 +471,53 @@ test('calls `remove` on sourceBuffer to when loading a live segment', function() deepEqual(removes[0], [0, seekable.start(0)], 'remove called with the right range'); }); -test('calls `remove` on sourceBuffer to when loading a vod segment', function() { +test('calls `remove` based on currentTime when loading a live segment '+ + 'if seekable start is after currentTime', function() { + var + removes = [], + seekable = videojs.createTimeRanges([[0, 80]]); + + player.src({ + src: 'liveStart30sBefore.m3u8', + type: 'application/vnd.apple.mpegurl' + }); + openMediaSource(player); + player.tech_.hls.seekable = function(){ + return seekable; + }; + + openMediaSource(player); + player.tech_.hls.mediaSource.addSourceBuffer = function() { + return new (videojs.extend(videojs.EventTarget, { + constructor: function() {}, + abort: function() {}, + buffered: videojs.createTimeRange(), + appendBuffer: function() {}, + remove: function(start, end) { + removes.push([start, end]); + } + }))(); + }; + player.tech_.hls.bandwidth = 20e10; + player.tech_.triggerReady(); + standardXHRResponse(requests[0]); + player.tech_.hls.playlists.trigger('loadedmetadata'); + player.tech_.trigger('canplay'); + player.tech_.paused = function() { return false; }; + player.tech_.readyState = function(){return 1;}; + player.tech_.trigger('play'); + clock.tick(1); + // Change seekable so that it starts *after* the currentTime which was set + // based on the previous seekable range (the end of 80) + seekable = videojs.createTimeRanges([[100, 120]]); + standardXHRResponse(requests[1]); + + strictEqual(requests[0].url, 'liveStart30sBefore.m3u8', 'master playlist requested'); + equal(removes.length, 1, 'remove called'); + deepEqual(removes[0], [0, 80 - 60], 'remove called with the right range'); +}); + +test('calls `remove` based on currentTime when loading a vod segment', function() { var removes = []; player.src({ src: 'manifest/master.m3u8', @@ -1308,13 +1354,13 @@ test('After an initial media playlist 404s, we fire loadedmetadata once we succe count += 1; }); standardXHRResponse(requests.shift()); //master - equal(count, 0, + equal(count, 0, 'loadedMedia not triggered before requesting playlist'); - requests.shift().respond(404); //media - equal(count, 0, + requests.shift().respond(404); //media + equal(count, 0, 'loadedMedia not triggered after playlist 404'); standardXHRResponse(requests.shift()); //media - equal(count, 1, + equal(count, 1, 'loadedMedia triggered after successful recovery from 404'); });