From a8d12ba26f0f86bf37f2362e524ec986ef5da62d Mon Sep 17 00:00:00 2001 From: Timothy Drews Date: Thu, 14 Apr 2016 14:27:49 -0700 Subject: [PATCH] Support live presentations as soon as they start. 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 --- lib/media/playhead.js | 69 ++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/lib/media/playhead.js b/lib/media/playhead.js index 2290cc84d6..59d49eddec 100644 --- a/lib/media/playhead.js +++ b/lib/media/playhead.js @@ -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; @@ -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_(); @@ -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; }; @@ -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)); @@ -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)); };