Skip to content

Commit

Permalink
Support rewind outside of buffered area
Browse files Browse the repository at this point in the history
Closes #165

Change-Id: I684560b332808f9acffcfc09ad8fffcd8c164fba
  • Loading branch information
joeyparrish committed Sep 4, 2015
1 parent a06fb39 commit bc7b826
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 10 deletions.
37 changes: 27 additions & 10 deletions lib/player/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ shaka.player.Player = function(video) {
/** @private {?number} */
this.rewindTimer_ = null;

/** @private {number} */
this.seekRangeStart_ = 0;

/** @private {?number} */
this.watchdogTimer_ = null;

Expand Down Expand Up @@ -281,6 +284,8 @@ shaka.player.Player.prototype.load = function(videoSource) {
function() {
this.videoSource_ = videoSource;
this.videoSource_.setRestrictions(this.restrictions_);
this.eventManager_.listen(this.videoSource_, 'seekrangechanged',
this.onSeekRangeChanged_.bind(this));
this.emeManager_ = new shaka.media.EmeManager(
this, this.video_, this.videoSource_);
return this.emeManager_.initialize();
Expand Down Expand Up @@ -416,7 +421,17 @@ shaka.player.Player.prototype.onPause_ = function(event) {
if (!isNaN(elapsed)) {
this.stats_.logPlayTime(elapsed);
}
this.cancelRewindTimer_();
};


/**
* Handler for seek range events.
*
* @param {!Event} event
* @private
*/
shaka.player.Player.prototype.onSeekRangeChanged_ = function(event) {
this.seekRangeStart_ = event['start'];
};


Expand Down Expand Up @@ -881,19 +896,21 @@ shaka.player.Player.prototype.cancelWatchdogTimer_ = function() {
shaka.player.Player.prototype.onRewindTimer_ =
function(startVideoTime, startWallTime, rate) {
shaka.asserts.assert(rate < 0);
var rewindOffset =
shaka.player.Player.REWIND_UPDATE_INTERVAL_ * Math.abs(rate);
if (this.video_.buffered.length &&
this.video_.buffered.start(0) + rewindOffset < this.video_.currentTime) {
var offset = ((Date.now() - startWallTime) / 1000) * rate;
this.video_.currentTime = startVideoTime + offset;
this.rewindTimer_ = null;

var offset = ((Date.now() - startWallTime) / 1000) * rate;
var fudge = this.isLive() ? 1 : 0.05;

if (this.video_.currentTime < this.seekRangeStart_ + fudge) {
// Hit the beginning (or near enough), so pause.
this.video_.pause();
} else {
var goal = Math.max(this.seekRangeStart_, startVideoTime + offset);
this.video_.currentTime = goal;
var callback = this.onRewindTimer_.bind(
this, startVideoTime, startWallTime, rate);
this.rewindTimer_ = window.setTimeout(
callback, shaka.player.Player.REWIND_UPDATE_INTERVAL_ * 1000);
} else {
this.video_.pause();
}
};

Expand Down Expand Up @@ -991,7 +1008,7 @@ shaka.player.Player.BUFFERED_FUDGE_FACTOR_ = 0.05;
* @private {number}
* @const
*/
shaka.player.Player.REWIND_UPDATE_INTERVAL_ = 0.1;
shaka.player.Player.REWIND_UPDATE_INTERVAL_ = 0.25;


/**
Expand Down
23 changes: 23 additions & 0 deletions spec/player_integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,29 @@ describe('Player', function() {
done();
});
});

it('plays in reverse past the buffered area', function(done) {
var timestamp = 10;
// Start in the second segment.
player.load(newSource(plainManifest)).then(function() {
video.currentTime = timestamp;
video.play();
return waitForMovement(video, eventManager);
}).then(function() {
expect(video.buffered.length).toBe(1);
expect(video.buffered.start(0)).toBeGreaterThan(5);
player.setPlaybackRate(-3.0);
return waitForMovement(video, eventManager);
}).then(function() {
return delay(4.0);
}).then(function() {
expect(video.currentTime).toBeLessThan(0.1);
done();
}).catch(function(error) {
fail(error);
done();
});
});
});

describe('getStats', function() {
Expand Down

0 comments on commit bc7b826

Please sign in to comment.