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 <tykus160@gmail.com>
  • Loading branch information
2 people authored and avelad committed Aug 29, 2024
1 parent 53e6f66 commit b18dcbf
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 @@ -92,12 +92,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 @@ -235,6 +242,7 @@ shaka.dash.DashParser = class {
this.manifestUris_ = [];
this.manifest_ = null;
this.streamMap_ = {};
this.indexStreamMap_ = {};
this.contextCache_.clear();
this.manifestPatchContext_ = {
mpdId: '',
Expand Down Expand Up @@ -618,7 +626,7 @@ shaka.dash.DashParser = class {
}

this.manifestPatchContext_.type = mpdType;

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

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 @@ -977,7 +986,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 @@ -996,6 +1005,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 @@ -1237,14 +1250,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 @@ -1370,8 +1384,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 @@ -1399,6 +1423,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 @@ -2184,7 +2228,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 b18dcbf

Please sign in to comment.