From 0129be6cccb4bd6f561ce382d92ca1d0172d5520 Mon Sep 17 00:00:00 2001 From: Jaya Allamsetty Date: Thu, 29 Feb 2024 16:26:21 -0500 Subject: [PATCH] fix(SDP): Generate msid attr for source when browser doesn't produce one. Chrome 122 does not generate a 'msid' attribute in the local SDP when a local source is added after the user joins muted. The SSRC doesn't get signaled to remote p2p peer when this happens. Also, when the direction of the transceiver changes from 'sendonly' to 'sendrecv', Chrome is generating a new set of SSRCs resulting the client sending out a source-remove followed by source-add. Fixes various p2p related bugs that have surfaced in p2p calls where both the endpoints are running Chromium 122. --- modules/sdp/LocalSdpMunger.js | 41 ++++++++++++++++------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/modules/sdp/LocalSdpMunger.js b/modules/sdp/LocalSdpMunger.js index 0b731b1cb1..1690e3d062 100644 --- a/modules/sdp/LocalSdpMunger.js +++ b/modules/sdp/LocalSdpMunger.js @@ -67,36 +67,28 @@ export default class LocalSdpMunger { const msidLine = mediaSection.mLine?.msid; const sources = [ ...new Set(mediaSection.mLine?.ssrcs?.map(s => s.id)) ]; const streamId = `${this.localEndpointId}-${mediaType}`; - const trackId = msidLine && msidLine.split(' ')[1]; + let trackId = msidLine ? msidLine.split(' ')[1] : `${this.localEndpointId}-${mediaSection.mLine.mid}`; // Always overwrite msid since we want the msid to be in this format even if the browser generates one. for (const source of sources) { const msid = mediaSection.ssrcs.find(ssrc => ssrc.id === source && ssrc.attribute === 'msid'); - // Update the msid if the 'msid' attribute exists. if (msid) { - const streamAndTrackIDs = msid.value.split(' '); - const trackID = streamAndTrackIDs[1]; - - this._updateSourcesToMsidMap(mediaType, streamId, trackID); - - // Update the msid. - const storedStreamId = mediaType === MediaType.VIDEO - ? this.videoSourcesToMsidMap.get(trackID) - : this.audioSourcesToMsidMap.get(trackID); - - msid.value = this._generateMsidAttribute(mediaType, trackID, storedStreamId); + trackId = msid.value.split(' ')[1]; + } + this._updateSourcesToMsidMap(mediaType, streamId, trackId); + const storedStreamId = mediaType === MediaType.VIDEO + ? this.videoSourcesToMsidMap.get(trackId) + : this.audioSourcesToMsidMap.get(trackId); - // Generate the msid attribute using the 'trackId' from the msid line from the media description. Only - // descriptions that have the direction set to 'sendonly' or 'sendrecv' will have the 'a=msid' line. - } else if (trackId) { - this._updateSourcesToMsidMap(mediaType, streamId, trackId); + const generatedMsid = this._generateMsidAttribute(mediaType, trackId, storedStreamId); - const storedStreamId = mediaType === MediaType.VIDEO - ? this.videoSourcesToMsidMap.get(trackId) - : this.audioSourcesToMsidMap.get(trackId); - const generatedMsid = this._generateMsidAttribute(mediaType, trackId, storedStreamId); + // Update the msid if the 'msid' attribute exists. + if (msid) { + msid.value = generatedMsid; + // Generate the 'msid' attribute if there is a local source. + } else if (mediaDirection === MediaDirection.SENDONLY || mediaDirection === MediaDirection.SENDRECV) { mediaSection.ssrcs.push({ id: source, attribute: 'msid', @@ -167,7 +159,6 @@ export default class LocalSdpMunger { * (a modified copy of the one given as the input). */ transformStreamIdentifiers(sessionDesc) { - // FIXME similar check is probably duplicated in all other transformers if (!sessionDesc || !sessionDesc.sdp || !sessionDesc.type) { return sessionDesc; } @@ -187,6 +178,12 @@ export default class LocalSdpMunger { this._injectSourceNames(videoMLine); } + // Reset the local tracks based maps for msid after every transformation since Chrome 122 is generating + // a new set of SSRCs for the same source when the direction of transceiver changes because of a remote + // source getting added on the p2p connection. + this.audioSourcesToMsidMap.clear(); + this.videoSourcesToMsidMap.clear(); + return new RTCSessionDescription({ type: sessionDesc.type, sdp: transformer.toRawSDP()