7462bdce by Jon-Carlos Rivera

Merge pull request #470 from videojs/remove-from-buffer

Remove from buffer
2 parents 9eb8c8fe e57b99f5
......@@ -982,7 +982,26 @@ videojs.HlsHandler.prototype.blacklistCurrentPlaylist_ = function(error) {
videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) {
var
self = this,
segment = segmentInfo.playlist.segments[segmentInfo.mediaIndex];
segment = segmentInfo.playlist.segments[segmentInfo.mediaIndex],
removeToTime = 0,
seekable = this.seekable();
// 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
// on the source buffer during subsequent appends
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) {
removeToTime = seekable.start(0);
} else {
removeToTime = this.tech_.currentTime() - 60;
}
if (removeToTime > 0) {
this.sourceBuffer.remove(0, removeToTime);
}
}
// if the segment is encrypted, request the key
if (segment.key) {
......
......@@ -373,6 +373,81 @@ 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() {
var
removes = [],
seekable = videojs.createTimeRanges([[60, 120]]);
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_.trigger('play');
clock.tick(1);
standardXHRResponse(requests[1]);
strictEqual(requests[0].url, 'liveStart30sBefore.m3u8', 'master playlist requested');
equal(removes.length, 1, 'remove called');
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() {
var removes = [];
player.src({
src: 'manifest/master.m3u8',
type: 'application/vnd.apple.mpegurl'
});
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;
standardXHRResponse(requests[0]);
player.currentTime(120);
standardXHRResponse(requests[1]);
standardXHRResponse(requests[2]);
strictEqual(requests[0].url, 'manifest/master.m3u8', 'master playlist requested');
strictEqual(requests[1].url,
absoluteUrl('manifest/media3.m3u8'),
'media playlist requested');
equal(removes.length, 1, 'remove called');
deepEqual(removes[0], [0, 120 - 60], 'remove called with the right range');
});
test('codecs are passed to the source buffer', function() {
var codecs = [];
player.src({
......