Skip to content

Commit

Permalink
fix: Fix segment index assertions with DAI (shaka-project#4348)
Browse files Browse the repository at this point in the history
When DAI adds ad segments faster than real-time, the availability
windows gets messed up, and some assertions in SegmentIndex break.
This locks down the presentation start time after the initial manifest
is parsed, so that the availability window is stable throughout
playback.

b/233075535
  • Loading branch information
joeyparrish committed Jul 14, 2022
1 parent 47fa309 commit c2b3853
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 3 deletions.
5 changes: 5 additions & 0 deletions lib/dash/dash_parser.js
Expand Up @@ -513,6 +513,11 @@ shaka.dash.DashParser = class {
}
presentationTimeline.setClockOffset(offset);
}

// This is the first point where we have a meaningful presentation start
// time, and we need to tell PresentationTimeline that so that it can
// maintain consistency from here on.
presentationTimeline.lockStartTime();
} else {
// Just update the variants and text streams, which may change as periods
// are added or removed.
Expand Down
8 changes: 6 additions & 2 deletions lib/hls/hls_parser.js
Expand Up @@ -740,8 +740,14 @@ shaka.hls.HlsParser = class {
for (const stream of streamsToNotify) {
this.segmentsToNotifyByStream_.push(stream.segmentIndex.references);
}

this.notifySegments_();

// This is the first point where we have a meaningful presentation start
// time, and we need to tell PresentationTimeline that so that it can
// maintain consistency from here on.
this.presentationTimeline_.lockStartTime();

// This asserts that the live edge is being calculated from segment times.
// For VOD and event streams, this check should still pass.
goog.asserts.assert(
Expand Down Expand Up @@ -1859,8 +1865,6 @@ shaka.hls.HlsParser = class {
/* presentationStartTime= */ null, /* delay= */ 0);
this.presentationTimeline_.setStatic(true);
}

this.notifySegments_();
}

/**
Expand Down
25 changes: 24 additions & 1 deletion lib/media/presentation_timeline.js
Expand Up @@ -93,6 +93,9 @@ shaka.media.PresentationTimeline = class {
* @private {number}
*/
this.availabilityTimeOffset_ = 0;

/** @private {boolean} */
this.startTimeLocked_ = false;
}


Expand Down Expand Up @@ -229,7 +232,8 @@ shaka.media.PresentationTimeline = class {
this.maxSegmentEndTime_ =
Math.max(this.maxSegmentEndTime_, lastReferenceEndTime);

if (this.presentationStartTime_ != null && this.autoCorrectDrift_) {
if (this.presentationStartTime_ != null && this.autoCorrectDrift_ &&
!this.startTimeLocked_) {
// Since we have explicit segment end times, calculate a presentation
// start based on them. This start time accounts for drift.
// Date.now() is in milliseconds, from which we compute "now" in seconds.
Expand All @@ -243,6 +247,25 @@ shaka.media.PresentationTimeline = class {
}


/**
* Lock the presentation timeline's start time. After this is called, no
* further adjustments to presentationStartTime_ will be permitted.
*
* This should be called after all Periods have been parsed, and all calls to
* notifySegments() from the initial manifest parse have been made.
*
* Without this, we can get assertion failures in SegmentIndex for certain
* DAI content. If DAI adds ad segments to the manifest faster than
* real-time, adjustments to presentationStartTime_ can cause availability
* windows to jump around on updates.
*
* @export
*/
lockStartTime() {
this.startTimeLocked_ = true;
}


/**
* Gives PresentationTimeline a Stream's minimum segment start time.
*
Expand Down

0 comments on commit c2b3853

Please sign in to comment.