|
@@ -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 = [];
|