e266db29 by jrivera

Add/fix tests related to segment annotation and fetching

1 parent 6ea1ad65
......@@ -450,7 +450,7 @@
break;
} else {
knownStart = segment.end;
startIndex = i;
startIndex = i + 1;
}
}
}
......@@ -494,9 +494,14 @@
return i;
}
}
// We haven't found a segment so load the first one
// We haven't found a segment so load the first one if time is zero
if (time === 0) {
return 0;
} else {
return -1;
}
} else {
// We known nothing so walk from the front of the playlist,
// subtracting durations until we find a segment that contains
// time and return it
......
......@@ -10,8 +10,8 @@ var
// A fudge factor to apply to advertised playlist bitrates to account for
// temporary flucations in client bandwidth
bandwidthVariance = 1.2,
blacklistDuration = 5 * 60 * 1000, // 2 minute blacklist
TIME_FUDGE_FACTOR = 1 / 60, // Fudge factor to account for TimeRanges rounding
blacklistDuration = 5 * 60 * 1000, // 5 minute blacklist
TIME_FUDGE_FACTOR = 1 / 30, // Fudge factor to account for TimeRanges rounding
Component = videojs.getComponent('Component'),
// The amount of time to wait between checking the state of the buffer
......@@ -242,32 +242,52 @@ videojs.HlsHandler.prototype.handleSourceOpen = function() {
}
};
// Search for any end-points in `update` that do not also exist
// in `original`.
// Search for a likely end time for the segment that was just appened
// based on the state of the `buffered` property before and after the
// append.
// If we found only one such uncommon end-point return it.
videojs.Hls.findSoleUncommonTimeRangesEnd_ = function(original, update) {
var result = [], originalEnds = [];
// if original or update are falsey, return an empty list of
// additions
if (!original || !update) {
return result;
}
var
i, start, end,
result = [],
edges = [],
// In order to qualify as a possible candidate, the end point must:
// 1) Not have already existed in the `original` ranges
// 2) Not result from the shrinking of a range that already existed
// in the `original` ranges
// 3) Not be contained inside of a range that existed in `original`
checkEdges = function(span) {
return (span[0] <= end && span[1] > end) || span[1] === end;
};
// Save all the end-points in the `original` TimeRanges object
if (original) {
// Save all the edges in the `original` TimeRanges object
for (i = 0; i < original.length; i++) {
originalEnds.push(original.end(i));
start = original.start(i);
end = original.end(i);
edges.push([start, end]);
}
}
if (update) {
// Save any end-points in `update` that are not in the `original`
// TimeRanges object
for (i = 0; i < update.length; i++) {
if (originalEnds.indexOf(update.end(i)) === -1) {
result.push(update.end(i));
start = update.start(i);
end = update.end(i);
if (edges.some(checkEdges)) {
continue;
}
// at this point it must be a unique non-shrinking end edge
result.push(end);
}
}
// Return null if didn't find exactly one differing end-point
// we err on the side of caution and return null if didn't find
// exactly *one* differing end edge in the search above
if (result.length !== 1) {
return null;
} else {
......@@ -719,10 +739,6 @@ videojs.HlsHandler.prototype.checkBuffer_ = function() {
* append bytes into the SourceBuffer.
*/
videojs.HlsHandler.prototype.startCheckingBuffer_ = function() {
// if the player ever stalls, check if there is video data available
// to append immediately
this.tech_.on('waiting', (this.drainBuffer).bind(this));
this.checkBuffer_();
};
......@@ -735,7 +751,6 @@ videojs.HlsHandler.prototype.stopCheckingBuffer_ = function() {
window.clearTimeout(this.checkBufferTimeout_);
this.checkBufferTimeout_ = null;
}
this.tech_.off('waiting', this.drainBuffer);
};
var filterBufferedRanges = function(predicate) {
......
......@@ -811,7 +811,7 @@
'1001.ts\n' +
'#EXTINF:5,\n' +
'1002.ts\n');
loader.media().segments[0].start = 150;
loader.media().segments[0].end = 154;
equal(loader.getMediaIndexForTime_(0), -1, 'the lowest returned value is negative one');
equal(loader.getMediaIndexForTime_(45), -1, 'expired content returns negative one');
......@@ -819,6 +819,7 @@
equal(loader.getMediaIndexForTime_(50 + 100), 0, 'calculates the earliest available position');
equal(loader.getMediaIndexForTime_(50 + 100 + 2), 0, 'calculates within the first segment');
equal(loader.getMediaIndexForTime_(50 + 100 + 2), 0, 'calculates within the first segment');
equal(loader.getMediaIndexForTime_(50 + 100 + 4), 1, 'calculates within the second segment');
equal(loader.getMediaIndexForTime_(50 + 100 + 4.5), 1, 'calculates within the second segment');
equal(loader.getMediaIndexForTime_(50 + 100 + 6), 1, 'calculates within the second segment');
});
......@@ -837,9 +838,9 @@
loader.expired_ = 160;
// annotate the first segment with a start time
// this number would be coming from the Source Buffer in practice
loader.media().segments[0].start = 150;
loader.media().segments[0].end = 150;
equal(loader.getMediaIndexForTime_(151), 0, 'prefers the value on the first segment');
equal(loader.getMediaIndexForTime_(149), 0, 'prefers the value on the first segment');
clock.tick(10 * 1000); // trigger a playlist refresh
requests.shift().respond(200, null,
......
......@@ -2745,47 +2745,72 @@ test('does not download segments if preload option set to none', function() {
module('Buffer Inspection');
test('detects time range edges added by updates', function() {
var edges;
test('detects time range end-point changed by updates', function() {
var edge;
edges = videojs.Hls.bufferedAdditions_(videojs.createTimeRange([[0, 10]]),
// Single-range changes
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10]]),
videojs.createTimeRange([[0, 11]]));
deepEqual(edges, [{ end: 11 }], 'detected a forward addition');
strictEqual(edge, 11, 'detected a forward addition');
edges = videojs.Hls.bufferedAdditions_(videojs.createTimeRange([[5, 10]]),
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[5, 10]]),
videojs.createTimeRange([[0, 10]]));
deepEqual(edges, [{ start: 0 }], 'detected a backward addition');
strictEqual(edge, null, 'ignores backward addition');
edges = videojs.Hls.bufferedAdditions_(videojs.createTimeRange([[5, 10]]),
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[5, 10]]),
videojs.createTimeRange([[0, 11]]));
deepEqual(edges, [
{ start: 0 }, { end: 11 }
], 'detected forward and backward additions');
strictEqual(edge, 11, 'detected a forward addition & ignores a backward addition');
edges = videojs.Hls.bufferedAdditions_(videojs.createTimeRange([[0, 10]]),
videojs.createTimeRange([[0, 10]]));
deepEqual(edges, [], 'detected no addition');
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10]]),
videojs.createTimeRange([[0, 9]]));
strictEqual(edge, null, 'ignores a backwards addition resulting from a shrinking range');
edges = videojs.Hls.bufferedAdditions_(videojs.createTimeRange([]),
videojs.createTimeRange([[0, 10]]));
deepEqual(edges, [
{ start: 0 },
{ end: 10 }
], 'detected an initial addition');
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10]]),
videojs.createTimeRange([[2, 7]]));
strictEqual(edge, null, 'ignores a forward & backwards addition resulting from a shrinking range');
edges = videojs.Hls.bufferedAdditions_(videojs.createTimeRange([[0, 10]]),
videojs.createTimeRange([[0, 10], [20, 30]]));
deepEqual(edges, [
{ start: 20 },
{ end: 30}
], 'detected a non-contiguous addition');
});
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[2, 10]]),
videojs.createTimeRange([[0, 7]]));
strictEqual(edge, null, 'ignores a forward & backwards addition resulting from a range shifted backward');
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[2, 10]]),
videojs.createTimeRange([[5, 15]]));
strictEqual(edge, 15, 'detected a forwards addition resulting from a range shifted foward');
// Multiple-range changes
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10]]),
videojs.createTimeRange([[0, 11], [12, 15]]));
strictEqual(edge, null, 'ignores multiple new forward additions');
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10], [20, 40]]),
videojs.createTimeRange([[20, 50]]));
strictEqual(edge, 50, 'detected a forward addition & ignores range removal');
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10], [20, 40]]),
videojs.createTimeRange([[0, 50]]));
strictEqual(edge, 50, 'detected a forward addition & ignores merges');
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 10], [20, 40]]),
videojs.createTimeRange([[0, 40]]));
strictEqual(edge, null, 'ignores merges');
// Empty input
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange(),
videojs.createTimeRange([[0, 11]]));
strictEqual(edge, 11, 'handle an empty original TimeRanges object');
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 11]]),
videojs.createTimeRange());
strictEqual(edge, null, 'handle an empty update TimeRanges object');
test('treats null buffered ranges as no addition', function() {
var edges = videojs.Hls.bufferedAdditions_(null,
// Null input
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(null,
videojs.createTimeRange([[0, 11]]));
strictEqual(edge, 11, 'treat null original buffer as an empty TimeRanges object');
equal(edges.length, 0, 'no additions');
edge = videojs.Hls.findSoleUncommonTimeRangesEnd_(videojs.createTimeRange([[0, 11]]),
null);
strictEqual(edge, null, 'treat null update buffer as an empty TimeRanges object');
});
})(window, window.videojs);
......