浏览代码

fix(ssrc-rewriting): Fire track removed/added instead of owner changed.

When an existing SSRC for a remote track gets re-mapped from one source to another, fire a TRACK_REMOVED event followed by TRACK_ADDED event instead of TRACK_OWNER_CHANGED event. This should simplify the application logic for track handling.
release-8443
Jaya Allamsetty 1年前
父节点
当前提交
3b11dce3aa

+ 4
- 6
JitsiConference.js 查看文件

@@ -1881,12 +1881,12 @@ JitsiConference.prototype.onMemberLeft = function(jid, reason) {
1881 1881
     }
1882 1882
 
1883 1883
     tracksToBeRemoved.forEach(track => {
1884
+        // Fire the event before renegotiation is done so that the thumbnails can be removed immediately.
1885
+        this.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);
1886
+
1884 1887
         if (FeatureFlags.isSsrcRewritingSupported()) {
1885 1888
             track.setSourceName(null);
1886 1889
             track.setOwner(null);
1887
-        } else {
1888
-            // Fire the event before renegotiation is done so that the thumbnails can be removed immediately.
1889
-            this.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);
1890 1890
         }
1891 1891
     });
1892 1892
 
@@ -2945,9 +2945,7 @@ JitsiConference.prototype._addRemoteP2PTracks = function() {
2945 2945
  */
2946 2946
 JitsiConference.prototype._addRemoteTracks = function(logName, remoteTracks) {
2947 2947
     for (const track of remoteTracks) {
2948
-        // There will be orphan (with no owner) tracks when ssrc-rewriting is enabled and all of them need to be addded
2949
-        // back to the conference.
2950
-        if (FeatureFlags.isSsrcRewritingSupported() || this.participants.has(track.ownerEndpointId)) {
2948
+        if (this.participants.has(track.ownerEndpointId)) {
2951 2949
             logger.info(`Adding remote ${logName} track: ${track}`);
2952 2950
             this.onRemoteTrackAdded(track);
2953 2951
         }

+ 4
- 1
JitsiConferenceEventManager.js 查看文件

@@ -173,7 +173,10 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
173 173
         }
174 174
     });
175 175
 
176
-    chatRoom.addListener(JitsiTrackEvents.TRACK_REMOVED, track => {
176
+    chatRoom.addListener(JitsiTrackEvents.TRACK_OWNER_ADDED, track => {
177
+        conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, track);
178
+    });
179
+    chatRoom.addListener(JitsiTrackEvents.TRACK_OWNER_REMOVED, track => {
177 180
         conference.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);
178 181
     });
179 182
 

+ 6
- 6
JitsiTrackEvents.spec.ts 查看文件

@@ -8,12 +8,12 @@ describe( "/JitsiTrackEvents members", () => {
8 8
         TRACK_AUDIO_LEVEL_CHANGED,
9 9
         TRACK_AUDIO_OUTPUT_CHANGED,
10 10
         TRACK_MUTE_CHANGED,
11
+        TRACK_OWNER_ADDED,
12
+        TRACK_OWNER_REMOVED,
11 13
         TRACK_STREAMING_STATUS_CHANGED,
12 14
         TRACK_VIDEOTYPE_CHANGED,
13 15
         NO_DATA_FROM_SOURCE,
14 16
         NO_AUDIO_INPUT,
15
-        TRACK_OWNER_CHANGED,
16
-        TRACK_REMOVED,
17 17
         JitsiTrackEvents,
18 18
         ...others
19 19
     } = exported;
@@ -23,12 +23,12 @@ describe( "/JitsiTrackEvents members", () => {
23 23
         expect( TRACK_AUDIO_LEVEL_CHANGED ).toBe( 'track.audioLevelsChanged' );
24 24
         expect( TRACK_AUDIO_OUTPUT_CHANGED ).toBe( 'track.audioOutputChanged' );
25 25
         expect( TRACK_MUTE_CHANGED ).toBe( 'track.trackMuteChanged' );
26
+        expect( TRACK_OWNER_ADDED ).toBe( 'track.owner_added' );
27
+        expect( TRACK_OWNER_REMOVED ).toBe( 'track.owner_removed' );
26 28
         expect( TRACK_STREAMING_STATUS_CHANGED ).toBe( 'track.streaming_status_changed' );
27 29
         expect( TRACK_VIDEOTYPE_CHANGED ).toBe( 'track.videoTypeChanged' );
28 30
         expect( NO_DATA_FROM_SOURCE ).toBe( 'track.no_data_from_source' );
29 31
         expect( NO_AUDIO_INPUT ).toBe( 'track.no_audio_input' );
30
-        expect( TRACK_OWNER_CHANGED ).toBe( 'track.owner_changed' );
31
-        expect( TRACK_REMOVED ).toBe( 'track.removed' );
32 32
 
33 33
         expect( JitsiTrackEvents ).toBeDefined();
34 34
 
@@ -36,12 +36,12 @@ describe( "/JitsiTrackEvents members", () => {
36 36
         expect( JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED ).toBe( 'track.audioLevelsChanged' );
37 37
         expect( JitsiTrackEvents.TRACK_AUDIO_OUTPUT_CHANGED ).toBe( 'track.audioOutputChanged' );
38 38
         expect( JitsiTrackEvents.TRACK_MUTE_CHANGED ).toBe( 'track.trackMuteChanged' );
39
+        expect( JitsiTrackEvents.TRACK_OWNER_ADDED ).toBe( 'track.owner_added' );
40
+        expect( JitsiTrackEvents.TRACK_OWNER_REMOVED ).toBe( 'track.owner_removed' );
39 41
         expect( JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED ).toBe( 'track.streaming_status_changed' );
40 42
         expect( JitsiTrackEvents.TRACK_VIDEOTYPE_CHANGED ).toBe( 'track.videoTypeChanged' );
41 43
         expect( JitsiTrackEvents.NO_DATA_FROM_SOURCE ).toBe( 'track.no_data_from_source' );
42 44
         expect( JitsiTrackEvents.NO_AUDIO_INPUT ).toBe( 'track.no_audio_input' );
43
-        expect( JitsiTrackEvents.TRACK_OWNER_CHANGED ).toBe( 'track.owner_changed' );
44
-        expect( JitsiTrackEvents.TRACK_REMOVED ).toBe( 'track.removed' );
45 45
     } );
46 46
 
47 47
     it( "unknown members", () => {

+ 12
- 13
JitsiTrackEvents.ts 查看文件

@@ -45,6 +45,16 @@ export enum JitsiTrackEvents {
45 45
      */
46 46
     NO_AUDIO_INPUT = 'track.no_audio_input',
47 47
 
48
+    /**
49
+     * Indicates that a new owner has been assigned to a remote track when SSRC rewriting is enabled.
50
+     */
51
+    TRACK_OWNER_ADDED = 'track.owner_added',
52
+
53
+    /**
54
+     * Indicates that an owner has been removed from a remote track when SSRC rewriting is enabled.
55
+     */
56
+    TRACK_OWNER_REMOVED = 'track.owner_removed',
57
+
48 58
     /**
49 59
      * Event fired whenever video track's streaming changes.
50 60
      * First argument is the sourceName of the track and the second is a string indicating if the connection is currently
@@ -57,17 +67,6 @@ export enum JitsiTrackEvents {
57 67
      * The current status value can be obtained by calling JitsiRemoteTrack.getTrackStreamingStatus().
58 68
      */
59 69
     TRACK_STREAMING_STATUS_CHANGED = 'track.streaming_status_changed',
60
-
61
-    /**
62
-     * An SSRC has been remapped. The track is now associated with a new participant.
63
-     */
64
-    TRACK_OWNER_CHANGED = 'track.owner_changed',
65
-
66
-    /**
67
-     * A track is being removed. Fired when a session terminates for tracks
68
-     * that persist in ssrc-rewriting mode.
69
-     */
70
-    TRACK_REMOVED = 'track.removed',
71 70
 };
72 71
 
73 72
 // exported for backward compatibility
@@ -78,6 +77,6 @@ export const TRACK_MUTE_CHANGED = JitsiTrackEvents.TRACK_MUTE_CHANGED;
78 77
 export const TRACK_VIDEOTYPE_CHANGED = JitsiTrackEvents.TRACK_VIDEOTYPE_CHANGED;
79 78
 export const NO_DATA_FROM_SOURCE = JitsiTrackEvents.NO_DATA_FROM_SOURCE;
80 79
 export const NO_AUDIO_INPUT = JitsiTrackEvents.NO_AUDIO_INPUT;
80
+export const TRACK_OWNER_ADDED = JitsiTrackEvents.TRACK_OWNER_ADDED;
81
+export const TRACK_OWNER_REMOVED = JitsiTrackEvents.TRACK_OWNER_REMOVED;
81 82
 export const TRACK_STREAMING_STATUS_CHANGED = JitsiTrackEvents.TRACK_STREAMING_STATUS_CHANGED;
82
-export const TRACK_OWNER_CHANGED = JitsiTrackEvents.TRACK_OWNER_CHANGED;
83
-export const TRACK_REMOVED = JitsiTrackEvents.TRACK_REMOVED;

+ 0
- 1
modules/RTC/JitsiRemoteTrack.js 查看文件

@@ -280,7 +280,6 @@ export default class JitsiRemoteTrack extends JitsiTrack {
280 280
      */
281 281
     setOwner(owner) {
282 282
         this.ownerEndpointId = owner;
283
-        this.emit(JitsiTrackEvents.TRACK_OWNER_CHANGED, owner);
284 283
     }
285 284
 
286 285
     /**

+ 79
- 26
modules/RTC/TraceablePeerConnection.js 查看文件

@@ -138,6 +138,12 @@ export default function TraceablePeerConnection(
138 138
      */
139 139
     this.isP2P = isP2P;
140 140
 
141
+    /**
142
+     * A map that holds remote tracks signaled on the peerconnection indexed by their SSRC.
143
+     * @type {Map<number, JitsiRemoteTrack>}
144
+     */
145
+    this.remoteTracksBySsrc = new Map();
146
+
141 147
     /**
142 148
      * The map holds remote tracks associated with this peer connection. It maps user's JID to media type and a set of
143 149
      * remote tracks.
@@ -712,6 +718,21 @@ TraceablePeerConnection.prototype.hasAnyTracksOfType = function(mediaType) {
712 718
  */
713 719
 TraceablePeerConnection.prototype.getRemoteTracks = function(endpointId, mediaType) {
714 720
     let remoteTracks = [];
721
+
722
+    if (FeatureFlags.isSsrcRewritingSupported()) {
723
+        for (const remoteTrack of this.remoteTracksBySsrc.values()) {
724
+            const owner = remoteTrack.getParticipantId();
725
+
726
+            if (owner && (!endpointId || owner === endpointId)) {
727
+                if (!mediaType || remoteTrack.getType() === mediaType) {
728
+                    remoteTracks.push(remoteTrack);
729
+                }
730
+            }
731
+        }
732
+
733
+        return remoteTracks;
734
+    }
735
+
715 736
     const endpoints = endpointId ? [ endpointId ] : this.remoteTracks.keys();
716 737
 
717 738
     for (const endpoint of endpoints) {
@@ -792,6 +813,10 @@ TraceablePeerConnection.prototype.getTargetVideoBitrates = function() {
792 813
  * @return {JitsiTrack|null}
793 814
  */
794 815
 TraceablePeerConnection.prototype.getTrackBySSRC = function(ssrc) {
816
+    if (FeatureFlags.isSsrcRewritingSupported()) {
817
+        return this.remoteTracksBySsrc.get(ssrc);
818
+    }
819
+
795 820
     if (typeof ssrc !== 'number') {
796 821
         throw new Error(`SSRC ${ssrc} is not a number`);
797 822
     }
@@ -959,23 +984,37 @@ TraceablePeerConnection.prototype._createRemoteTrack = function(
959 984
         sourceName) {
960 985
     logger.info(`${this} creating remote track[endpoint=${ownerEndpointId},ssrc=${ssrc},`
961 986
         + `type=${mediaType},sourceName=${sourceName}]`);
962
-    let remoteTracksMap = this.remoteTracks.get(ownerEndpointId);
987
+    let remoteTracksMap;
988
+    let userTracksByMediaType;
963 989
 
964
-    if (!remoteTracksMap) {
965
-        remoteTracksMap = new Map();
966
-        remoteTracksMap.set(MediaType.AUDIO, new Set());
967
-        remoteTracksMap.set(MediaType.VIDEO, new Set());
968
-        this.remoteTracks.set(ownerEndpointId, remoteTracksMap);
969
-    }
990
+    if (FeatureFlags.isSsrcRewritingSupported()) {
991
+        const existingTrack = this.remoteTracksBySsrc.get(ssrc);
970 992
 
971
-    const userTracksByMediaType = remoteTracksMap.get(mediaType);
993
+        if (existingTrack) {
994
+            logger.info(`${this} ignored duplicated track event for SSRC[ssrc=${ssrc},type=${mediaType}]`);
972 995
 
973
-    if (userTracksByMediaType?.size
974
-        && Array.from(userTracksByMediaType).find(jitsiTrack => jitsiTrack.getTrack() === track)) {
975
-        // Ignore duplicated event which can originate either from 'onStreamAdded' or 'onTrackAdded'.
976
-        logger.info(`${this} ignored duplicated track event for track[endpoint=${ownerEndpointId},type=${mediaType}]`);
996
+            return;
997
+        }
998
+    } else {
999
+        remoteTracksMap = this.remoteTracks.get(ownerEndpointId);
977 1000
 
978
-        return;
1001
+        if (!remoteTracksMap) {
1002
+            remoteTracksMap = new Map();
1003
+            remoteTracksMap.set(MediaType.AUDIO, new Set());
1004
+            remoteTracksMap.set(MediaType.VIDEO, new Set());
1005
+            this.remoteTracks.set(ownerEndpointId, remoteTracksMap);
1006
+        }
1007
+
1008
+        userTracksByMediaType = remoteTracksMap.get(mediaType);
1009
+
1010
+        if (userTracksByMediaType?.size
1011
+            && Array.from(userTracksByMediaType).find(jitsiTrack => jitsiTrack.getTrack() === track)) {
1012
+            // Ignore duplicated event which can originate either from 'onStreamAdded' or 'onTrackAdded'.
1013
+            logger.info(`${this} ignored duplicated track event for track[endpoint=${ownerEndpointId},`
1014
+                + `type=${mediaType}]`);
1015
+
1016
+            return;
1017
+        }
979 1018
     }
980 1019
 
981 1020
     const remoteTrack
@@ -992,7 +1031,12 @@ TraceablePeerConnection.prototype._createRemoteTrack = function(
992 1031
                 this.isP2P,
993 1032
                 sourceName);
994 1033
 
995
-    userTracksByMediaType.add(remoteTrack);
1034
+    if (FeatureFlags.isSsrcRewritingSupported()) {
1035
+        this.remoteTracksBySsrc.set(ssrc, remoteTrack);
1036
+    } else {
1037
+        userTracksByMediaType.add(remoteTrack);
1038
+    }
1039
+
996 1040
     this.eventEmitter.emit(RTCEvents.REMOTE_TRACK_ADDED, remoteTrack, this);
997 1041
 };
998 1042
 
@@ -1069,16 +1113,18 @@ TraceablePeerConnection.prototype._removeRemoteTrack = function(toBeRemoved) {
1069 1113
     toBeRemoved.dispose();
1070 1114
     const participantId = toBeRemoved.getParticipantId();
1071 1115
 
1072
-    if (!participantId && FeatureFlags.isSsrcRewritingSupported()) {
1116
+    if (FeatureFlags.isSsrcRewritingSupported() && !participantId) {
1073 1117
         return;
1074
-    }
1075
-    const userTracksByMediaType = this.remoteTracks.get(participantId);
1118
+    } else if (!FeatureFlags.isSsrcRewritingSupported()) {
1119
+        const userTracksByMediaType = this.remoteTracks.get(participantId);
1076 1120
 
1077
-    if (!userTracksByMediaType) {
1078
-        logger.error(`${this} removeRemoteTrack: no remote tracks map for endpoint=${participantId}`);
1079
-    } else if (!userTracksByMediaType.get(toBeRemoved.getType())?.delete(toBeRemoved)) {
1080
-        logger.error(`${this} Failed to remove ${toBeRemoved} - type mapping messed up ?`);
1121
+        if (!userTracksByMediaType) {
1122
+            logger.error(`${this} removeRemoteTrack: no remote tracks map for endpoint=${participantId}`);
1123
+        } else if (!userTracksByMediaType.get(toBeRemoved.getType())?.delete(toBeRemoved)) {
1124
+            logger.error(`${this} Failed to remove ${toBeRemoved} - type mapping messed up ?`);
1125
+        }
1081 1126
     }
1127
+
1082 1128
     this.eventEmitter.emit(RTCEvents.REMOTE_TRACK_REMOVED, toBeRemoved);
1083 1129
 };
1084 1130
 
@@ -2440,14 +2486,21 @@ TraceablePeerConnection.prototype.close = function() {
2440 2486
     this.signalingLayer.off(SignalingEvents.PEER_VIDEO_TYPE_CHANGED, this._peerVideoTypeChanged);
2441 2487
     this.peerconnection.removeEventListener('track', this.onTrack);
2442 2488
 
2443
-    for (const peerTracks of this.remoteTracks.values()) {
2444
-        for (const remoteTracks of peerTracks.values()) {
2445
-            for (const remoteTrack of remoteTracks) {
2446
-                this._removeRemoteTrack(remoteTrack);
2489
+    if (FeatureFlags.isSsrcRewritingSupported()) {
2490
+        for (const remoteTrack of this.remoteTracksBySsrc.values()) {
2491
+            this._removeRemoteTrack(remoteTrack);
2492
+        }
2493
+        this.remoteTracksBySsrc.clear();
2494
+    } else {
2495
+        for (const peerTracks of this.remoteTracks.values()) {
2496
+            for (const remoteTracks of peerTracks.values()) {
2497
+                for (const remoteTrack of remoteTracks) {
2498
+                    this._removeRemoteTrack(remoteTrack);
2499
+                }
2447 2500
             }
2448 2501
         }
2502
+        this.remoteTracks.clear();
2449 2503
     }
2450
-    this.remoteTracks.clear();
2451 2504
 
2452 2505
     this._dtmfSender = null;
2453 2506
     this._dtmfTonesQueue = [];

+ 8
- 3
modules/xmpp/JingleSessionPC.js 查看文件

@@ -1777,19 +1777,24 @@ export default class JingleSessionPC extends JingleSession {
1777 1777
                     const track = this.peerconnection.getTrackBySSRC(oldSsrc);
1778 1778
 
1779 1779
                     if (track) {
1780
-                        track.setSourceName(undefined);
1781
-                        track.setOwner(undefined);
1782
-                        track._setVideoType(undefined);
1780
+                        track.setSourceName(null);
1781
+                        track.setOwner(null);
1782
+                        track._setVideoType(null);
1783
+                        this.room.eventEmitter.emit(JitsiTrackEvents.TRACK_OWNER_REMOVED, track);
1783 1784
                     }
1784 1785
                 }
1785 1786
             } else {
1786 1787
                 logger.debug(`Existing SSRC re-mapped ${ssrc}: new owner=${owner}, source-name=${source}`);
1787 1788
                 const track = this.peerconnection.getTrackBySSRC(ssrc);
1788 1789
 
1790
+                this.room.eventEmitter.emit(JitsiTrackEvents.TRACK_OWNER_REMOVED, track);
1791
+
1789 1792
                 this._signalingLayer.setSSRCOwner(ssrc, owner, source);
1790 1793
                 track.setSourceName(source);
1791 1794
                 track.setOwner(owner);
1792 1795
 
1796
+                this.room.eventEmitter.emit(JitsiTrackEvents.TRACK_OWNER_ADDED, track);
1797
+
1793 1798
                 // Update the muted state and the video type on the track since the presence for this track could have
1794 1799
                 // been received before the updated source map is received on the bridge channel.
1795 1800
                 const peerMediaInfo = this._signalingLayer.getPeerMediaInfo(owner, mediaType, source);

正在加载...
取消
保存