Selaa lähdekoodia

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.
dev1
Jaya Allamsetty 3 vuotta sitten
vanhempi
commit
55131be9e6
No account linked to committer's email address

+ 64
- 58
JitsiConference.js Näytä tiedosto

778
         videoType = BridgeVideoType.DESKTOP_HIGH_FPS;
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
         this.rtc.setVideoType(videoType);
784
         this.rtc.setVideoType(videoType);
788
     }
785
     }
789
 };
786
 };
1252
  * @returns {Promise} resolves when the replacement is finished
1249
  * @returns {Promise} resolves when the replacement is finished
1253
  */
1250
  */
1254
 JitsiConference.prototype.replaceTrack = function(oldTrack, newTrack) {
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
     const oldTrackBelongsToConference = this === oldTrack?.conference;
1259
     const oldTrackBelongsToConference = this === oldTrack?.conference;
1256
 
1260
 
1257
     if (oldTrackBelongsToConference && oldTrack.disposed) {
1261
     if (oldTrackBelongsToConference && oldTrack.disposed) {
1395
  * @private
1399
  * @private
1396
  */
1400
  */
1397
 JitsiConference.prototype._setNewVideoType = function(track) {
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
  * @private
1434
  * @private
1430
  */
1435
  */
1431
 JitsiConference.prototype._setTrackMuteStatus = function(mediaType, localTrack, isMuted) {
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
         logger.debug('Add local MediaStream as unmute - no P2P Jingle session started yet');
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
         logger.debug('Remove local MediaStream - no P2P JingleSession started yet');
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
         ctx.skip = true;
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
     let presenceChanged = false;
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
     presenceChanged && this.room.sendPresence();
3640
     presenceChanged && this.room.sendPresence();

+ 4
- 0
modules/RTC/JitsiLocalTrack.js Näytä tiedosto

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

+ 24
- 6
modules/xmpp/SignalingLayerImpl.js Näytä tiedosto

72
      */
72
      */
73
     _addLocalSourceInfoToPresence() {
73
     _addLocalSourceInfoToPresence() {
74
         if (this.chatRoom) {
74
         if (this.chatRoom) {
75
-            this.chatRoom.addOrReplaceInPresence(
75
+            return this.chatRoom.addOrReplaceInPresence(
76
                 SOURCE_INFO_PRESENCE_ELEMENT,
76
                 SOURCE_INFO_PRESENCE_ELEMENT,
77
                 { value: JSON.stringify(this._localSourceState) });
77
                 { value: JSON.stringify(this._localSourceState) });
78
         }
78
         }
79
+
80
+        return false;
79
     }
81
     }
80
 
82
 
81
     /**
83
     /**
195
                 emitVideoTypeEvent(from, node.value);
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
         this._sourceInfoHandler = (node, mucNick) => {
205
         this._sourceInfoHandler = (node, mucNick) => {
201
             const endpointId = mucNick;
206
             const endpointId = mucNick;
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
                 if (oldSourceState.videoType !== newVideoType) {
233
                 if (oldSourceState.videoType !== newVideoType) {
226
                     oldSourceState.videoType = newVideoType;
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
             // FIXME This only adjusts the presence, but doesn't actually send it. Here we temporarily rely on
400
             // FIXME This only adjusts the presence, but doesn't actually send it. Here we temporarily rely on
388
             // the legacy signaling part to send the presence. Remember to add "send presence" here when the legacy
401
             // the legacy signaling part to send the presence. Remember to add "send presence" here when the legacy
389
             // signaling is removed.
402
             // signaling is removed.
390
-            this._addLocalSourceInfoToPresence();
403
+            return this._addLocalSourceInfoToPresence();
391
         }
404
         }
405
+
406
+        return false;
392
     }
407
     }
393
 
408
 
394
     /**
409
     /**
395
      * Sets track's video type.
410
      * Sets track's video type.
396
      * @param {SourceName} sourceName - the track's source name.
411
      * @param {SourceName} sourceName - the track's source name.
397
      * @param {VideoType} videoType - the new video type.
412
      * @param {VideoType} videoType - the new video type.
413
+     * @returns {boolean}
398
      */
414
      */
399
     setTrackVideoType(sourceName, videoType) {
415
     setTrackVideoType(sourceName, videoType) {
400
         if (!this._localSourceState[sourceName]) {
416
         if (!this._localSourceState[sourceName]) {
408
             // NOTE this doesn't send the actual presence, because is called from the same place where the legacy video
424
             // NOTE this doesn't send the actual presence, because is called from the same place where the legacy video
409
             // type is emitted which does the actual sending. A send presence statement needs to be added when
425
             // type is emitted which does the actual sending. A send presence statement needs to be added when
410
             // the legacy part is removed.
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 Näytä tiedosto

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

Loading…
Peruuta
Tallenna