Quellcode durchsuchen

feat(multi-stream-support) Adjust presence and videoType bridge message. (#1887)

* feat(multi-stream-support) Adjust presence and videoType message.
Adjust the sourceInfo for all the available local tracks. Do not add handlers for videoType changes on the peer since the videoType doesn't change when multiple stream support is enabled.

* fix(presence) Send the presence in old format for backwards compat.
Send the presence messages in both the old and new format when source name signaling is enabled and sending multiple streams is disabled.

* fix(JitsiConference) Send the videoType bridge msg after mute/unmute op is complete.

* ref(multi-stream-support) Throw if a track is being replaced with a track of different videoType.
This is not supported in the multi sender enabled mode.

* Address review comments.
release-8443
Jaya Allamsetty vor 3 Jahren
Ursprung
Commit
55131be9e6
Es ist kein Account mit der E-Mail-Adresse des Committers verbunden

+ 64
- 58
JitsiConference.js Datei anzeigen

@@ -778,12 +778,9 @@ JitsiConference.prototype._sendBridgeVideoTypeMessage = function(localtrack) {
778 778
         videoType = BridgeVideoType.DESKTOP_HIGH_FPS;
779 779
     }
780 780
 
781
-    if (FeatureFlags.isSourceNameSignalingEnabled()) {
782
-        this.rtc.sendSourceVideoType(
783
-            getSourceNameForJitsiTrack(this.myUserId(), MediaType.VIDEO, 0),
784
-            videoType
785
-        );
786
-    } else {
781
+    if (FeatureFlags.isSourceNameSignalingEnabled() && localtrack) {
782
+        this.rtc.sendSourceVideoType(localtrack.getSourceName(), videoType);
783
+    } else if (!FeatureFlags.isSourceNameSignalingEnabled()) {
787 784
         this.rtc.setVideoType(videoType);
788 785
     }
789 786
 };
@@ -1252,6 +1249,13 @@ JitsiConference.prototype.removeTrack = function(track) {
1252 1249
  * @returns {Promise} resolves when the replacement is finished
1253 1250
  */
1254 1251
 JitsiConference.prototype.replaceTrack = function(oldTrack, newTrack) {
1252
+    const oldVideoType = oldTrack?.getVideoType();
1253
+    const newVideoType = newTrack?.getVideoType();
1254
+
1255
+    if (FeatureFlags.isMultiStreamSupportEnabled() && oldTrack && newTrack && oldVideoType !== newVideoType) {
1256
+        throw new Error(`Replacing a track of videoType=${oldVideoType} with a track of videoType=${newVideoType} is`
1257
+            + ' not supported in this mode.');
1258
+    }
1255 1259
     const oldTrackBelongsToConference = this === oldTrack?.conference;
1256 1260
 
1257 1261
     if (oldTrackBelongsToConference && oldTrack.disposed) {
@@ -1395,29 +1399,30 @@ JitsiConference.prototype._setupNewTrack = function(newTrack) {
1395 1399
  * @private
1396 1400
  */
1397 1401
 JitsiConference.prototype._setNewVideoType = function(track) {
1398
-    if (FeatureFlags.isSourceNameSignalingEnabled() && track) {
1399
-        // FIXME once legacy signaling using 'sendCommand' is removed, signalingLayer.setTrackVideoType must be adjusted
1400
-        // to send the presence (not just modify it).
1401
-        this._signalingLayer.setTrackVideoType(track.getSourceName(), track.videoType);
1402
+    let videoTypeChanged = false;
1402 1403
 
1403
-        // TODO: Optimize to detect whether presence was changed, for now always report changed to send presence
1404
-        return true;
1404
+    if (FeatureFlags.isSourceNameSignalingEnabled() && track) {
1405
+        videoTypeChanged = this._signalingLayer.setTrackVideoType(track.getSourceName(), track.videoType);
1405 1406
     }
1406 1407
 
1407
-    const videoTypeTagName = 'videoType';
1408
+    if (!FeatureFlags.isMultiStreamSupportEnabled()) {
1409
+        const videoTypeTagName = 'videoType';
1408 1410
 
1409
-    // if track is missing we revert to default type Camera, the case where we screenshare and
1410
-    // we return to be video muted
1411
-    const trackVideoType = track ? track.videoType : VideoType.CAMERA;
1411
+        // If track is missing we revert to default type Camera, the case where we screenshare and
1412
+        // we return to be video muted.
1413
+        const trackVideoType = track ? track.videoType : VideoType.CAMERA;
1412 1414
 
1413
-    // if video type is camera and there is no videoType in presence, we skip adding it, as this is the default one
1414
-    if (trackVideoType !== VideoType.CAMERA || this.room.getFromPresence(videoTypeTagName)) {
1415
-        // we will not use this.sendCommand here to avoid sending the presence immediately, as later we may also set
1416
-        // and the mute status
1417
-        return this.room.addOrReplaceInPresence(videoTypeTagName, { value: trackVideoType });
1415
+        // If video type is camera and there is no videoType in presence, we skip adding it, as this is the default one
1416
+        if (trackVideoType !== VideoType.CAMERA || this.room.getFromPresence(videoTypeTagName)) {
1417
+            // We will not use this.sendCommand here to avoid sending the presence immediately, as later we may also
1418
+            // set the mute status.
1419
+            const legacyTypeChanged = this.room.addOrReplaceInPresence(videoTypeTagName, { value: trackVideoType });
1420
+
1421
+            videoTypeChanged = videoTypeChanged || legacyTypeChanged;
1422
+        }
1418 1423
     }
1419 1424
 
1420
-    return false;
1425
+    return videoTypeChanged;
1421 1426
 };
1422 1427
 
1423 1428
 /**
@@ -1429,21 +1434,31 @@ JitsiConference.prototype._setNewVideoType = function(track) {
1429 1434
  * @private
1430 1435
  */
1431 1436
 JitsiConference.prototype._setTrackMuteStatus = function(mediaType, localTrack, isMuted) {
1432
-    if (FeatureFlags.isSourceNameSignalingEnabled()) {
1433
-        // TODO When legacy signaling part is removed, remember to adjust signalingLayer.setTrackMuteStatus, so that
1434
-        // it triggers sending the presence (it only updates it for now, because the legacy code below sends).
1435
-        this._signalingLayer.setTrackMuteStatus(localTrack?.getSourceName(), isMuted);
1436
-    }
1437
+    let presenceChanged = false;
1437 1438
 
1438
-    if (!this.room) {
1439
-        return false;
1439
+    if (FeatureFlags.isSourceNameSignalingEnabled() && localTrack) {
1440
+        presenceChanged = this._signalingLayer.setTrackMuteStatus(localTrack.getSourceName(), isMuted);
1440 1441
     }
1441 1442
 
1442
-    if (mediaType === MediaType.AUDIO) {
1443
-        return this.room.addAudioInfoToPresence(isMuted);
1443
+    // Add the 'audioMuted' and 'videoMuted' tags when source name signaling is enabled for backward compatibility.
1444
+    // It won't be used anymore when multiple stream support is enabled.
1445
+    if (!FeatureFlags.isMultiStreamSupportEnabled()) {
1446
+        let audioMuteChanged, videoMuteChanged;
1447
+
1448
+        if (!this.room) {
1449
+            return false;
1450
+        }
1451
+
1452
+        if (mediaType === MediaType.AUDIO) {
1453
+            audioMuteChanged = this.room.addAudioInfoToPresence(isMuted);
1454
+        } else {
1455
+            videoMuteChanged = this.room.addVideoInfoToPresence(isMuted);
1456
+        }
1457
+
1458
+        presenceChanged = presenceChanged || audioMuteChanged || videoMuteChanged;
1444 1459
     }
1445 1460
 
1446
-    return this.room.addVideoInfoToPresence(isMuted);
1461
+    return presenceChanged;
1447 1462
 };
1448 1463
 
1449 1464
 /**
@@ -1470,11 +1485,7 @@ JitsiConference.prototype._addLocalTrackAsUnmute = function(track) {
1470 1485
         logger.debug('Add local MediaStream as unmute - no P2P Jingle session started yet');
1471 1486
     }
1472 1487
 
1473
-    return Promise.allSettled(addAsUnmutePromises)
1474
-        .then(() => {
1475
-            // Signal the video type to the bridge.
1476
-            track.isVideoTrack() && this._sendBridgeVideoTypeMessage(track);
1477
-        });
1488
+    return Promise.allSettled(addAsUnmutePromises);
1478 1489
 };
1479 1490
 
1480 1491
 /**
@@ -1498,11 +1509,7 @@ JitsiConference.prototype._removeLocalTrackAsMute = function(track) {
1498 1509
         logger.debug('Remove local MediaStream - no P2P JingleSession started yet');
1499 1510
     }
1500 1511
 
1501
-    return Promise.allSettled(removeAsMutePromises)
1502
-        .then(() => {
1503
-            // Signal the video type to the bridge.
1504
-            track.isVideoTrack() && this._sendBridgeVideoTypeMessage();
1505
-        });
1512
+    return Promise.allSettled(removeAsMutePromises);
1506 1513
 };
1507 1514
 
1508 1515
 /**
@@ -3608,27 +3615,26 @@ JitsiConference.prototype._updateRoomPresence = function(jingleSession, ctx) {
3608 3615
         ctx.skip = true;
3609 3616
     }
3610 3617
 
3611
-    const localAudioTracks = jingleSession.peerconnection.getLocalTracks(MediaType.AUDIO);
3612
-    const localVideoTracks = jingleSession.peerconnection.getLocalTracks(MediaType.VIDEO);
3613 3618
     let presenceChanged = false;
3619
+    let muteStatusChanged, videoTypeChanged;
3620
+    const localTracks = this.getLocalTracks();
3614 3621
 
3615
-    if (localAudioTracks && localAudioTracks.length) {
3616
-        presenceChanged = this._setTrackMuteStatus(MediaType.AUDIO, localAudioTracks[0], localAudioTracks[0].isMuted());
3617
-    } else if (this._setTrackMuteStatus(MediaType.AUDIO, undefined, true)) {
3618
-        presenceChanged = true;
3622
+    // Set presence for all the available local tracks.
3623
+    for (const track of localTracks) {
3624
+        muteStatusChanged = this._setTrackMuteStatus(track.getType(), track, track.isMuted());
3625
+        if (track.getType() === MediaType.VIDEO) {
3626
+            videoTypeChanged = this._setNewVideoType(track);
3627
+        }
3628
+        presenceChanged = presenceChanged || muteStatusChanged || videoTypeChanged;
3619 3629
     }
3620 3630
 
3621
-    if (localVideoTracks && localVideoTracks.length) {
3622
-        const muteStatusChanged = this._setTrackMuteStatus(
3623
-            MediaType.VIDEO, localVideoTracks[0], localVideoTracks[0].isMuted());
3624
-        const videoTypeChanged = this._setNewVideoType(localVideoTracks[0]);
3631
+    // Set the presence in the legacy format if there are no local tracks and multi stream support is not enabled.
3632
+    if (!localTracks.length && !FeatureFlags.isMultiStreamSupportEnabled()) {
3633
+        const audioMuteStatusChanged = this._setTrackMuteStatus(MediaType.AUDIO, undefined, true);
3634
+        const videoMuteStatusChanged = this._setTrackMuteStatus(MediaType.VIDEO, undefined, true);
3625 3635
 
3626
-        presenceChanged = presenceChanged || muteStatusChanged || videoTypeChanged;
3627
-    } else {
3628
-        const muteStatusChanged = this._setTrackMuteStatus(MediaType.VIDEO, undefined, true);
3629
-        const videoTypeChanged = this._setNewVideoType(); // set back to default video type
3630
-
3631
-        presenceChanged = presenceChanged || muteStatusChanged || videoTypeChanged;
3636
+        videoTypeChanged = this._setNewVideoType();
3637
+        presenceChanged = audioMuteStatusChanged || videoMuteStatusChanged || videoTypeChanged;
3632 3638
     }
3633 3639
 
3634 3640
     presenceChanged && this.room.sendPresence();

+ 4
- 0
modules/RTC/JitsiLocalTrack.js Datei anzeigen

@@ -395,6 +395,7 @@ export default class JitsiLocalTrack extends JitsiTrack {
395 395
                         this._unregisterHandlers();
396 396
                         this.stopStream();
397 397
                         this._setStream(null);
398
+
398 399
                         resolve();
399 400
                     },
400 401
                     reject);
@@ -451,6 +452,9 @@ export default class JitsiLocalTrack extends JitsiTrack {
451 452
         return promise
452 453
             .then(() => {
453 454
                 this._sendMuteStatus(muted);
455
+
456
+                // Send the videoType message to the bridge.
457
+                this.isVideoTrack() && this.conference && this.conference._sendBridgeVideoTypeMessage(this);
454 458
                 this.emit(TRACK_MUTE_CHANGED, this);
455 459
             });
456 460
     }

+ 24
- 6
modules/xmpp/SignalingLayerImpl.js Datei anzeigen

@@ -72,10 +72,12 @@ export default class SignalingLayerImpl extends SignalingLayer {
72 72
      */
73 73
     _addLocalSourceInfoToPresence() {
74 74
         if (this.chatRoom) {
75
-            this.chatRoom.addOrReplaceInPresence(
75
+            return this.chatRoom.addOrReplaceInPresence(
76 76
                 SOURCE_INFO_PRESENCE_ELEMENT,
77 77
                 { value: JSON.stringify(this._localSourceState) });
78 78
         }
79
+
80
+        return false;
79 81
     }
80 82
 
81 83
     /**
@@ -195,7 +197,10 @@ export default class SignalingLayerImpl extends SignalingLayer {
195 197
                 emitVideoTypeEvent(from, node.value);
196 198
             }
197 199
         };
198
-        room.addPresenceListener('videoType', this._videoTypeHandler);
200
+
201
+        if (!FeatureFlags.isMultiStreamSupportEnabled()) {
202
+            room.addPresenceListener('videoType', this._videoTypeHandler);
203
+        }
199 204
 
200 205
         this._sourceInfoHandler = (node, mucNick) => {
201 206
             const endpointId = mucNick;
@@ -220,11 +225,19 @@ export default class SignalingLayerImpl extends SignalingLayer {
220 225
                     }
221 226
                 }
222 227
 
223
-                const newVideoType = sourceInfoJSON[sourceName].videoType;
228
+                // Assume a default videoType of 'camera' for video sources.
229
+                const newVideoType = mediaType === MediaType.VIDEO
230
+                    ? sourceInfoJSON[sourceName].videoType ?? VideoType.CAMERA
231
+                    : undefined;
224 232
 
225 233
                 if (oldSourceState.videoType !== newVideoType) {
226 234
                     oldSourceState.videoType = newVideoType;
227
-                    emitEventsFromHere && emitVideoTypeEvent(endpointId, newVideoType);
235
+
236
+                    // videoType is not allowed to change on a given JitsiLocalTrack when multi stream support is
237
+                    // enabled.
238
+                    emitEventsFromHere
239
+                        && !FeatureFlags.isMultiStreamSupportEnabled()
240
+                        && emitVideoTypeEvent(endpointId, newVideoType);
228 241
                 }
229 242
             }
230 243
 
@@ -387,14 +400,17 @@ export default class SignalingLayerImpl extends SignalingLayer {
387 400
             // FIXME This only adjusts the presence, but doesn't actually send it. Here we temporarily rely on
388 401
             // the legacy signaling part to send the presence. Remember to add "send presence" here when the legacy
389 402
             // signaling is removed.
390
-            this._addLocalSourceInfoToPresence();
403
+            return this._addLocalSourceInfoToPresence();
391 404
         }
405
+
406
+        return false;
392 407
     }
393 408
 
394 409
     /**
395 410
      * Sets track's video type.
396 411
      * @param {SourceName} sourceName - the track's source name.
397 412
      * @param {VideoType} videoType - the new video type.
413
+     * @returns {boolean}
398 414
      */
399 415
     setTrackVideoType(sourceName, videoType) {
400 416
         if (!this._localSourceState[sourceName]) {
@@ -408,8 +424,10 @@ export default class SignalingLayerImpl extends SignalingLayer {
408 424
             // NOTE this doesn't send the actual presence, because is called from the same place where the legacy video
409 425
             // type is emitted which does the actual sending. A send presence statement needs to be added when
410 426
             // the legacy part is removed.
411
-            this._addLocalSourceInfoToPresence();
427
+            return this._addLocalSourceInfoToPresence();
412 428
         }
429
+
430
+        return false;
413 431
     }
414 432
 
415 433
     /**

+ 2
- 1
types/auto/modules/xmpp/SignalingLayerImpl.d.ts Datei anzeigen

@@ -100,11 +100,12 @@ export default class SignalingLayerImpl extends SignalingLayer {
100 100
      * Sets track's video type.
101 101
      * @param {SourceName} sourceName - the track's source name.
102 102
      * @param {VideoType} videoType - the new video type.
103
+     * @returns {boolean}
103 104
      */
104 105
     setTrackVideoType(sourceName: any, videoType: {
105 106
         CAMERA: string;
106 107
         DESKTOP: string;
107
-    }): void;
108
+    }): boolean;
108 109
     /**
109 110
      * Saves the source name for a track identified by it's ssrc.
110 111
      * @param {number} ssrc the ssrc of the target track.

Laden…
Abbrechen
Speichern