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) { ...@@ -982,7 +982,26 @@ videojs.HlsHandler.prototype.blacklistCurrentPlaylist_ = function(error) {
982 videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) { 982 videojs.HlsHandler.prototype.loadSegment = function(segmentInfo) {
983 var 983 var
984 self = this, 984 self = this,
985 segment = segmentInfo.playlist.segments[segmentInfo.mediaIndex]; 985 segment = segmentInfo.playlist.segments[segmentInfo.mediaIndex],
986 removeToTime = 0,
987 seekable = this.seekable();
988
989 // Chrome has a hard limit of 150mb of buffer and a very conservative "garbage collector"
990 // We manually clear out the old buffer to ensure we don't trigger the QuotaExceeded error
991 // on the source buffer during subsequent appends
992 if (this.sourceBuffer && !this.sourceBuffer.updating) {
993 // If we have a seekable range use that as the limit for what can be removed safely
994 // otherwise remove anything older than 1 minute before the current play head
995 if (seekable.length && seekable.start(0) > 0) {
996 removeToTime = seekable.start(0);
997 } else {
998 removeToTime = this.tech_.currentTime() - 60;
999 }
1000
1001 if (removeToTime > 0) {
1002 this.sourceBuffer.remove(0, removeToTime);
1003 }
1004 }
986 1005
987 // if the segment is encrypted, request the key 1006 // if the segment is encrypted, request the key
988 if (segment.key) { 1007 if (segment.key) {
......
...@@ -373,6 +373,81 @@ test('duration is set when the source opens after the playlist is loaded', funct ...@@ -373,6 +373,81 @@ test('duration is set when the source opens after the playlist is loaded', funct
373 equal(player.tech_.hls.mediaSource.duration , 40, 'set the duration'); 373 equal(player.tech_.hls.mediaSource.duration , 40, 'set the duration');
374 }); 374 });
375 375
376 test('calls `remove` on sourceBuffer to when loading a live segment', function() {
377 var
378 removes = [],
379 seekable = videojs.createTimeRanges([[60, 120]]);
380
381 player.src({
382 src: 'liveStart30sBefore.m3u8',
383 type: 'application/vnd.apple.mpegurl'
384 });
385 openMediaSource(player);
386 player.tech_.hls.seekable = function(){
387 return seekable;
388 };
389
390 openMediaSource(player);
391 player.tech_.hls.mediaSource.addSourceBuffer = function() {
392 return new (videojs.extend(videojs.EventTarget, {
393 constructor: function() {},
394 abort: function() {},
395 buffered: videojs.createTimeRange(),
396 appendBuffer: function() {},
397 remove: function(start, end) {
398 removes.push([start, end]);
399 }
400 }))();
401 };
402 player.tech_.hls.bandwidth = 20e10;
403 player.tech_.triggerReady();
404 standardXHRResponse(requests[0]);
405
406 player.tech_.hls.playlists.trigger('loadedmetadata');
407 player.tech_.trigger('canplay');
408 player.tech_.paused = function() { return false; };
409 player.tech_.trigger('play');
410
411 clock.tick(1);
412 standardXHRResponse(requests[1]);
413
414 strictEqual(requests[0].url, 'liveStart30sBefore.m3u8', 'master playlist requested');
415 equal(removes.length, 1, 'remove called');
416 deepEqual(removes[0], [0, seekable.start(0)], 'remove called with the right range');
417 });
418
419 test('calls `remove` on sourceBuffer to when loading a vod segment', function() {
420 var removes = [];
421 player.src({
422 src: 'manifest/master.m3u8',
423 type: 'application/vnd.apple.mpegurl'
424 });
425 openMediaSource(player);
426 player.tech_.hls.mediaSource.addSourceBuffer = function() {
427 return new (videojs.extend(videojs.EventTarget, {
428 constructor: function() {},
429 abort: function() {},
430 buffered: videojs.createTimeRange(),
431 appendBuffer: function() {},
432 remove: function(start, end) {
433 removes.push([start, end]);
434 }
435 }))();
436 };
437 player.tech_.hls.bandwidth = 20e10;
438 standardXHRResponse(requests[0]);
439 player.currentTime(120);
440 standardXHRResponse(requests[1]);
441 standardXHRResponse(requests[2]);
442
443 strictEqual(requests[0].url, 'manifest/master.m3u8', 'master playlist requested');
444 strictEqual(requests[1].url,
445 absoluteUrl('manifest/media3.m3u8'),
446 'media playlist requested');
447 equal(removes.length, 1, 'remove called');
448 deepEqual(removes[0], [0, 120 - 60], 'remove called with the right range');
449 });
450
376 test('codecs are passed to the source buffer', function() { 451 test('codecs are passed to the source buffer', function() {
377 var codecs = []; 452 var codecs = [];
378 player.src({ 453 player.src({
......