Skip to content

Commit

Permalink
Support live presentations as soon as they start.
Browse files Browse the repository at this point in the history
When live streams begin broadcasting their manifests' may be
incomplete.  This patch ensures startup succeeds even when the
initial manifest may be missing segment information.

Change-Id: I60205fc2a4d61046c17faf1d66b4767ef1c30319
  • Loading branch information
Timothy Drews committed Apr 15, 2016
1 parent d2a812c commit a8d12ba
Showing 1 changed file with 39 additions and 30 deletions.
69 changes: 39 additions & 30 deletions lib/media/playhead.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,12 @@ shaka.media.Playhead = function(
this.rebufferingGoal_ = rebufferingGoal;

/**
* The playhead's initial position in seconds.
* @private {number}
* The playhead's initial position in seconds, or null if it should
* automatically be calculated later.
* @private {?number}
* @const
*/
this.startTime_;
this.startTime_ = startTime;

/** @private {?function(boolean)} */
this.onBuffering_ = onBuffering;
Expand All @@ -81,21 +82,6 @@ shaka.media.Playhead = function(
/** @private {number} */
this.lastPlaybackRate_ = 0;

// Set the start time.
if (startTime == null) {
if (timeline.getDuration() < Number.POSITIVE_INFINITY) {
startTime = timeline.getSegmentAvailabilityStart();
} else {
// For live presentations, ensure that the startup buffering goal can be
// met.
startTime =
Math.max(timeline.getSegmentAvailabilityEnd() - rebufferingGoal,
timeline.getSegmentAvailabilityStart());
}
}
this.startTime_ = startTime;
shaka.log.debug('Starting the presentation at ' + startTime + ' seconds...');

// Check if the video has already loaded some metadata.
if (video.readyState > 0) {
this.onLoadedMetadata_();
Expand Down Expand Up @@ -132,14 +118,40 @@ shaka.media.Playhead.prototype.setRebufferingGoal = function(rebufferingGoal) {
* @return {number}
*/
shaka.media.Playhead.prototype.getTime = function() {
var time = this.video_.readyState > 0 ?
this.video_.currentTime :
this.startTime_;
// Although we restrict the video's currentTime elsewhere, clamp it here to
// ensure any timing issues (e.g., the user agent seeks and calls this
// function before we receive the 'seeking' event) don't cause us to return a
// time outside the segment availability window.
return this.clampTime_(time);
if (this.video_.readyState > 0) {
// Although we restrict the video's currentTime elsewhere, clamp it here to
// ensure any timing issues (e.g., the user agent seeks and calls this
// function before we receive the 'seeking' event) don't cause us to return
// a time outside the segment availability window.
return this.clampTime_(this.video_.currentTime);
}

return this.getStartTime_();
};


/**
* Gets the playhead's initial position in seconds.
*
* @return {number}
* @private
*/
shaka.media.Playhead.prototype.getStartTime_ = function() {
if (this.startTime_) {
return this.clampTime_(this.startTime_);
}

var startTime;
if (this.timeline_.getDuration() < Number.POSITIVE_INFINITY) {
startTime = this.timeline_.getSegmentAvailabilityStart();
} else {
// For live presentations, ensure that the startup buffering goal can be
// met.
startTime = Math.max(
this.timeline_.getSegmentAvailabilityEnd() - this.rebufferingGoal_,
this.timeline_.getSegmentAvailabilityStart());
}
return startTime;
};


Expand Down Expand Up @@ -178,7 +190,7 @@ shaka.media.Playhead.prototype.onLoadedMetadata_ = function() {
this.eventManager_.unlisten(this.video_, 'loadedmetadata');

// Move the real playhead to the start time.
var targetTime = this.clampTime_(this.startTime_);
var targetTime = this.getStartTime_();
if (this.video_.currentTime.toFixed(3) == targetTime.toFixed(3)) {
this.eventManager_.listen(
this.video_, 'seeking', this.onSeeking_.bind(this));
Expand All @@ -199,9 +211,6 @@ shaka.media.Playhead.prototype.onLoadedMetadata_ = function() {
shaka.media.Playhead.prototype.onSeekingToStartTime_ = function() {
goog.asserts.assert(this.video_.readyState > 0,
'readyState should be greater than 0');
goog.asserts.assert(
this.video_.currentTime.toFixed(3) == this.startTime_.toFixed(3),
'currentTime should be equal to startTime');
this.eventManager_.unlisten(this.video_, 'seeking');
this.eventManager_.listen(this.video_, 'seeking', this.onSeeking_.bind(this));
};
Expand Down

0 comments on commit a8d12ba

Please sign in to comment.