|
|
@@ -80,34 +80,6 @@ export class TPCUtils {
|
|
80
|
80
|
];
|
|
81
|
81
|
}
|
|
82
|
82
|
|
|
83
|
|
- /**
|
|
84
|
|
- * Returns the transceiver associated with a given RTCRtpSender/RTCRtpReceiver.
|
|
85
|
|
- *
|
|
86
|
|
- * @param {string} mediaType - type of track associated with the transceiver 'audio' or 'video'.
|
|
87
|
|
- * @param {JitsiLocalTrack} localTrack - local track to be used for lookup.
|
|
88
|
|
- * @returns {RTCRtpTransceiver}
|
|
89
|
|
- */
|
|
90
|
|
- _findTransceiver(mediaType, localTrack = null) {
|
|
91
|
|
- let transceiver = null;
|
|
92
|
|
-
|
|
93
|
|
- // Check if the local track has been removed from the peerconnection already.
|
|
94
|
|
- const trackRemoved = !localTrack
|
|
95
|
|
- || (localTrack
|
|
96
|
|
- && browser.doesVideoMuteByStreamRemove()
|
|
97
|
|
- && localTrack.isVideoTrack()
|
|
98
|
|
- && localTrack.isMuted());
|
|
99
|
|
-
|
|
100
|
|
- if (trackRemoved) {
|
|
101
|
|
- transceiver = this.pc.peerconnection.getTransceivers()
|
|
102
|
|
- .find(t => t.receiver?.track?.kind === mediaType);
|
|
103
|
|
- } else if (localTrack) {
|
|
104
|
|
- transceiver = this.pc.peerconnection.getTransceivers()
|
|
105
|
|
- .find(t => t.sender?.track?.id === localTrack.getTrackId());
|
|
106
|
|
- }
|
|
107
|
|
-
|
|
108
|
|
- return transceiver;
|
|
109
|
|
- }
|
|
110
|
|
-
|
|
111
|
83
|
/**
|
|
112
|
84
|
* Obtains stream encodings that need to be configured on the given track based
|
|
113
|
85
|
* on the track media type and the simulcast setting.
|
|
|
@@ -169,6 +141,21 @@ export class TPCUtils {
|
|
169
|
141
|
});
|
|
170
|
142
|
}
|
|
171
|
143
|
|
|
|
144
|
+ /**
|
|
|
145
|
+ * Returns the transceiver associated with a given RTCRtpSender/RTCRtpReceiver.
|
|
|
146
|
+ *
|
|
|
147
|
+ * @param {string} mediaType - type of track associated with the transceiver 'audio' or 'video'.
|
|
|
148
|
+ * @param {JitsiLocalTrack} localTrack - local track to be used for lookup.
|
|
|
149
|
+ * @returns {RTCRtpTransceiver}
|
|
|
150
|
+ */
|
|
|
151
|
+ findTransceiver(mediaType, localTrack = null) {
|
|
|
152
|
+ const transceiver = localTrack?.track && localTrack.getOriginalStream()
|
|
|
153
|
+ ? this.pc.peerconnection.getTransceivers().find(t => t.sender?.track?.id === localTrack.getTrackId())
|
|
|
154
|
+ : this.pc.peerconnection.getTransceivers().find(t => t.receiver?.track?.kind === mediaType);
|
|
|
155
|
+
|
|
|
156
|
+ return transceiver;
|
|
|
157
|
+ }
|
|
|
158
|
+
|
|
172
|
159
|
/**
|
|
173
|
160
|
* Takes in a *unified plan* offer and inserts the appropriate
|
|
174
|
161
|
* parameters for adding simulcast receive support.
|
|
|
@@ -271,24 +258,6 @@ export class TPCUtils {
|
|
271
|
258
|
}
|
|
272
|
259
|
}
|
|
273
|
260
|
|
|
274
|
|
- /**
|
|
275
|
|
- * Adds a track on the RTCRtpSender as part of the unmute operation.
|
|
276
|
|
- * @param {JitsiLocalTrack} localTrack - track to be unmuted.
|
|
277
|
|
- * @returns {Promise<void>} - resolved when done.
|
|
278
|
|
- */
|
|
279
|
|
- addTrackUnmute(localTrack) {
|
|
280
|
|
- const mediaType = localTrack.getType();
|
|
281
|
|
- const track = localTrack.getTrack();
|
|
282
|
|
- const transceiver = this._findTransceiver(mediaType);
|
|
283
|
|
-
|
|
284
|
|
- if (!transceiver) {
|
|
285
|
|
- return Promise.reject(new Error(`RTCRtpTransceiver for ${mediaType} not found`));
|
|
286
|
|
- }
|
|
287
|
|
- logger.debug(`${this.pc} Adding ${localTrack}`);
|
|
288
|
|
-
|
|
289
|
|
- return transceiver.sender.replaceTrack(track);
|
|
290
|
|
- }
|
|
291
|
|
-
|
|
292
|
261
|
/**
|
|
293
|
262
|
* Returns the calculated active state of the simulcast encodings based on the frame height requested for the send
|
|
294
|
263
|
* stream. All the encodings that have a resolution lower than the frame height requested will be enabled.
|
|
|
@@ -368,24 +337,6 @@ export class TPCUtils {
|
|
368
|
337
|
return encodingsBitrates;
|
|
369
|
338
|
}
|
|
370
|
339
|
|
|
371
|
|
- /**
|
|
372
|
|
- * Removes the track from the RTCRtpSender as part of the mute operation.
|
|
373
|
|
- * @param {JitsiLocalTrack} localTrack - track to be removed.
|
|
374
|
|
- * @returns {Promise<void>} - resolved when done.
|
|
375
|
|
- */
|
|
376
|
|
- removeTrackMute(localTrack) {
|
|
377
|
|
- const mediaType = localTrack.getType();
|
|
378
|
|
- const transceiver = this._findTransceiver(mediaType, localTrack);
|
|
379
|
|
-
|
|
380
|
|
- if (!transceiver) {
|
|
381
|
|
- return Promise.reject(new Error(`RTCRtpTransceiver for ${mediaType} not found`));
|
|
382
|
|
- }
|
|
383
|
|
-
|
|
384
|
|
- logger.debug(`${this.pc} Removing ${localTrack}`);
|
|
385
|
|
-
|
|
386
|
|
- return transceiver.sender.replaceTrack(null);
|
|
387
|
|
- }
|
|
388
|
|
-
|
|
389
|
340
|
/**
|
|
390
|
341
|
* Replaces the existing track on a RTCRtpSender with the given track.
|
|
391
|
342
|
* @param {JitsiLocalTrack} oldTrack - existing track on the sender that needs to be removed.
|
|
|
@@ -393,86 +344,16 @@ export class TPCUtils {
|
|
393
|
344
|
* @returns {Promise<void>} - resolved when done.
|
|
394
|
345
|
*/
|
|
395
|
346
|
replaceTrack(oldTrack, newTrack) {
|
|
396
|
|
- if (oldTrack && newTrack) {
|
|
397
|
|
- const mediaType = newTrack.getType();
|
|
398
|
|
- const stream = newTrack.getOriginalStream();
|
|
399
|
|
-
|
|
400
|
|
- // Ignore cases when the track is replaced while the device is in a muted state,like
|
|
401
|
|
- // replacing camera when video muted or replacing mic when audio muted. These JitsiLocalTracks
|
|
402
|
|
- // do not have a mediastream attached. Replace track will be called again when the device is
|
|
403
|
|
- // unmuted and the track will be replaced on the peerconnection then.
|
|
404
|
|
- if (!stream) {
|
|
405
|
|
- this.pc.localTracks.delete(oldTrack.rtcId);
|
|
406
|
|
- this.pc.localTracks.set(newTrack.rtcId, newTrack);
|
|
407
|
|
-
|
|
408
|
|
- return Promise.resolve();
|
|
409
|
|
- }
|
|
410
|
|
-
|
|
411
|
|
- const transceiver = this._findTransceiver(mediaType, oldTrack);
|
|
412
|
|
- const track = newTrack.getTrack();
|
|
|
347
|
+ const mediaType = newTrack?.getType() ?? oldTrack?.getType();
|
|
|
348
|
+ const transceiver = this.findTransceiver(mediaType, oldTrack);
|
|
|
349
|
+ const track = newTrack?.getTrack() ?? null;
|
|
413
|
350
|
|
|
414
|
|
- if (!transceiver) {
|
|
415
|
|
- return Promise.reject(new Error('replace track failed'));
|
|
416
|
|
- }
|
|
417
|
|
- logger.debug(`${this.pc} Replacing ${oldTrack} with ${newTrack}`);
|
|
418
|
|
-
|
|
419
|
|
- return transceiver.sender.replaceTrack(track)
|
|
420
|
|
- .then(() => {
|
|
421
|
|
- const ssrc = this.pc.localSSRCs.get(oldTrack.rtcId);
|
|
422
|
|
-
|
|
423
|
|
- this.pc.localTracks.delete(oldTrack.rtcId);
|
|
424
|
|
- this.pc.localSSRCs.delete(oldTrack.rtcId);
|
|
425
|
|
- this.pc._addedStreams = this.pc._addedStreams.filter(s => s !== stream);
|
|
426
|
|
- this.pc.localTracks.set(newTrack.rtcId, newTrack);
|
|
427
|
|
-
|
|
428
|
|
- this.pc._addedStreams.push(stream);
|
|
429
|
|
- this.pc.localSSRCs.set(newTrack.rtcId, ssrc);
|
|
430
|
|
- });
|
|
431
|
|
- } else if (oldTrack && !newTrack) {
|
|
432
|
|
- return this.removeTrackMute(oldTrack)
|
|
433
|
|
- .then(() => {
|
|
434
|
|
- const mediaType = oldTrack.getType();
|
|
435
|
|
- const transceiver = this._findTransceiver(mediaType);
|
|
436
|
|
-
|
|
437
|
|
- // Change the direction on the transceiver to 'recvonly' so that a 'removetrack'
|
|
438
|
|
- // is fired on the associated media stream on the remote peer.
|
|
439
|
|
- if (transceiver) {
|
|
440
|
|
- transceiver.direction = MediaDirection.RECVONLY;
|
|
441
|
|
- }
|
|
442
|
|
-
|
|
443
|
|
- // Remove the old track from the list of local tracks.
|
|
444
|
|
- this.pc.localTracks.delete(oldTrack.rtcId);
|
|
445
|
|
- this.pc.localSSRCs.delete(oldTrack.rtcId);
|
|
446
|
|
- });
|
|
447
|
|
- } else if (newTrack && !oldTrack) {
|
|
448
|
|
- return this.addTrackUnmute(newTrack)
|
|
449
|
|
- .then(() => {
|
|
450
|
|
- const mediaType = newTrack.getType();
|
|
451
|
|
- const transceiver = this._findTransceiver(mediaType, newTrack);
|
|
452
|
|
-
|
|
453
|
|
- // Change the direction on the transceiver back to 'sendrecv' so that a 'track'
|
|
454
|
|
- // event is fired on the remote peer.
|
|
455
|
|
- if (transceiver) {
|
|
456
|
|
- transceiver.direction = MediaDirection.SENDRECV;
|
|
457
|
|
- }
|
|
458
|
|
-
|
|
459
|
|
- // Avoid configuring the encodings on Chromium/Safari until simulcast is configured
|
|
460
|
|
- // for the newly added track using SDP munging which happens during the renegotiation.
|
|
461
|
|
- const promise = browser.usesSdpMungingForSimulcast()
|
|
462
|
|
- ? Promise.resolve()
|
|
463
|
|
- : this.setEncodings(newTrack);
|
|
464
|
|
-
|
|
465
|
|
- return promise
|
|
466
|
|
- .then(() => {
|
|
467
|
|
- // Add the new track to the list of local tracks.
|
|
468
|
|
- this.pc.localTracks.set(newTrack.rtcId, newTrack);
|
|
469
|
|
- });
|
|
470
|
|
- });
|
|
|
351
|
+ if (!transceiver) {
|
|
|
352
|
+ return Promise.reject(new Error('replace track failed'));
|
|
471
|
353
|
}
|
|
|
354
|
+ logger.debug(`${this.pc} Replacing ${oldTrack} with ${newTrack}`);
|
|
472
|
355
|
|
|
473
|
|
- logger.info(`${this.pc} TPCUtils.replaceTrack called with no new track and no old track`);
|
|
474
|
|
-
|
|
475
|
|
- return Promise.resolve();
|
|
|
356
|
+ return transceiver.sender.replaceTrack(track);
|
|
476
|
357
|
}
|
|
477
|
358
|
|
|
478
|
359
|
/**
|
|
|
@@ -496,7 +377,7 @@ export class TPCUtils {
|
|
496
|
377
|
*/
|
|
497
|
378
|
setEncodings(track) {
|
|
498
|
379
|
const mediaType = track.getType();
|
|
499
|
|
- const transceiver = this._findTransceiver(mediaType, track);
|
|
|
380
|
+ const transceiver = this.findTransceiver(mediaType, track);
|
|
500
|
381
|
const parameters = transceiver?.sender?.getParameters();
|
|
501
|
382
|
|
|
502
|
383
|
// Resolve if the encodings are not available yet. This happens immediately after the track is added to the
|