Przeglądaj źródła

fix(SS): On FF (#727)

master
hristoterezov 7 lat temu
rodzic
commit
6be1ff9cf5
2 zmienionych plików z 109 dodań i 52 usunięć
  1. 89
    30
      modules/RTC/TraceablePeerConnection.js
  2. 20
    22
      modules/xmpp/JingleSessionPC.js

+ 89
- 30
modules/RTC/TraceablePeerConnection.js Wyświetl plik

@@ -1463,6 +1463,93 @@ TraceablePeerConnection.prototype.removeTrack = function(localTrack) {
1463 1463
     }
1464 1464
 };
1465 1465
 
1466
+/**
1467
+ * Returns the sender corresponding to the given MediaStream.
1468
+ *
1469
+ * @param {MediaStream} stream - The media stream used for the search.
1470
+ * @returns {RTPSender|undefined} - The found sender or undefined if no sender
1471
+ * was found.
1472
+ */
1473
+TraceablePeerConnection.prototype.findSenderByStream = function(stream) {
1474
+    const track = stream.getTracks()[0];
1475
+
1476
+    if (!track) {
1477
+        logger.error('Cannot find sender: no tracks.');
1478
+
1479
+        return;
1480
+    }
1481
+
1482
+    // Find the right sender (for audio or video)
1483
+    return this.peerconnection.getSenders().find(s => s.track === track);
1484
+};
1485
+
1486
+/**
1487
+ * Replaces <tt>oldTrack</tt> with <tt>newTrack</tt> from the peer connection.
1488
+ * Either <tt>oldTrack</tt> or <tt>newTrack</tt> can be null; replacing a valid
1489
+ * <tt>oldTrack</tt> with a null <tt>newTrack</tt> effectively just removes
1490
+ * <tt>oldTrack</tt>
1491
+ *
1492
+ * @param {JitsiLocalTrack|null} oldTrack - The current track in use to be
1493
+ * replaced
1494
+ * @param {JitsiLocalTrack|null} newTrack - The new track to use
1495
+ * @returns {Promise<boolean>} - If the promise resolves with true,
1496
+ * renegotiation will be needed. Otherwise no renegotiation is needed.
1497
+ */
1498
+TraceablePeerConnection.prototype.replaceTrack = function(oldTrack, newTrack) {
1499
+    if (browser.isFirefox() && oldTrack && newTrack) {
1500
+        // Add and than remove stream in FF leads to wrong local SDP. In order
1501
+        // to workaround the issue we need to use sender.replaceTrack().
1502
+        const sender = this.findSenderByStream(oldTrack.getOriginalStream());
1503
+        const stream = newTrack.getOriginalStream();
1504
+
1505
+        if (sender && stream) {
1506
+            const track = stream.getTracks()[0];
1507
+
1508
+            if (track) {
1509
+                return sender.replaceTrack(track, stream).then(() => {
1510
+                    // Since there is no need to do renegotiations we need to
1511
+                    // fix all ssrc-msid mappings here.
1512
+                    // NOTE: after sender.replaceTrack the sdp will remain the
1513
+                    // same but the stream attach to the new JitsiLocalTrack
1514
+                    // will have different msid. Luckily on FF we are not doing
1515
+                    // all the transformations related to video mute.
1516
+
1517
+                    const ssrc = this.localSSRCs.get(oldTrack.rtcId);
1518
+
1519
+                    this.localTracks.delete(oldTrack.rtcId);
1520
+                    this.localSSRCs.delete(oldTrack.rtcId);
1521
+                    this._addedStreams
1522
+                        = this._addedStreams.filter(s => s !== stream);
1523
+
1524
+                    this.localTracks.set(newTrack.rtcId, newTrack);
1525
+
1526
+                    // Override the msid of JitsiLocalTrack in order to be
1527
+                    // consistent with the SDP values.
1528
+                    newTrack.storedMSID = oldTrack.storedMSID;
1529
+                    this._addedStreams.push(stream);
1530
+
1531
+                    this.localSSRCs.set(newTrack.rtcId, ssrc);
1532
+                    this.eventEmitter.emit(
1533
+                        RTCEvents.LOCAL_TRACK_SSRC_UPDATED,
1534
+                        newTrack,
1535
+                        extractPrimarySSRC(ssrc));
1536
+
1537
+                    return false;
1538
+                });
1539
+            }
1540
+        }
1541
+    }
1542
+
1543
+    if (oldTrack) {
1544
+        this.removeTrack(oldTrack);
1545
+    }
1546
+    if (newTrack) {
1547
+        this.addTrack(newTrack);
1548
+    }
1549
+
1550
+    return Promise.resolve(true);
1551
+};
1552
+
1466 1553
 /**
1467 1554
  * Removes local track as part of the mute operation.
1468 1555
  * @param {JitsiLocalTrack} localTrack the local track to be remove as part of
@@ -1505,36 +1592,8 @@ TraceablePeerConnection.prototype._handleFirefoxRemoveStream = function(
1505 1592
         // There is nothing to be changed
1506 1593
         return;
1507 1594
     }
1508
-    let sender = null;
1509
-
1510
-    // On Firefox we don't replace MediaStreams as this messes up the
1511
-    // m-lines (which can't be removed in Plan Unified) and brings a lot
1512
-    // of complications. Instead, we use the RTPSender and remove just
1513
-    // the track.
1514
-    let track = null;
1515
-
1516
-    if (stream.getAudioTracks() && stream.getAudioTracks().length) {
1517
-        track = stream.getAudioTracks()[0];
1518
-    } else if (stream.getVideoTracks() && stream.getVideoTracks().length) {
1519
-        track = stream.getVideoTracks()[0];
1520
-    }
1521
-
1522
-    if (!track) {
1523
-        logger.error('Cannot remove tracks: no tracks.');
1524 1595
 
1525
-        return;
1526
-    }
1527
-
1528
-    // Find the right sender (for audio or video)
1529
-    this.peerconnection.getSenders().some(s => {
1530
-        if (s.track === track) {
1531
-            sender = s;
1532
-
1533
-            return true;
1534
-        }
1535
-
1536
-        return false;
1537
-    });
1596
+    const sender = this.findSenderByStream(stream);
1538 1597
 
1539 1598
     if (sender) {
1540 1599
         this.peerconnection.removeTrack(sender);
@@ -2262,7 +2321,7 @@ function extractPrimarySSRC(ssrcObj) {
2262 2321
  */
