diff --git a/src/Consumer.ts b/src/Consumer.ts index 2863bf69..837efdfd 100644 --- a/src/Consumer.ts +++ b/src/Consumer.ts @@ -7,9 +7,9 @@ import type { AppData } from './types'; const logger = new Logger('Consumer'); export type ConsumerOptions = { - id?: string; - producerId?: string; - kind?: 'audio' | 'video'; + id: string; + producerId: string; + kind: 'audio' | 'video'; rtpParameters: RtpParameters; streamId?: string; onRtpReceiver?: OnRtpReceiverCallback; diff --git a/src/DataConsumer.ts b/src/DataConsumer.ts index e015c663..62f9404c 100644 --- a/src/DataConsumer.ts +++ b/src/DataConsumer.ts @@ -7,8 +7,8 @@ const logger = new Logger('DataConsumer'); export type DataConsumerOptions = { - id?: string; - dataProducerId?: string; + id: string; + dataProducerId: string; sctpStreamParameters: SctpStreamParameters; label?: string; protocol?: string; diff --git a/src/Producer.ts b/src/Producer.ts index 725e9a7c..8f51d13b 100644 --- a/src/Producer.ts +++ b/src/Producer.ts @@ -13,6 +13,7 @@ const logger = new Logger('Producer'); export type ProducerOptions = { track?: MediaStreamTrack; + streamId?: string; encodings?: RtpEncodingParameters[]; codecOptions?: ProducerCodecOptions; headerExtensionOptions?: ProducerHeaderExtensionOptions; diff --git a/src/RtpParameters.ts b/src/RtpParameters.ts index db16d087..555fe56e 100644 --- a/src/RtpParameters.ts +++ b/src/RtpParameters.ts @@ -164,6 +164,12 @@ export type RtpParameters = { * Parameters used for RTCP. */ rtcp?: RtcpParameters; + /** + * MSID (WebRTC MediaStream Identification). + * + * @see https://datatracker.ietf.org/doc/html/rfc8830 + */ + msid?: string; }; /** diff --git a/src/Transport.ts b/src/Transport.ts index 1b6a602b..b67effdf 100644 --- a/src/Transport.ts +++ b/src/Transport.ts @@ -500,6 +500,7 @@ export class Transport< */ async produce({ track, + streamId, encodings, codecOptions, headerExtensionOptions, @@ -587,6 +588,7 @@ export class Transport< const { localId, rtpParameters, rtpSender } = await this._handler.send({ track, + streamId, encodings: normalizedEncodings, codecOptions, headerExtensionOptions, @@ -902,8 +904,8 @@ export class Transport< task.consumerOptions; optionsList.push({ - trackId: id!, - kind: kind!, + trackId: id, + kind: kind, rtpParameters, streamId, onRtpReceiver, @@ -920,9 +922,9 @@ export class Transport< task.consumerOptions; const { localId, rtpReceiver, track } = result; const consumer: Consumer = new Consumer({ - id: id!, + id, localId, - producerId: producerId!, + producerId, rtpReceiver, track, rtpParameters, diff --git a/src/handlers/Chrome111.ts b/src/handlers/Chrome111.ts index 15a1c0d2..209d34fb 100644 --- a/src/handlers/Chrome111.ts +++ b/src/handlers/Chrome111.ts @@ -14,6 +14,7 @@ import type { RtpHeaderExtensionDirection, } from '../RtpParameters'; import type { SctpCapabilities, SctpStreamParameters } from '../SctpParameters'; +import { RemoteSdp } from './sdp/RemoteSdp'; import * as sdpCommonUtils from './sdp/commonUtils'; import * as sdpUnifiedPlanUtils from './sdp/unifiedPlanUtils'; import * as ortcUtils from './ortc/utils'; @@ -31,7 +32,6 @@ import type { HandlerReceiveDataChannelOptions, HandlerReceiveDataChannelResult, } from './HandlerInterface'; -import { RemoteSdp } from './sdp/RemoteSdp'; const logger = new Logger('Chrome111'); @@ -60,7 +60,7 @@ export class Chrome111 // Map of RTCTransceivers indexed by MID. private readonly _mapMidTransceiver: Map = new Map(); - // Local stream for sending. + // Default local stream for sending if no `streamId` is given in send(). private readonly _sendStream = new MediaStream(); // Whether a DataChannel m=application section has been created. private _hasDataChannelMediaSection = false; @@ -336,6 +336,7 @@ export class Chrome111 async send({ track, + streamId, encodings, codecOptions, headerExtensionOptions, @@ -345,7 +346,12 @@ export class Chrome111 this.assertNotClosed(); this.assertSendDirection(); - logger.debug('send() [kind:%s, track.id:%s]', track.kind, track.id); + logger.debug( + 'send() [kind:%s, track.id:%s, streamId:%s]', + track.kind, + track.id, + streamId + ); if (encodings && encodings.length > 1) { // Set rid and verify scalabilityMode in each encoding. @@ -481,6 +487,9 @@ export class Chrome111 offerMediaObject, }); + // Set msid. + sendingRtpParameters.msid = `${streamId ?? this._sendStream.id} ${track.id}`; + // Set RTP encodings by parsing the SDP offer if no encodings are given. if (!encodings) { sendingRtpParameters.encodings = sdpUnifiedPlanUtils.getRtpEncodings({ @@ -905,11 +914,17 @@ export class Chrome111 mapLocalId.set(trackId, localId); + // We ignore MSID `trackId` when consuming and always use our computed + // `trackId` which matches the `consumer.id`. + const { msidStreamId } = ortcUtils.getMsidStreamIdAndTrackId( + rtpParameters.msid + ); + this._remoteSdp.receive({ mid: localId, kind, offerRtpParameters: rtpParameters, - streamId: streamId ?? rtpParameters.rtcp!.cname!, + streamId: streamId ?? msidStreamId ?? rtpParameters.rtcp?.cname ?? '-', trackId, }); } diff --git a/src/handlers/Chrome74.ts b/src/handlers/Chrome74.ts index 41736d13..afbef8af 100644 --- a/src/handlers/Chrome74.ts +++ b/src/handlers/Chrome74.ts @@ -15,6 +15,7 @@ import type { RtpHeaderExtensionDirection, } from '../RtpParameters'; import type { SctpCapabilities, SctpStreamParameters } from '../SctpParameters'; +import { RemoteSdp } from './sdp/RemoteSdp'; import * as sdpCommonUtils from './sdp/commonUtils'; import * as sdpUnifiedPlanUtils from './sdp/unifiedPlanUtils'; import * as ortcUtils from './ortc/utils'; @@ -32,7 +33,6 @@ import type { HandlerReceiveDataChannelOptions, HandlerReceiveDataChannelResult, } from './HandlerInterface'; -import { RemoteSdp } from './sdp/RemoteSdp'; const logger = new Logger('Chrome74'); @@ -61,7 +61,7 @@ export class Chrome74 // Map of RTCTransceivers indexed by MID. private readonly _mapMidTransceiver: Map = new Map(); - // Local stream for sending. + // Default local stream for sending if no `streamId` is given in send(). private readonly _sendStream = new MediaStream(); // Whether a DataChannel m=application section has been created. private _hasDataChannelMediaSection = false; @@ -333,6 +333,7 @@ export class Chrome74 async send({ track, + streamId, encodings, codecOptions, headerExtensionOptions, @@ -341,7 +342,12 @@ export class Chrome74 this.assertNotClosed(); this.assertSendDirection(); - logger.debug('send() [kind:%s, track.id:%s]', track.kind, track.id); + logger.debug( + 'send() [kind:%s, track.id:%s, streamId:%s]', + track.kind, + track.id, + streamId + ); if (encodings && encodings.length > 1) { encodings.forEach((encoding: RtpEncodingParameters, idx: number) => { @@ -484,6 +490,9 @@ export class Chrome74 offerMediaObject, }); + // Set msid. + sendingRtpParameters.msid = `${streamId ?? this._sendStream.id} ${track.id}`; + // Set RTP encodings by parsing the SDP offer if no encodings are given. if (!encodings) { sendingRtpParameters.encodings = sdpUnifiedPlanUtils.getRtpEncodings({ @@ -929,11 +938,17 @@ export class Chrome74 mapLocalId.set(trackId, localId); + // We ignore MSID `trackId` when consuming and always use our computed + // `trackId` which matches the `consumer.id`. + const { msidStreamId } = ortcUtils.getMsidStreamIdAndTrackId( + rtpParameters.msid + ); + this._remoteSdp.receive({ mid: localId, kind, offerRtpParameters: rtpParameters, - streamId: streamId ?? rtpParameters.rtcp!.cname!, + streamId: streamId ?? msidStreamId ?? rtpParameters.rtcp?.cname ?? '-', trackId, }); } diff --git a/src/handlers/FakeHandler.ts b/src/handlers/FakeHandler.ts index 72418cf5..b621fb50 100644 --- a/src/handlers/FakeHandler.ts +++ b/src/handlers/FakeHandler.ts @@ -19,6 +19,13 @@ import type { ExtendedRtpCapabilities, } from '../RtpParameters'; import type { SctpCapabilities } from '../SctpParameters'; +import { FakeEventTarget } from './fakeEvents/FakeEventTarget'; +import { + FakeEventListener, + FakeAddEventListenerOptions, + FakeEventListenerOptions, +} from './fakeEvents/FakeEventListener'; +import { FakeEvent } from './fakeEvents/FakeEvent'; import type { HandlerFactory, HandlerInterface, @@ -33,13 +40,6 @@ import type { HandlerReceiveDataChannelOptions, HandlerReceiveDataChannelResult, } from './HandlerInterface'; -import { FakeEventTarget } from './fakeEvents/FakeEventTarget'; -import { - FakeEventListener, - FakeAddEventListenerOptions, - FakeEventListenerOptions, -} from './fakeEvents/FakeEventListener'; -import { FakeEvent } from './fakeEvents/FakeEvent'; const logger = new Logger('FakeHandler'); @@ -65,6 +65,8 @@ export class FakeHandler ) => ExtendedRtpCapabilities; // Local RTCP CNAME. private _cname = `CNAME-${utils.generateRandomNumber()}`; + // Default sending MediaStream id. + private _defaultSendStreamId = `${utils.generateRandomNumber()}`; // Got transport local and remote parameters. private _transportReady = false; // Next localId. @@ -179,7 +181,7 @@ export class FakeHandler async send( // eslint-disable-next-line @typescript-eslint/no-unused-vars - { track, encodings, codecOptions, codec }: HandlerSendOptions + { track, streamId, encodings, codecOptions, codec }: HandlerSendOptions ): Promise { this.assertNotClosed(); @@ -214,6 +216,8 @@ export class FakeHandler sendingRtpParameters.mid = `mid-${utils.generateRandomNumber()}`; + sendingRtpParameters.msid = `${streamId ?? '-'} ${track.id}`; + if (!encodings) { encodings = [{}]; } @@ -235,6 +239,9 @@ export class FakeHandler mux: true, }; + // Set msid. + sendingRtpParameters.msid = `${streamId ?? this._defaultSendStreamId} ${track.id}`; + const localId = this._nextLocalId++; this._tracks.set(localId, track); diff --git a/src/handlers/Firefox120.ts b/src/handlers/Firefox120.ts index de006239..079c9a11 100644 --- a/src/handlers/Firefox120.ts +++ b/src/handlers/Firefox120.ts @@ -13,8 +13,10 @@ import type { ExtendedRtpCapabilities, } from '../RtpParameters'; import type { SctpCapabilities, SctpStreamParameters } from '../SctpParameters'; +import { RemoteSdp } from './sdp/RemoteSdp'; import * as sdpCommonUtils from './sdp/commonUtils'; import * as sdpUnifiedPlanUtils from './sdp/unifiedPlanUtils'; +import * as ortcUtils from './ortc/utils'; import type { HandlerFactory, HandlerInterface, @@ -29,7 +31,6 @@ import type { HandlerReceiveDataChannelOptions, HandlerReceiveDataChannelResult, } from './HandlerInterface'; -import { RemoteSdp } from './sdp/RemoteSdp'; const logger = new Logger('Firefox120'); @@ -55,7 +56,7 @@ export class Firefox120 // Map of RTCTransceivers indexed by MID. private readonly _mapMidTransceiver: Map = new Map(); - // Local stream for sending. + // Default local stream for sending if no `streamId` is given in send(). private readonly _sendStream = new MediaStream(); // Whether a DataChannel m=application section has been created. private _hasDataChannelMediaSection = false; @@ -336,6 +337,7 @@ export class Firefox120 async send({ track, + streamId, encodings, codecOptions, codec, @@ -344,7 +346,12 @@ export class Firefox120 this.assertNotClosed(); this.assertSendDirection(); - logger.debug('send() [kind:%s, track.id:%s]', track.kind, track.id); + logger.debug( + 'send() [kind:%s, track.id:%s, streamId:%s]', + track.kind, + track.id, + streamId + ); if (encodings && encodings.length > 1) { encodings.forEach((encoding: RtpEncodingParameters, idx: number) => { @@ -435,6 +442,9 @@ export class Firefox120 offerMediaObject, }); + // Set msid. + sendingRtpParameters.msid = `${streamId ?? this._sendStream.id} ${track.id}`; + // Set RTP encodings by parsing the SDP offer if no encodings are given. if (!encodings) { sendingRtpParameters.encodings = sdpUnifiedPlanUtils.getRtpEncodings({ @@ -873,11 +883,17 @@ export class Firefox120 mapLocalId.set(trackId, localId); + // We ignore MSID `trackId` when consuming and always use our computed + // `trackId` which matches the `consumer.id`. + const { msidStreamId } = ortcUtils.getMsidStreamIdAndTrackId( + rtpParameters.msid + ); + this._remoteSdp.receive({ mid: localId, kind, offerRtpParameters: rtpParameters, - streamId: streamId ?? rtpParameters.rtcp!.cname!, + streamId: streamId ?? msidStreamId ?? rtpParameters.rtcp?.cname ?? '-', trackId, }); } diff --git a/src/handlers/HandlerInterface.ts b/src/handlers/HandlerInterface.ts index 15e0c090..6b0384ae 100644 --- a/src/handlers/HandlerInterface.ts +++ b/src/handlers/HandlerInterface.ts @@ -48,6 +48,13 @@ export type HandlerFactory = { export type HandlerSendOptions = { track: MediaStreamTrack; + /** + * Stream id (it affects the `id` field of the `a=msid` attribute in the + * local SDP. If not given, all `Producers` will have the same `streamId` + * in their `rtpParameters.msid`. Such a value tells consuming endpoints + * which tracks to syncronize on reception. + */ + streamId?: string; encodings?: RtpEncodingParameters[]; codecOptions?: ProducerCodecOptions; headerExtensionOptions?: ProducerHeaderExtensionOptions; @@ -66,8 +73,9 @@ export type HandlerReceiveOptions = { kind: 'audio' | 'video'; rtpParameters: RtpParameters; /** - * Stream id. WebRTC based devices try to synchronize inbound streams with - * same streamId. If not given, the consuming device will be told to + * Stream id (it affects the `id` field of the `a=msid` attribute in the + * remote SDP. WebRTC based devices try to synchronize inbound streams with + * same `streamId`. If not given, the consuming device will be told to * synchronize all streams produced by the same endpoint. However libwebrtc * can just synchronize up to one audio stream with one video stream. */ diff --git a/src/handlers/ReactNative106.ts b/src/handlers/ReactNative106.ts index 0366f143..2bfa239b 100644 --- a/src/handlers/ReactNative106.ts +++ b/src/handlers/ReactNative106.ts @@ -15,6 +15,10 @@ import type { RtpHeaderExtensionDirection, } from '../RtpParameters'; import type { SctpCapabilities, SctpStreamParameters } from '../SctpParameters'; +import { RemoteSdp } from './sdp/RemoteSdp'; +import * as sdpCommonUtils from './sdp/commonUtils'; +import * as sdpUnifiedPlanUtils from './sdp/unifiedPlanUtils'; +import * as ortcUtils from './ortc/utils'; import type { HandlerFactory, HandlerInterface, @@ -29,10 +33,6 @@ import type { HandlerReceiveDataChannelOptions, HandlerReceiveDataChannelResult, } from './HandlerInterface'; -import { RemoteSdp } from './sdp/RemoteSdp'; -import * as sdpCommonUtils from './sdp/commonUtils'; -import * as sdpUnifiedPlanUtils from './sdp/unifiedPlanUtils'; -import * as ortcUtils from './ortc/utils'; const logger = new Logger('ReactNative106'); @@ -61,7 +61,7 @@ export class ReactNative106 // Map of RTCTransceivers indexed by MID. private readonly _mapMidTransceiver: Map = new Map(); - // Local stream for sending. + // Default local stream for sending if no `streamId` is given in send(). private readonly _sendStream = new MediaStream(); // Whether a DataChannel m=application section has been created. private _hasDataChannelMediaSection = false; @@ -339,6 +339,7 @@ export class ReactNative106 async send({ track, + streamId, encodings, codecOptions, headerExtensionOptions, @@ -348,7 +349,12 @@ export class ReactNative106 this.assertNotClosed(); this.assertSendDirection(); - logger.debug('send() [kind:%s, track.id:%s]', track.kind, track.id); + logger.debug( + 'send() [kind:%s, track.id:%s, streamId:%s]', + track.kind, + track.id, + streamId + ); if (encodings && encodings.length > 1) { encodings.forEach((encoding: RtpEncodingParameters, idx: number) => { @@ -509,6 +515,9 @@ export class ReactNative106 offerMediaObject, }); + // Set msid. + sendingRtpParameters.msid = `${streamId ?? this._sendStream.id} ${track.id}`; + // Set RTP encodings by parsing the SDP offer if no encodings are given. if (!encodings) { sendingRtpParameters.encodings = sdpUnifiedPlanUtils.getRtpEncodings({ @@ -963,11 +972,17 @@ export class ReactNative106 mapLocalId.set(trackId, localId); + // We ignore MSID `trackId` when consuming and always use our computed + // `trackId` which matches the `consumer.id`. + const { msidStreamId } = ortcUtils.getMsidStreamIdAndTrackId( + rtpParameters.msid + ); + this._remoteSdp.receive({ mid: localId, kind, offerRtpParameters: rtpParameters, - streamId: streamId ?? rtpParameters.rtcp!.cname!, + streamId: streamId ?? msidStreamId ?? rtpParameters.rtcp?.cname ?? '-', trackId, }); } diff --git a/src/handlers/Safari12.ts b/src/handlers/Safari12.ts index cb619412..de48f60d 100644 --- a/src/handlers/Safari12.ts +++ b/src/handlers/Safari12.ts @@ -14,6 +14,10 @@ import type { RtpHeaderExtensionDirection, } from '../RtpParameters'; import type { SctpCapabilities, SctpStreamParameters } from '../SctpParameters'; +import { RemoteSdp } from './sdp/RemoteSdp'; +import * as sdpCommonUtils from './sdp/commonUtils'; +import * as sdpUnifiedPlanUtils from './sdp/unifiedPlanUtils'; +import * as ortcUtils from './ortc/utils'; import type { HandlerFactory, HandlerInterface, @@ -28,10 +32,6 @@ import type { HandlerReceiveDataChannelOptions, HandlerReceiveDataChannelResult, } from './HandlerInterface'; -import { RemoteSdp } from './sdp/RemoteSdp'; -import * as sdpCommonUtils from './sdp/commonUtils'; -import * as sdpUnifiedPlanUtils from './sdp/unifiedPlanUtils'; -import * as ortcUtils from './ortc/utils'; const logger = new Logger('Safari12'); @@ -60,7 +60,7 @@ export class Safari12 // Map of RTCTransceivers indexed by MID. private readonly _mapMidTransceiver: Map = new Map(); - // Local stream for sending. + // Default local stream for sending if no `streamId` is given in send(). private readonly _sendStream = new MediaStream(); // Whether a DataChannel m=application section has been created. private _hasDataChannelMediaSection = false; @@ -343,6 +343,7 @@ export class Safari12 async send({ track, + streamId, encodings, codecOptions, headerExtensionOptions, @@ -352,7 +353,12 @@ export class Safari12 this.assertNotClosed(); this.assertSendDirection(); - logger.debug('send() [kind:%s, track.id:%s]', track.kind, track.id); + logger.debug( + 'send() [kind:%s, track.id:%s, streamId:%s]', + track.kind, + track.id, + streamId + ); const mediaSectionIdx = this._remoteSdp.getNextMediaSectionIdx(); const transceiver = this._pc.addTransceiver(track, { @@ -485,6 +491,9 @@ export class Safari12 offerMediaObject, }); + // Set msid. + sendingRtpParameters.msid = `${streamId ?? this._sendStream.id} ${track.id}`; + // Set RTP encodings. sendingRtpParameters.encodings = sdpUnifiedPlanUtils.getRtpEncodings({ offerMediaObject, @@ -916,11 +925,17 @@ export class Safari12 mapLocalId.set(trackId, localId); + // We ignore MSID `trackId` when consuming and always use our computed + // `trackId` which matches the `consumer.id`. + const { msidStreamId } = ortcUtils.getMsidStreamIdAndTrackId( + rtpParameters.msid + ); + this._remoteSdp.receive({ mid: localId, kind, offerRtpParameters: rtpParameters, - streamId: streamId ?? rtpParameters.rtcp!.cname!, + streamId: streamId ?? msidStreamId ?? rtpParameters.rtcp?.cname ?? '-', trackId, }); } diff --git a/src/handlers/ortc/utils.ts b/src/handlers/ortc/utils.ts index c749249d..16bfb298 100644 --- a/src/handlers/ortc/utils.ts +++ b/src/handlers/ortc/utils.ts @@ -70,3 +70,24 @@ export function addHeaderExtensionSupport( rtpCapabilities.headerExtensions.push(newHeaderExtension); } + +export function getMsidStreamIdAndTrackId(msid?: string): { + msidStreamId?: string; + msidTrackId?: string; +} { + if (!msid || typeof msid !== 'string') { + return { msidStreamId: undefined, msidTrackId: undefined }; + } + + /** + * `msidStreamId` must be an id or '-' (no stream). + * `msidTrackId` is an optional id. + */ + const [msidStreamId, msidTrackId] = msid.trim().split(/\s+/); + + if (!msidStreamId) { + return { msidStreamId: undefined, msidTrackId: undefined }; + } + + return { msidStreamId, msidTrackId }; +} diff --git a/src/handlers/sdp/MediaSection.ts b/src/handlers/sdp/MediaSection.ts index dab61643..e7675412 100644 --- a/src/handlers/sdp/MediaSection.ts +++ b/src/handlers/sdp/MediaSection.ts @@ -479,6 +479,7 @@ export class OfferMediaSection extends MediaSection { plainRtpParameters?: PlainRtpParameters; mid: string; kind: MediaKind | 'application'; + // Those are optionals because they are only given if `kind` is a MediaKind. offerRtpParameters?: RtpParameters; streamId?: string; trackId?: string; @@ -518,7 +519,7 @@ export class OfferMediaSection extends MediaSection { this._mediaObject.rtp = []; this._mediaObject.rtcpFb = []; this._mediaObject.fmtp = []; - this._mediaObject.msid = `${streamId ?? '-'} ${trackId}`; + this._mediaObject.msid = `${streamId} ${trackId}`; for (const codec of offerRtpParameters!.codecs) { const rtp: SdpTransform.MediaAttributes['rtp'][number] = { diff --git a/src/handlers/sdp/RemoteSdp.ts b/src/handlers/sdp/RemoteSdp.ts index 75d22b5b..f7c998ca 100644 --- a/src/handlers/sdp/RemoteSdp.ts +++ b/src/handlers/sdp/RemoteSdp.ts @@ -84,8 +84,6 @@ export class RemoteSdp { // If DTLS parameters are given, assume WebRTC and BUNDLE. if (dtlsParameters) { - this._sdpObject.msidSemantic = { semantic: 'WMS', token: '*' }; - // NOTE: We take the latest fingerprint. const numFingerprints = this._dtlsParameters!.fingerprints.length; @@ -190,15 +188,15 @@ export class RemoteSdp { // Unified-Plan with closed media section replacement. if (reuseMid) { - this._replaceMediaSection(mediaSection, reuseMid); + this.replaceMediaSection(mediaSection, reuseMid); } // Unified-Plan or Plan-B with different media kind. else if (!this._midToIndex.has(mediaSection.mid)) { - this._addMediaSection(mediaSection); + this.addMediaSection(mediaSection); } // Plan-B with same media kind. else { - this._replaceMediaSection(mediaSection); + this.replaceMediaSection(mediaSection); } } @@ -236,32 +234,32 @@ export class RemoteSdp { const oldMediaSection = this._mediaSections.find(m => m.closed); if (oldMediaSection) { - this._replaceMediaSection(mediaSection, oldMediaSection.mid); + this.replaceMediaSection(mediaSection, oldMediaSection.mid); } else { - this._addMediaSection(mediaSection); + this.addMediaSection(mediaSection); } } pauseMediaSection(mid: string): void { - const mediaSection = this._findMediaSection(mid); + const mediaSection = this.findMediaSection(mid); mediaSection.pause(); } resumeSendingMediaSection(mid: string): void { - const mediaSection = this._findMediaSection(mid); + const mediaSection = this.findMediaSection(mid); mediaSection.resume(); } resumeReceivingMediaSection(mid: string): void { - const mediaSection = this._findMediaSection(mid); + const mediaSection = this.findMediaSection(mid); mediaSection.resume(); } disableMediaSection(mid: string): void { - const mediaSection = this._findMediaSection(mid); + const mediaSection = this.findMediaSection(mid); mediaSection.disable(); } @@ -274,7 +272,7 @@ export class RemoteSdp { * transport, so instead closing it we just disable it. */ closeMediaSection(mid: string): boolean { - const mediaSection = this._findMediaSection(mid); + const mediaSection = this.findMediaSection(mid); // NOTE: Closing the first m section is a pain since it invalidates the // bundled transport, so let's avoid it. @@ -292,7 +290,7 @@ export class RemoteSdp { mediaSection.close(); // Regenerate BUNDLE mids. - this._regenerateBundleMids(); + this.regenerateBundleMids(); return true; } @@ -301,11 +299,11 @@ export class RemoteSdp { mid: string, encodings: RTCRtpEncodingParameters[] ): void { - const mediaSection = this._findMediaSection(mid) as AnswerMediaSection; + const mediaSection = this.findMediaSection(mid) as AnswerMediaSection; mediaSection.muxSimulcastStreams(encodings); - this._replaceMediaSection(mediaSection); + this.replaceMediaSection(mediaSection); } sendSctpAssociation({ @@ -322,7 +320,7 @@ export class RemoteSdp { offerMediaObject, }); - this._addMediaSection(mediaSection); + this.addMediaSection(mediaSection); } receiveSctpAssociation(): void { @@ -336,7 +334,7 @@ export class RemoteSdp { kind: 'application', }); - this._addMediaSection(mediaSection); + this.addMediaSection(mediaSection); } getSdp(): string { @@ -346,7 +344,7 @@ export class RemoteSdp { return sdpTransform.write(this._sdpObject); } - _addMediaSection(newMediaSection: MediaSection): void { + private addMediaSection(newMediaSection: MediaSection): void { if (!this._firstMid) { this._firstMid = newMediaSection.mid; } @@ -361,10 +359,13 @@ export class RemoteSdp { this._sdpObject.media.push(newMediaSection.getObject()); // Regenerate BUNDLE mids. - this._regenerateBundleMids(); + this.regenerateBundleMids(); } - _replaceMediaSection(newMediaSection: MediaSection, reuseMid?: string): void { + private replaceMediaSection( + newMediaSection: MediaSection, + reuseMid?: string + ): void { // Store it in the map. if (typeof reuseMid === 'string') { const idx = this._midToIndex.get(reuseMid); @@ -386,7 +387,7 @@ export class RemoteSdp { this._sdpObject.media[idx] = newMediaSection.getObject(); // Regenerate BUNDLE mids. - this._regenerateBundleMids(); + this.regenerateBundleMids(); } else { const idx = this._midToIndex.get(newMediaSection.mid); @@ -404,7 +405,7 @@ export class RemoteSdp { } } - _findMediaSection(mid: string): MediaSection { + private findMediaSection(mid: string): MediaSection { const idx = this._midToIndex.get(mid); if (idx === undefined) { @@ -414,7 +415,7 @@ export class RemoteSdp { return this._mediaSections[idx]!; } - _regenerateBundleMids(): void { + private regenerateBundleMids(): void { if (!this._dtlsParameters) { return; }