Skip to content

Commit

Permalink
Fix: Use period ID instead of start time
Browse files Browse the repository at this point in the history
  • Loading branch information
echoy-harmonicinc committed Aug 27, 2021
1 parent 94d696f commit 84f4578
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 25 deletions.
39 changes: 21 additions & 18 deletions lib/dash/dash_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,13 @@ shaka.dash.DashParser = class {
* Largest period start time seen.
* @private {?number}
*/
this.largestPeriodStartTime_ = null;
this.largestPeriodId_ = null;

/**
* Period start times seen in previous manifest.
* @private {!Array.<number>}
*/
this.seenPeriodStartTime_ = [];
this.seenPeriodIds = [];

/**
* The minimum of the availabilityTimeOffset values among the adaptation
Expand Down Expand Up @@ -542,7 +542,7 @@ shaka.dash.DashParser = class {
mpd, 'mediaPresentationDuration', XmlUtils.parseDuration);

const periods = [];
const periodStartTime = [];
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
Expand All @@ -551,6 +551,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 givenDuration =
XmlUtils.parseAttr(elem, 'duration', XmlUtils.parseDuration);

Expand Down Expand Up @@ -585,9 +586,11 @@ shaka.dash.DashParser = class {
}

/**
* This is to improve the robustness of the player
* when it received bad content/manifest, while still supporting
* modification of previous periods.
* This is to improve robustness when the player observes manifest with
* past periods that are inconsistent to previous ones.
*
* This may happen when a CDN or proxy server switches its upstream from
* one encoder to another redundant encoder.
*
* Skip periods that match all of the following criteria:
* - Start time is earlier than latest period start time ever seen
Expand All @@ -597,26 +600,26 @@ shaka.dash.DashParser = class {
* Periods that meet the aforementioned criteria are considered invalid
* and should be safe to discard.
*/
if (this.largestPeriodStartTime_ !== null && start !== null) {
if (start < this.largestPeriodStartTime_ &&
!this.seenPeriodStartTime_.includes(start) &&
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 start time is smaller than ` +
'the largest period start time that has been seen, and start ' +
'time is unseen before');
`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 {
periodStartTime.push(start);
periodIds.push(periodId);
}
}


// Save maximum period start time if it is the last period
if (start !== null &&
(this.largestPeriodStartTime_ === null ||
start > this.largestPeriodStartTime_)) {
this.largestPeriodStartTime_ = start;
if (periodId !== null &&
(this.largestPeriodId_ === null ||
periodId > this.largestPeriodId_)) {
this.largestPeriodId_ = periodId;
}

// Parse child nodes.
Expand Down Expand Up @@ -651,7 +654,7 @@ shaka.dash.DashParser = class {
} // end of period parsing loop

// Replace previous seen start time with the current one.
this.seenPeriodStartTime_ = periodStartTime;
this.seenPeriodIds = periodIds;

if (presentationDuration != null) {
if (prevEnd != presentationDuration) {
Expand Down
12 changes: 5 additions & 7 deletions test/dash/dash_parser_manifest_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2155,7 +2155,7 @@ describe('DashParser Manifest', () => {
* @param {!Array.<number>} periods Start time of multiple periods
* @return {string}
*/
function buildManifestWithPeriodStartTime(periods) {
function buildManifestWithPeriodId(periods) {
const mpdTemplate = [
`<MPD type="dynamic"`,
'availabilityStartTime="1970-01-01T00:00:00Z"',
Expand All @@ -2179,7 +2179,7 @@ describe('DashParser Manifest', () => {
};
const periodXmls = periods.map((period, i) => {
const duration = i+1 === periods.length ? 10 : periods[i+1] - period;
return periodTemplate(i+1, period, duration);
return periodTemplate(period, period, duration);
});
return sprintf(mpdTemplate, {
periods: periodXmls.join('\n'),
Expand All @@ -2193,13 +2193,11 @@ describe('DashParser Manifest', () => {
// redundant servers. The period start time might become out of sync
// during the switch-over/recovery.

// Solution: Ignore old DASH periods that are older than the latest one.

it('skip periods that are earlier than max period start time', async () => {
const sources = [
buildManifestWithPeriodStartTime([5, 15]),
buildManifestWithPeriodStartTime([6, 15]), // simulate out-of-sync of -1s
buildManifestWithPeriodStartTime([4, 15]), // simulate out-of-sync of +1s
buildManifestWithPeriodId([5, 15]),
buildManifestWithPeriodId([6, 15]), // simulate out-of-sync of -1s
buildManifestWithPeriodId([4, 15]), // simulate out-of-sync of +1s
];
const segments = [];

Expand Down

0 comments on commit 84f4578

Please sign in to comment.