Skip to content

Commit

Permalink
Detect and recover from multiple buffered ranges.
Browse files Browse the repository at this point in the history
There should never be multiple buffered ranges, but if there are
then at least try to keep playing.

Issue #121

Change-Id: I562bdb194dcc1f66701ad1b5bb3246b4e2fbe431
  • Loading branch information
Timothy Drews authored and Gerrit Code Review committed Jul 20, 2015
1 parent 89d0ef5 commit f08fbba
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 16 deletions.
21 changes: 16 additions & 5 deletions lib/media/source_buffer_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -337,12 +337,23 @@ shaka.media.SourceBufferManager.prototype.correct = function(


/**
* Assert correctness of SBM internal range.
* Emits an error message and returns true if there are multiple buffered
* ranges; otherwise, does nothing and returns false.
*
* @return {boolean}
*/
shaka.media.SourceBufferManager.prototype.assertSingleRange = function() {
shaka.asserts.assert(this.sourceBuffer_.buffered.length <= 1,
'Multiple time ranges should not be buffered!');
shaka.media.SegmentReference.assertCorrectReferences(this.inserted_);
shaka.media.SourceBufferManager.prototype.detectMultipleBufferedRanges =
function() {
if (this.sourceBuffer_.buffered.length > 1) {
shaka.log.error(
'Multiple buffered ranges detected:',
'Either the content has gaps in it,',
'the content\'s segments are not aligned across bitrates,',
'or the browser has evicted the middle of the buffer.');
return true;
} else {
return false;
}
};


Expand Down
21 changes: 10 additions & 11 deletions lib/media/stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,16 @@ shaka.media.Stream.prototype.onUpdate_ = function() {
shaka.asserts.assert((this.updateTimer_ != null) && !this.resyncing_);
shaka.asserts.assert(!this.fetching_);

// We should only have one buffered range at any given time, so the next
// segment we need is after the last one we inserted. However, non-ideal
// content and/or browser eviction policy may induce multiple buffered
// ranges in some cases.
if (this.sbm_.detectMultipleBufferedRanges() && this.started_) {
// Try to recover by clearing the buffer.
this.resync_(true /* clearBuffer */);
return;
}

this.updateTimer_ = null;

// Retain local copies since switch() may be called while fetching.
Expand Down Expand Up @@ -498,17 +508,6 @@ shaka.media.Stream.prototype.getBufferingGoal_ = function() {
*/
shaka.media.Stream.prototype.getNext_ = function(
currentTime, segmentIndex) {
// TODO: It's possible, depending on the browser's eviction policy, that the
// middle of a buffered time range is evicted, detect this and try to recover
// gracefully.

if (!COMPILED) {
// We should only have a single buffered time range at any given time,
// so assume that the next segment we need is after the last one we
// inserted.
this.sbm_.assertSingleRange();
}

var last = this.sbm_.getLastInserted();
return last != null ?
(last.endTime != null ? segmentIndex.find(last.endTime) : null) :
Expand Down

0 comments on commit f08fbba

Please sign in to comment.