2263 2322
 TraceablePeerConnection.prototype._processLocalSSRCsMap = function(ssrcMap) {
2264 2323
     for (const track of this.localTracks.values()) {
2265
-        const trackMSID = track.getMSID();
2324
+        const trackMSID = track.storedMSID;
2266 2325
 
2267 2326
         if (ssrcMap.has(trackMSID)) {
2268 2327
             const newSSRC = ssrcMap.get(trackMSID);

+ 20
- 22
modules/xmpp/JingleSessionPC.js Wyświetl plik

@@ -1654,29 +1654,27 @@ export default class JingleSessionPC extends JingleSession {
1654 1654
                 this.peerconnection.clearRecvonlySsrc();
1655 1655
                 this.peerconnection.generateRecvonlySsrc();
1656 1656
             }
1657
-            if (oldTrack) {
1658
-                this.peerconnection.removeTrack(oldTrack);
1659
-            }
1660
-            if (newTrack) {
1661
-                this.peerconnection.addTrack(newTrack);
1662
-            }
1663 1657
 
1664
-            if ((oldTrack || newTrack)
1665
-                && this.state === JingleSessionState.ACTIVE) {
1666
-                this._renegotiate()
1667
-                    .then(() => {
1668
-                        const newLocalSDP
1669
-                            = new SDP(
1670
-                                this.peerconnection.localDescription.sdp);
1671
-
1672
-                        this.notifyMySSRCUpdate(
1673
-                            new SDP(oldLocalSdp), newLocalSDP);
1674
-                        finishedCallback();
1675
-                    },
1676
-                    finishedCallback /* will be called with en error */);
1677
-            } else {
1678
-                finishedCallback();
1679
-            }
1658
+            this.peerconnection.replaceTrack(oldTrack, newTrack)
1659
+            .then(shouldRenegotiate => {
1660
+                if (shouldRenegotiate
1661
+                    && (oldTrack || newTrack)
1662
+                    && this.state === JingleSessionState.ACTIVE) {
1663
+                    this._renegotiate()
1664
+                        .then(() => {
1665
+                            const newLocalSDP
1666
+                                = new SDP(
1667
+                                    this.peerconnection.localDescription.sdp);
1668
+
1669
+                            this.notifyMySSRCUpdate(
1670
+                                new SDP(oldLocalSdp), newLocalSDP);
1671
+                            finishedCallback();
1672
+                        },
1673
+                        finishedCallback /* will be called with en error */);
1674
+                } else {
1675
+                    finishedCallback();
1676
+                }
1677
+            });
1680 1678
         };
1681 1679
 
1682 1680
         this.modificationQueue.push(

Ładowanie…
Anuluj
Zapisz