Skip to content

Commit

Permalink
fix(DASH): Clear streamMap when period is removed from the manifest (#…
Browse files Browse the repository at this point in the history
…7202)

Related to #6239 and
#7148
Remove the reference to the stream when is no more needed.

---------

Co-authored-by: Wojciech Tyczyński <[email protected]>
  • Loading branch information
2 people authored and avelad committed Aug 29, 2024
1 parent 6589d28 commit e76f6b2
Showing 1 changed file with 57 additions and 8 deletions.
65 changes: 57 additions & 8 deletions lib/dash/dash_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,19 @@ shaka.dash.DashParser = class {

/**
* A map of IDs to Stream objects.
* ID: Period@id,AdaptationSet@id,@Representation@id
* e.g.: '1,5,23'
* ID: Period@id,Representation@id
* e.g.: '1,23'
* @private {!Object.<string, !shaka.extern.Stream>}
*/
this.streamMap_ = {};

/**
* A map of Period IDs to Stream Map IDs.
* Use to have direct access to streamMap key.
* @private {!Object.<string, !Array<string>>}
*/
this.indexStreamMap_ = {};

/**
* A map of period ids to their durations
* @private {!Object.<string, number>}
Expand Down Expand Up @@ -256,6 +263,7 @@ shaka.dash.DashParser = class {
this.manifestUris_ = [];
this.manifest_ = null;
this.streamMap_ = {};
this.indexStreamMap_ = {};
this.contextCache_.clear();
this.manifestPatchContext_ = {
mpdId: '',
Expand Down Expand Up @@ -653,7 +661,7 @@ shaka.dash.DashParser = class {
}

this.manifestPatchContext_.type = mpdType;

this.cleanStreamMap_();
/** @type {!shaka.media.PresentationTimeline} */
let presentationTimeline;
if (this.manifest_) {
Expand Down Expand Up @@ -734,7 +742,8 @@ shaka.dash.DashParser = class {
};

this.gapCount_ = 0;
const periodsAndDuration = this.parsePeriods_(context, getBaseUris, mpd);
const periodsAndDuration = this.parsePeriods_(
context, getBaseUris, mpd, /* newPeriod= */ false);
const duration = periodsAndDuration.duration;
const periods = periodsAndDuration.periods;

Expand Down Expand Up @@ -1013,7 +1022,7 @@ shaka.dash.DashParser = class {
};

const periodsAndDuration = this.parsePeriods_(context,
this.manifestPatchContext_.getBaseUris, periods);
this.manifestPatchContext_.getBaseUris, periods, /* newPeriod= */ true);

return periodsAndDuration.periods;
}
Expand All @@ -1033,6 +1042,10 @@ shaka.dash.DashParser = class {
this.contextCache_.delete(contextId);
}
}
const newPeriods = this.lastManifestUpdatePeriodIds_.filter((pID) => {
return pID !== periodId;
});
this.lastManifestUpdatePeriodIds_ = newPeriods;
}

/**
Expand Down Expand Up @@ -1274,14 +1287,15 @@ shaka.dash.DashParser = class {
* @param {shaka.dash.DashParser.Context} context
* @param {function():!Array.<string>} getBaseUris
* @param {!shaka.extern.xml.Node} mpd
* @param {!boolean} newPeriod
* @return {{
* periods: !Array.<shaka.extern.Period>,
* duration: ?number,
* durationDerivedFromPeriods: boolean
* }}
* @private
*/
parsePeriods_(context, getBaseUris, mpd) {
parsePeriods_(context, getBaseUris, mpd, newPeriod) {
const TXml = shaka.util.TXml;
let presentationDuration = context.mediaPresentationDuration;

Expand Down Expand Up @@ -1413,8 +1427,18 @@ shaka.dash.DashParser = class {
prevEnd = start + periodDuration;
} // end of period parsing loop

// Replace previous seen periods with the current one.
this.lastManifestUpdatePeriodIds_ = periods.map((el) => el.id);
if (newPeriod) {
// append new period from the patch manifest
for (const el of periods) {
const periodID = el.id;
if (!this.lastManifestUpdatePeriodIds_.includes(periodID)) {
this.lastManifestUpdatePeriodIds_.push(periodID);
}
}
} else {
// Replace previous seen periods with the current one.
this.lastManifestUpdatePeriodIds_ = periods.map((el) => el.id);
}

if (presentationDuration != null) {
if (prevEnd != null) {
Expand Down Expand Up @@ -1442,6 +1466,26 @@ shaka.dash.DashParser = class {
}
}

/**
* Clean StreamMap Object to remove reference of deleted Stream Object
* @private
*/
cleanStreamMap_() {
const oldPeriodIds = Object.keys(this.indexStreamMap_);
if (oldPeriodIds.length === this.lastManifestUpdatePeriodIds_.length) {
return;
}
const diffPeriodsIDs = oldPeriodIds.filter((pId) => {
return !this.lastManifestUpdatePeriodIds_.includes(pId);
});
for (const pId of diffPeriodsIDs) {
for (const contextId of this.indexStreamMap_[pId]) {
delete this.streamMap_[contextId];
}
delete this.indexStreamMap_[pId];
}
}

/**
* Parses a Period XML element. Unlike the other parse methods, this is not
* given the Node; it is given a PeriodInfo structure. Also, partial parsing
Expand Down Expand Up @@ -2221,7 +2265,12 @@ shaka.dash.DashParser = class {
};

if (contextId && context.dynamic && !this.streamMap_[contextId]) {
const periodId = context.period.id || '';
if (!this.indexStreamMap_[periodId]) {
this.indexStreamMap_[periodId] = [];
}
this.streamMap_[contextId] = stream;
this.indexStreamMap_[periodId].push(contextId);
}

return stream;
Expand Down

0 comments on commit e76f6b2

Please sign in to comment.