c8da7b50 by marguinbc Committed by Jon-Carlos Rivera

Prevent trimming buffer between segment boundaries (#773)

* add trimBuffer_ helper function to streamline loadSegment
1 parent 47f303d1
......@@ -503,14 +503,16 @@ export default class SegmentLoader extends videojs.EventTarget {
}
/**
* load a specific segment from a request into the buffer
* trim the back buffer so we only remove content
* on segment boundaries
*
* @private
*
* @param {Object} segmentInfo - the current segment
* @returns {Number} removeToTime - the end point in time, in seconds
* that the the buffer should be trimmed.
*/
loadSegment_(segmentInfo) {
let segment;
let keyXhr;
let segmentXhr;
trimBuffer_(segmentInfo) {
let seekable = this.seekable_();
let currentTime = this.currentTime_();
let removeToTime = 0;
......@@ -531,6 +533,43 @@ export default class SegmentLoader extends videojs.EventTarget {
removeToTime = currentTime - 60;
}
// If we are going to remove time from the front of the buffer, make
// sure we aren't discarding a partial segment to avoid throwing
// PLAYER_ERR_TIMEOUT while trying to read a partially discarded segment
for (let i = 0; i <= segmentInfo.playlist.segments.length; i++) {
// Loop through the segments and calculate the duration to compare
// against the removeToTime
let removeDuration = duration(segmentInfo.playlist,
segmentInfo.playlist.mediaSequence + i,
this.expired_);
// If we are close to next segment begining, remove to end of previous
// segment instead
let previousDuration = duration(segmentInfo.playlist,
segmentInfo.playlist.mediaSequence + (i - 1),
this.expired_);
if (removeDuration >= removeToTime) {
removeToTime = previousDuration;
break;
}
}
return removeToTime;
}
/**
* load a specific segment from a request into the buffer
*
* @private
*/
loadSegment_(segmentInfo) {
let segment;
let keyXhr;
let segmentXhr;
let removeToTime = 0;
removeToTime = this.trimBuffer_(segmentInfo);
if (removeToTime > 0) {
this.sourceUpdater_.remove(0, removeToTime);
}
......
......@@ -2016,7 +2016,9 @@ QUnit.test('cleans up the buffer when loading live segments', function() {
QUnit.strictEqual(this.requests[0].url, 'liveStart30sBefore.m3u8',
'master playlist requested');
QUnit.equal(removes.length, 1, 'remove called');
QUnit.deepEqual(removes[0], [0, seekable.start(0)],
// segment-loader removes up to the segment prior to seekable.start
// to avoid crossing segment-boundaries
QUnit.deepEqual(removes[0], [0, seekable.start(0) - 10],
'remove called with the right range');
// verify stats
......@@ -2071,7 +2073,7 @@ QUnit.test('cleans up the buffer based on currentTime when loading a live segmen
QUnit.strictEqual(this.requests[0].url, 'liveStart30sBefore.m3u8', 'master playlist requested');
QUnit.equal(removes.length, 1, 'remove called');
QUnit.deepEqual(removes[0], [0, 80 - 60], 'remove called with the right range');
QUnit.deepEqual(removes[0], [0, 80 - 70], 'remove called with the right range');
// verify stats
QUnit.equal(this.player.tech_.hls.stats.mediaBytesTransferred, 16, '16 bytes');
......