diff --git a/lib/dash/dash_parser.js b/lib/dash/dash_parser.js index fc6ee817f1..5075fb9ac1 100644 --- a/lib/dash/dash_parser.js +++ b/lib/dash/dash_parser.js @@ -173,6 +173,9 @@ shaka.dash.DashParser = class { /** @private {HTMLMediaElement} */ this.mediaElement_ = null; + + /** @private {boolean} */ + this.isTransitionFromDynamicToStatic_ = false; } /** @@ -644,6 +647,11 @@ shaka.dash.DashParser = class { } const mpdType = mpd.attributes['type'] || 'static'; + if (this.manifest_ && this.manifest_.presentationTimeline) { + this.isTransitionFromDynamicToStatic_ = + this.manifest_.presentationTimeline.isLive() && mpdType == 'static'; + } + this.manifestPatchContext_.type = mpdType; /** @type {!shaka.media.PresentationTimeline} */ @@ -730,7 +738,7 @@ shaka.dash.DashParser = class { const duration = periodsAndDuration.duration; const periods = periodsAndDuration.periods; - if (mpdType == 'static' || + if ((mpdType == 'static' && !this.isTransitionFromDynamicToStatic_) || !periodsAndDuration.durationDerivedFromPeriods) { // Ignore duration calculated from Period lengths if this is dynamic. presentationTimeline.setDuration(duration || Infinity); @@ -756,7 +764,7 @@ shaka.dash.DashParser = class { // Use @maxSegmentDuration to override smaller, derived values. presentationTimeline.notifyMaxSegmentDuration(maxSegmentDuration || 1); - if (goog.DEBUG) { + if (goog.DEBUG && !this.isTransitionFromDynamicToStatic_) { presentationTimeline.assertIsValid(); } @@ -1268,8 +1276,14 @@ shaka.dash.DashParser = class { presentationDuration; } + let seekRangeStart = 0; + if (this.manifest_ && this.manifest_.presentationTimeline && + this.isTransitionFromDynamicToStatic_) { + seekRangeStart = this.manifest_.presentationTimeline.getSeekRangeStart(); + } + const periods = []; - let prevEnd = 0; + let prevEnd = seekRangeStart; const periodNodes = TXml.findChildren(mpd, 'Period'); for (let i = 0; i < periodNodes.length; i++) { const elem = periodNodes[i]; @@ -1294,7 +1308,7 @@ shaka.dash.DashParser = class { // "The Period extends until the Period.start of the next Period, or // until the end of the Media Presentation in the case of the last // Period." - periodDuration = presentationDuration - start; + periodDuration = presentationDuration - start + seekRangeStart; } const threshold = @@ -1387,15 +1401,20 @@ shaka.dash.DashParser = class { this.lastManifestUpdatePeriodIds_ = periods.map((el) => el.id); if (presentationDuration != null) { - if (prevEnd != presentationDuration) { - shaka.log.warning( - '@mediaPresentationDuration does not match the total duration of ', - 'all Periods.'); - // Assume @mediaPresentationDuration is correct. + if (prevEnd != null) { + const threshold = + shaka.util.ManifestParserUtils.GAP_OVERLAP_TOLERANCE_SECONDS; + const diference = prevEnd - seekRangeStart - presentationDuration; + if (Math.abs(diference) > threshold) { + shaka.log.warning( + '@mediaPresentationDuration does not match the total duration ', + 'of all Periods.'); + // Assume @mediaPresentationDuration is correct. + } } return { periods: periods, - duration: presentationDuration, + duration: presentationDuration + seekRangeStart, durationDerivedFromPeriods: false, }; } else {