diff --git a/lib/dash/dash_parser.js b/lib/dash/dash_parser.js index 767ae8668c..89da858931 100644 --- a/lib/dash/dash_parser.js +++ b/lib/dash/dash_parser.js @@ -99,13 +99,13 @@ shaka.dash.DashParser = class { * Largest period start time seen. * @private {?number} */ - this.largestPeriodId_ = null; + this.largestPeriodStartTime_ = null; /** - * Period start times seen in previous manifest. + * Period IDs seen in previous manifest. * @private {!Array.} */ - this.seenPeriodIds = []; + this.seenPeriodIds_ = []; /** * The minimum of the availabilityTimeOffset values among the adaptation @@ -542,7 +542,6 @@ shaka.dash.DashParser = class { mpd, 'mediaPresentationDuration', XmlUtils.parseDuration); const periods = []; - const periodIds = []; let prevEnd = 0; const periodNodes = XmlUtils.findChildren(mpd, 'Period'); // This uses a for-loop rather than a for-of loop because this needs to look @@ -551,7 +550,7 @@ shaka.dash.DashParser = class { for (const {i, item: elem, next} of enumerate(periodNodes)) { const start = /** @type {number} */ ( XmlUtils.parseAttr(elem, 'start', XmlUtils.parseDuration, prevEnd)); - const periodId = Number(elem.id); + const periodId = elem.id; const givenDuration = XmlUtils.parseAttr(elem, 'duration', XmlUtils.parseDuration); @@ -594,32 +593,31 @@ shaka.dash.DashParser = class { * * Skip periods that match all of the following criteria: * - Start time is earlier than latest period start time ever seen - * - Start time is never seen in the previous manifest + * - Period ID is never seen in the previous manifest * - Not the last period in the manifest * * Periods that meet the aforementioned criteria are considered invalid * and should be safe to discard. */ - if (this.largestPeriodId_ !== null && periodId !== null) { - if (periodId < this.largestPeriodId_ && - !this.seenPeriodIds.includes(periodId) && - i + 1 != periodNodes.length) { - shaka.log.debug( - `Skipping Period ${i+1} as its period ID is smaller than ` + - 'the largest period ID that has been seen, and ID ' + - 'is unseen before'); - continue; - } else { - periodIds.push(periodId); - } + + if (this.largestPeriodStartTime_ !== null && + periodId !== null && start !== null && + start < this.largestPeriodStartTime_ && + !this.seenPeriodIds_.includes(periodId) && + i + 1 != periodNodes.length) { + shaka.log.debug( + `Skipping Period with ID ${periodId} as its start time is smaller` + + ' than the largest period start time that has been seen, and ID ' + + 'is unseen before'); + continue; } // Save maximum period start time if it is the last period - if (periodId !== null && - (this.largestPeriodId_ === null || - periodId > this.largestPeriodId_)) { - this.largestPeriodId_ = periodId; + if (start !== null && + (this.largestPeriodStartTime_ === null || + start > this.largestPeriodStartTime_)) { + this.largestPeriodStartTime_ = start; } // Parse child nodes. @@ -653,8 +651,8 @@ shaka.dash.DashParser = class { prevEnd = start + periodDuration; } // end of period parsing loop - // Replace previous seen start time with the current one. - this.seenPeriodIds = periodIds; + // Replace previous seen periods with the current one. + this.seenPeriodIds_ = periods.map((el) => el.id); if (presentationDuration != null) { if (prevEnd != presentationDuration) { diff --git a/test/dash/dash_parser_manifest_unit.js b/test/dash/dash_parser_manifest_unit.js index 10e6758b5c..6b5784e8d3 100644 --- a/test/dash/dash_parser_manifest_unit.js +++ b/test/dash/dash_parser_manifest_unit.js @@ -2155,7 +2155,7 @@ describe('DashParser Manifest', () => { * @param {!Array.} periods Start time of multiple periods * @return {string} */ - function buildManifestWithPeriodId(periods) { + function buildManifestWithPeriodStartTime(periods) { const mpdTemplate = [ ` { }; const periodXmls = periods.map((period, i) => { const duration = i+1 === periods.length ? 10 : periods[i+1] - period; + // Period start time as ID here. If we use index then there will be + // periods with same period ID and different start time which are invalid. return periodTemplate(period, period, duration); }); return sprintf(mpdTemplate, { @@ -2195,9 +2197,9 @@ describe('DashParser Manifest', () => { it('skip periods that are earlier than max period start time', async () => { const sources = [ - buildManifestWithPeriodId([5, 15]), - buildManifestWithPeriodId([6, 15]), // simulate out-of-sync of -1s - buildManifestWithPeriodId([4, 15]), // simulate out-of-sync of +1s + buildManifestWithPeriodStartTime([5, 15]), + buildManifestWithPeriodStartTime([6, 15]), // simulate out-of-sync of +1s + buildManifestWithPeriodStartTime([4, 15]), // simulate out-of-sync of -1s ]; const segments = [];