Skip to content

Commit 5bc27f9

Browse files
authored
RtpParameters: add msid optional field and streamId in ProducerOptions (#352)
1 parent 2d59ecb commit 5bc27f9

File tree

15 files changed

+192
-69
lines changed

15 files changed

+192
-69
lines changed

src/Consumer.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import type { AppData } from './types';
77
const logger = new Logger('Consumer');
88

99
export type ConsumerOptions<ConsumerAppData extends AppData = AppData> = {
10-
id?: string;
11-
producerId?: string;
12-
kind?: 'audio' | 'video';
10+
id: string;
11+
producerId: string;
12+
kind: 'audio' | 'video';
1313
rtpParameters: RtpParameters;
1414
streamId?: string;
1515
onRtpReceiver?: OnRtpReceiverCallback;

src/DataConsumer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ const logger = new Logger('DataConsumer');
77

88
export type DataConsumerOptions<DataConsumerAppData extends AppData = AppData> =
99
{
10-
id?: string;
11-
dataProducerId?: string;
10+
id: string;
11+
dataProducerId: string;
1212
sctpStreamParameters: SctpStreamParameters;
1313
label?: string;
1414
protocol?: string;

src/Producer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const logger = new Logger('Producer');
1313

1414
export type ProducerOptions<ProducerAppData extends AppData = AppData> = {
1515
track?: MediaStreamTrack;
16+
streamId?: string;
1617
encodings?: RtpEncodingParameters[];
1718
codecOptions?: ProducerCodecOptions;
1819
headerExtensionOptions?: ProducerHeaderExtensionOptions;

src/RtpParameters.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,12 @@ export type RtpParameters = {
164164
* Parameters used for RTCP.
165165
*/
166166
rtcp?: RtcpParameters;
167+
/**
168+
* MSID (WebRTC MediaStream Identification).
169+
*
170+
* @see https://datatracker.ietf.org/doc/html/rfc8830
171+
*/
172+
msid?: string;
167173
};
168174

169175
/**

src/Transport.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ export class Transport<
500500
*/
501501
async produce<ProducerAppData extends AppData = AppData>({
502502
track,
503+
streamId,
503504
encodings,
504505
codecOptions,
505506
headerExtensionOptions,
@@ -587,6 +588,7 @@ export class Transport<
587588
const { localId, rtpParameters, rtpSender } =
588589
await this._handler.send({
589590
track,
591+
streamId,
590592
encodings: normalizedEncodings,
591593
codecOptions,
592594
headerExtensionOptions,
@@ -902,8 +904,8 @@ export class Transport<
902904
task.consumerOptions;
903905

904906
optionsList.push({
905-
trackId: id!,
906-
kind: kind!,
907+
trackId: id,
908+
kind: kind,
907909
rtpParameters,
908910
streamId,
909911
onRtpReceiver,
@@ -920,9 +922,9 @@ export class Transport<
920922
task.consumerOptions;
921923
const { localId, rtpReceiver, track } = result;
922924
const consumer: Consumer<ConsumerAppData> = new Consumer({
923-
id: id!,
925+
id,
924926
localId,
925-
producerId: producerId!,
927+
producerId,
926928
rtpReceiver,
927929
track,
928930
rtpParameters,

src/handlers/Chrome111.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {
1414
RtpHeaderExtensionDirection,
1515
} from '../RtpParameters';
1616
import type { SctpCapabilities, SctpStreamParameters } from '../SctpParameters';
17+
import { RemoteSdp } from './sdp/RemoteSdp';
1718
import * as sdpCommonUtils from './sdp/commonUtils';
1819
import * as sdpUnifiedPlanUtils from './sdp/unifiedPlanUtils';
1920
import * as ortcUtils from './ortc/utils';
@@ -31,7 +32,6 @@ import type {
3132
HandlerReceiveDataChannelOptions,
3233
HandlerReceiveDataChannelResult,
3334
} from './HandlerInterface';
34-
import { RemoteSdp } from './sdp/RemoteSdp';
3535

3636
const logger = new Logger('Chrome111');
3737

@@ -60,7 +60,7 @@ export class Chrome111
6060
// Map of RTCTransceivers indexed by MID.
6161
private readonly _mapMidTransceiver: Map<string, RTCRtpTransceiver> =
6262
new Map();
63-
// Local stream for sending.
63+
// Default local stream for sending if no `streamId` is given in send().
6464
private readonly _sendStream = new MediaStream();
6565
// Whether a DataChannel m=application section has been created.
6666
private _hasDataChannelMediaSection = false;
@@ -336,6 +336,7 @@ export class Chrome111
336336

337337
async send({
338338
track,
339+
streamId,
339340
encodings,
340341
codecOptions,
341342
headerExtensionOptions,
@@ -345,7 +346,12 @@ export class Chrome111
345346
this.assertNotClosed();
346347
this.assertSendDirection();
347348

348-
logger.debug('send() [kind:%s, track.id:%s]', track.kind, track.id);
349+
logger.debug(
350+
'send() [kind:%s, track.id:%s, streamId:%s]',
351+
track.kind,
352+
track.id,
353+
streamId
354+
);
349355

350356
if (encodings && encodings.length > 1) {
351357
// Set rid and verify scalabilityMode in each encoding.
@@ -481,6 +487,9 @@ export class Chrome111
481487
offerMediaObject,
482488
});
483489

490+
// Set msid.
491+
sendingRtpParameters.msid = `${streamId ?? this._sendStream.id} ${track.id}`;
492+
484493
// Set RTP encodings by parsing the SDP offer if no encodings are given.
485494
if (!encodings) {
486495
sendingRtpParameters.encodings = sdpUnifiedPlanUtils.getRtpEncodings({
@@ -905,11 +914,17 @@ export class Chrome111
905914

906915
mapLocalId.set(trackId, localId);
907916

917+
// We ignore MSID `trackId` when consuming and always use our computed
918+
// `trackId` which matches the `consumer.id`.
919+
const { msidStreamId } = ortcUtils.getMsidStreamIdAndTrackId(
920+
rtpParameters.msid
921+
);
922+
908923
this._remoteSdp.receive({
909924
mid: localId,
910925
kind,
911926
offerRtpParameters: rtpParameters,
912-
streamId: streamId ?? rtpParameters.rtcp!.cname!,
927+
streamId: streamId ?? msidStreamId ?? rtpParameters.rtcp?.cname ?? '-',
913928
trackId,
914929
});
915930
}

src/handlers/Chrome74.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {
1515
RtpHeaderExtensionDirection,
1616
} from '../RtpParameters';
1717
import type { SctpCapabilities, SctpStreamParameters } from '../SctpParameters';
18+
import { RemoteSdp } from './sdp/RemoteSdp';
1819
import * as sdpCommonUtils from './sdp/commonUtils';
1920
import * as sdpUnifiedPlanUtils from './sdp/unifiedPlanUtils';
2021
import * as ortcUtils from './ortc/utils';
@@ -32,7 +33,6 @@ import type {
3233
HandlerReceiveDataChannelOptions,
3334
HandlerReceiveDataChannelResult,
3435
} from './HandlerInterface';
35-
import { RemoteSdp } from './sdp/RemoteSdp';
3636

3737
const logger = new Logger('Chrome74');
3838

@@ -61,7 +61,7 @@ export class Chrome74
6161
// Map of RTCTransceivers indexed by MID.
6262
private readonly _mapMidTransceiver: Map<string, RTCRtpTransceiver> =
6363
new Map();
64-
// Local stream for sending.
64+
// Default local stream for sending if no `streamId` is given in send().
6565
private readonly _sendStream = new MediaStream();
6666
// Whether a DataChannel m=application section has been created.
6767
private _hasDataChannelMediaSection = false;
@@ -333,6 +333,7 @@ export class Chrome74
333333

334334
async send({
335335
track,
336+
streamId,
336337
encodings,
337338
codecOptions,
338339
headerExtensionOptions,
@@ -341,7 +342,12 @@ export class Chrome74
341342
this.assertNotClosed();
342343
this.assertSendDirection();
343344

344-
logger.debug('send() [kind:%s, track.id:%s]', track.kind, track.id);
345+
logger.debug(
346+
'send() [kind:%s, track.id:%s, streamId:%s]',
347+
track.kind,
348+
track.id,
349+
streamId
350+
);
345351

346352
if (encodings && encodings.length > 1) {
347353
encodings.forEach((encoding: RtpEncodingParameters, idx: number) => {
@@ -484,6 +490,9 @@ export class Chrome74
484490
offerMediaObject,
485491
});
486492

493+
// Set msid.
494+
sendingRtpParameters.msid = `${streamId ?? this._sendStream.id} ${track.id}`;
495+
487496
// Set RTP encodings by parsing the SDP offer if no encodings are given.
488497
if (!encodings) {
489498
sendingRtpParameters.encodings = sdpUnifiedPlanUtils.getRtpEncodings({
@@ -929,11 +938,17 @@ export class Chrome74
929938

930939
mapLocalId.set(trackId, localId);
931940

941+
// We ignore MSID `trackId` when consuming and always use our computed
942+
// `trackId` which matches the `consumer.id`.
943+
const { msidStreamId } = ortcUtils.getMsidStreamIdAndTrackId(
944+
rtpParameters.msid
945+
);
946+
932947
this._remoteSdp.receive({
933948
mid: localId,
934949
kind,
935950
offerRtpParameters: rtpParameters,
936-
streamId: streamId ?? rtpParameters.rtcp!.cname!,
951+
streamId: streamId ?? msidStreamId ?? rtpParameters.rtcp?.cname ?? '-',
937952
trackId,
938953
});
939954
}

src/handlers/FakeHandler.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ import type {
1919
ExtendedRtpCapabilities,
2020
} from '../RtpParameters';
2121
import type { SctpCapabilities } from '../SctpParameters';
22+
import { FakeEventTarget } from './fakeEvents/FakeEventTarget';
23+
import {
24+
FakeEventListener,
25+
FakeAddEventListenerOptions,
26+
FakeEventListenerOptions,
27+
} from './fakeEvents/FakeEventListener';
28+
import { FakeEvent } from './fakeEvents/FakeEvent';
2229
import type {
2330
HandlerFactory,
2431
HandlerInterface,
@@ -33,13 +40,6 @@ import type {
3340
HandlerReceiveDataChannelOptions,
3441
HandlerReceiveDataChannelResult,
3542
} from './HandlerInterface';
36-
import { FakeEventTarget } from './fakeEvents/FakeEventTarget';
37-
import {
38-
FakeEventListener,
39-
FakeAddEventListenerOptions,
40-
FakeEventListenerOptions,
41-
} from './fakeEvents/FakeEventListener';
42-
import { FakeEvent } from './fakeEvents/FakeEvent';
4343

4444
const logger = new Logger('FakeHandler');
4545

@@ -65,6 +65,8 @@ export class FakeHandler
6565
) => ExtendedRtpCapabilities;
6666
// Local RTCP CNAME.
6767
private _cname = `CNAME-${utils.generateRandomNumber()}`;
68+
// Default sending MediaStream id.
69+
private _defaultSendStreamId = `${utils.generateRandomNumber()}`;
6870
// Got transport local and remote parameters.
6971
private _transportReady = false;
7072
// Next localId.
@@ -179,7 +181,7 @@ export class FakeHandler
179181

180182
async send(
181183
// eslint-disable-next-line @typescript-eslint/no-unused-vars
182-
{ track, encodings, codecOptions, codec }: HandlerSendOptions
184+
{ track, streamId, encodings, codecOptions, codec }: HandlerSendOptions
183185
): Promise<HandlerSendResult> {
184186
this.assertNotClosed();
185187

@@ -214,6 +216,8 @@ export class FakeHandler
214216

215217
sendingRtpParameters.mid = `mid-${utils.generateRandomNumber()}`;
216218

219+
sendingRtpParameters.msid = `${streamId ?? '-'} ${track.id}`;
220+
217221
if (!encodings) {
218222
encodings = [{}];
219223
}
@@ -235,6 +239,9 @@ export class FakeHandler
235239
mux: true,
236240
};
237241

242+
// Set msid.
243+
sendingRtpParameters.msid = `${streamId ?? this._defaultSendStreamId} ${track.id}`;
244+
238245
const localId = this._nextLocalId++;
239246

240247
this._tracks.set(localId, track);

src/handlers/Firefox120.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ import type {
1313
ExtendedRtpCapabilities,
1414
} from '../RtpParameters';
1515
import type { SctpCapabilities, SctpStreamParameters } from '../SctpParameters';
16+
import { RemoteSdp } from './sdp/RemoteSdp';
1617
import * as sdpCommonUtils from './sdp/commonUtils';
1718
import * as sdpUnifiedPlanUtils from './sdp/unifiedPlanUtils';
19+
import * as ortcUtils from './ortc/utils';
1820
import type {
1921
HandlerFactory,
2022
HandlerInterface,
@@ -29,7 +31,6 @@ import type {
2931
HandlerReceiveDataChannelOptions,
3032
HandlerReceiveDataChannelResult,
3133
} from './HandlerInterface';
32-
import { RemoteSdp } from './sdp/RemoteSdp';
3334

3435
const logger = new Logger('Firefox120');
3536

@@ -55,7 +56,7 @@ export class Firefox120
5556
// Map of RTCTransceivers indexed by MID.
5657
private readonly _mapMidTransceiver: Map<string, RTCRtpTransceiver> =
5758
new Map();
58-
// Local stream for sending.
59+
// Default local stream for sending if no `streamId` is given in send().
5960
private readonly _sendStream = new MediaStream();
6061
// Whether a DataChannel m=application section has been created.
6162
private _hasDataChannelMediaSection = false;
@@ -336,6 +337,7 @@ export class Firefox120
336337

337338
async send({
338339
track,
340+
streamId,
339341
encodings,
340342
codecOptions,
341343
codec,
@@ -344,7 +346,12 @@ export class Firefox120
344346
this.assertNotClosed();
345347
this.assertSendDirection();
346348

347-
logger.debug('send() [kind:%s, track.id:%s]', track.kind, track.id);
349+
logger.debug(
350+
'send() [kind:%s, track.id:%s, streamId:%s]',
351+
track.kind,
352+
track.id,
353+
streamId
354+
);
348355

349356
if (encodings && encodings.length > 1) {
350357
encodings.forEach((encoding: RtpEncodingParameters, idx: number) => {
@@ -435,6 +442,9 @@ export class Firefox120
435442
offerMediaObject,
436443
});
437444

445+
// Set msid.
446+
sendingRtpParameters.msid = `${streamId ?? this._sendStream.id} ${track.id}`;
447+
438448
// Set RTP encodings by parsing the SDP offer if no encodings are given.
439449
if (!encodings) {
440450
sendingRtpParameters.encodings = sdpUnifiedPlanUtils.getRtpEncodings({
@@ -873,11 +883,17 @@ export class Firefox120
873883

874884
mapLocalId.set(trackId, localId);
875885

886+
// We ignore MSID `trackId` when consuming and always use our computed
887+
// `trackId` which matches the `consumer.id`.
888+
const { msidStreamId } = ortcUtils.getMsidStreamIdAndTrackId(
889+
rtpParameters.msid
890+
);
891+
876892
this._remoteSdp.receive({
877893
mid: localId,
878894
kind,
879895
offerRtpParameters: rtpParameters,
880-
streamId: streamId ?? rtpParameters.rtcp!.cname!,
896+
streamId: streamId ?? msidStreamId ?? rtpParameters.rtcp?.cname ?? '-',
881897
trackId,
882898
});
883899
}

0 commit comments

Comments
 (0)