56919c5f by David LaPalomento

Merge pull request #439 from videojs/fix-fetcher

Minor fixes to fetcher
2 parents 958f2b8c 7c6736ca
......@@ -141,9 +141,7 @@
// https://tools.ietf.org/html/draft-pantos-http-live-streaming-16#section-6.3.3
start = intervalDuration(playlist, playlist.mediaSequence);
end = intervalDuration(playlist,
playlist.mediaSequence + playlist.segments.length);
end -= (playlist.targetDuration || DEFAULT_TARGET_DURATION) * 3;
end = Math.max(0, end);
playlist.mediaSequence + Math.max(0, playlist.segments.length - 3));
return videojs.createTimeRange(start, end);
};
......
......@@ -9,14 +9,15 @@
var
// a fudge factor to apply to advertised playlist bitrates to account for
// temporary flucations in client bandwidth
bandwidthVariance = 1.1,
bandwidthVariance = 1.2,
Component = videojs.getComponent('Component'),
// the amount of time to wait between checking the state of the buffer
bufferCheckInterval = 500,
keyFailed,
resolveUrl;
resolveUrl,
TIME_FUDGE_FACTOR = 1 / 60;
// returns true if a key has failed to download within a certain amount of retries
keyFailed = function(key) {
......@@ -396,72 +397,7 @@ videojs.HlsHandler.prototype.setupSourceBuffer_ = function() {
// transition the sourcebuffer to the ended state if we've hit the end of
// the playlist
this.sourceBuffer.addEventListener('updateend', function() {
var
segmentInfo = this.pendingSegment_,
segment,
segments,
playlist,
currentMediaIndex,
currentBuffered,
timelineUpdates;
this.pendingSegment_ = null;
// stop here if the update errored or was aborted
if (!segmentInfo) {
return;
}
playlist = this.playlists.media();
segments = playlist.segments;
currentMediaIndex = segmentInfo.mediaIndex + (segmentInfo.mediaSequence - playlist.mediaSequence);
currentBuffered = this.findCurrentBuffered_();
// if we switched renditions don't try to add segment timeline
// information to the playlist
if (segmentInfo.playlist.uri !== this.playlists.media().uri) {
return this.fillBuffer();
}
// annotate the segment with any start and end time information
// added by the media processing
segment = playlist.segments[currentMediaIndex];
timelineUpdates = videojs.Hls.bufferedAdditions_(segmentInfo.buffered,
this.tech_.buffered());
timelineUpdates.forEach(function (update) {
if (segment) {
if (update.end !== undefined) {
segment.end = update.end;
}
}
});
// if we've buffered to the end of the video, let the MediaSource know
if (this.playlists.media().endList &&
currentBuffered.length &&
segments[segments.length - 1].end <= currentBuffered.end(0) &&
this.mediaSource.readyState === 'open') {
this.mediaSource.endOfStream();
return;
}
if (timelineUpdates.length) {
this.updateDuration(playlist);
// check if it's time to download the next segment
this.fillBuffer();
return;
}
// the last segment append must have been entirely in the
// already buffered time ranges. just buffer forward until we
// find a segment that adds to the buffered time ranges and
// improves subsequent media index calculations.
this.fillBuffer(currentMediaIndex + 1);
return;
}.bind(this));
this.sourceBuffer.addEventListener('updateend', this.updateEndHandler_.bind(this));
};
/**
......@@ -540,6 +476,11 @@ videojs.HlsHandler.prototype.setCurrentTime = function(currentTime) {
return currentTime;
}
// if we are in the middle of appending a segment, let it finish up
if (this.pendingSegment_ && this.pendingSegment_.buffered) {
return currentTime;
}
this.lastSegmentLoaded_ = null;
// cancel outstanding requests and buffer appends
......@@ -640,6 +581,7 @@ videojs.HlsHandler.prototype.cancelSegmentXhr = function() {
this.segmentXhr_.abort();
this.segmentXhr_ = null;
}
// clear out the segment being processed
this.pendingSegment_ = null;
};
......@@ -828,8 +770,8 @@ videojs.HlsHandler.prototype.findCurrentBuffered_ = function() {
if (buffered && buffered.length) {
// Search for a range containing the play-head
for (i = 0; i < buffered.length; i++) {
if (buffered.start(i) <= currentTime &&
buffered.end(i) >= currentTime) {
if (buffered.start(i) - TIME_FUDGE_FACTOR <= currentTime &&
buffered.end(i) + TIME_FUDGE_FACTOR >= currentTime) {
ranges = videojs.createTimeRanges(buffered.start(i), buffered.end(i));
ranges.indexOf = i;
return ranges;
......@@ -1143,6 +1085,74 @@ videojs.HlsHandler.prototype.drainBuffer = function(event) {
this.sourceBuffer.appendBuffer(bytes);
};
videojs.HlsHandler.prototype.updateEndHandler_ = function () {
var
segmentInfo = this.pendingSegment_,
segment,
segments,
playlist,
currentMediaIndex,
currentBuffered,
timelineUpdates;
this.pendingSegment_ = null;
// stop here if the update errored or was aborted
if (!segmentInfo) {
return;
}
playlist = this.playlists.media();
segments = playlist.segments;
currentMediaIndex = segmentInfo.mediaIndex + (segmentInfo.mediaSequence - playlist.mediaSequence);
currentBuffered = this.findCurrentBuffered_();
// if we switched renditions don't try to add segment timeline
// information to the playlist
if (segmentInfo.playlist.uri !== this.playlists.media().uri) {
return this.fillBuffer();
}
// annotate the segment with any start and end time information
// added by the media processing
segment = playlist.segments[currentMediaIndex];
timelineUpdates = videojs.Hls.bufferedAdditions_(segmentInfo.buffered,
this.tech_.buffered());
timelineUpdates.forEach(function (update) {
if (segment) {
if (update.end !== undefined) {
segment.end = update.end;
}
}
});
// if we've buffered to the end of the video, let the MediaSource know
if (this.playlists.media().endList &&
currentBuffered.length &&
segments[segments.length - 1].end <= currentBuffered.end(0) &&
this.mediaSource.readyState === 'open') {
this.mediaSource.endOfStream();
return;
}
if (timelineUpdates.length ||
segmentInfo.buffered.length !== this.tech_.buffered().length) {
this.updateDuration(playlist);
// check if it's time to download the next segment
this.fillBuffer();
return;
}
// the last segment append must have been entirely in the
// already buffered time ranges. just buffer forward until we
// find a segment that adds to the buffered time ranges and
// improves subsequent media index calculations.
this.fillBuffer(currentMediaIndex + 1);
return;
};
/**
* Attempt to retrieve the key for a particular media segment.
*/
......
......@@ -381,8 +381,8 @@
});
equal(seekable.start(0), 0, 'starts at the earliest available segment');
equal(seekable.end(0),
9 - (2 * 3),
'allows seeking no further than three target durations from the end');
9 - (2 + 2 + 1),
'allows seeking no further than three segments from the end');
});
})(window, window.videojs);
......