瀏覽代碼

fix(RTC): Adjust the media direction for p2p conn.

For p2p connections, the media direction needs to be adjusted after every source-add/source-remove is processed based on the availability of local sources.
dev1
Jaya Allamsetty 4 年之前
父節點
當前提交
d9d9b7fc31
共有 2 個文件被更改,包括 98 次插入37 次删除
  1. 68
    35
      modules/RTC/TraceablePeerConnection.js
  2. 30
    2
      modules/xmpp/JingleSessionPC.js

+ 68
- 35
modules/RTC/TraceablePeerConnection.js 查看文件

@@ -5,6 +5,7 @@ import { getLogger } from 'jitsi-meet-logger';
5 5
 import transform from 'sdp-transform';
6 6
 
7 7
 import * as CodecMimeType from '../../service/RTC/CodecMimeType';
8
+import MediaDirection from '../../service/RTC/MediaDirection';
8 9
 import * as MediaType from '../../service/RTC/MediaType';
9 10
 import RTCEvents from '../../service/RTC/RTCEvents';
10 11
 import * as SignalingEvents from '../../service/RTC/SignalingEvents';
@@ -446,25 +447,28 @@ TraceablePeerConnection.prototype.getConnectionState = function() {
446 447
  * into account whether or not there are any local tracks for media and
447 448
  * the {@link audioTransferActive} and {@link videoTransferActive} flags.
448 449
  * @param {MediaType} mediaType
450
+ * @param {boolean} isAddOperation whether the direction is to be calculated after a source-add action.
449 451
  * @return {string} one of the SDP direction constants ('sendrecv, 'recvonly'
450 452
  * etc.) which should be used when setting local description on the peer
451 453
  * connection.
452 454
  * @private
453 455
  */
454
-TraceablePeerConnection.prototype._getDesiredMediaDirection = function(
455
-        mediaType) {
456
-    let mediaTransferActive = true;
456
+TraceablePeerConnection.prototype.getDesiredMediaDirection = function(mediaType, isAddOperation = false) {
457
+    const hasLocalSource = this.hasAnyTracksOfType(mediaType);
457 458
 
458
-    if (mediaType === MediaType.AUDIO) {
459
-        mediaTransferActive = this.audioTransferActive;
460
-    } else if (mediaType === MediaType.VIDEO) {
461
-        mediaTransferActive = this.videoTransferActive;
459
+    if (this._usesUnifiedPlan) {
460
+        return isAddOperation
461
+            ? hasLocalSource ? MediaDirection.SENDRECV : MediaDirection.SENDONLY
462
+            : hasLocalSource ? MediaDirection.RECVONLY : MediaDirection.INACTIVE;
462 463
     }
464
+
465
+    const mediaTransferActive = mediaType === MediaType.AUDIO ? this.audioTransferActive : this.videoTransferActive;
466
+
463 467
     if (mediaTransferActive) {
464
-        return this.hasAnyTracksOfType(mediaType) ? 'sendrecv' : 'recvonly';
468
+        return hasLocalSource ? MediaDirection.SENDRECV : MediaDirection.RECVONLY;
465 469
     }
466 470
 
467
-    return 'inactive';
471
+    return MediaDirection.INACTIVE;
468 472
 };
469 473
 
470 474
 /**
@@ -1357,7 +1361,7 @@ function replaceDefaultUnifiedPlanMsid(ssrcLines = []) {
1357 1361
         const cnameLine = filteredLines.find(line =>
1358 1362
             line.id === ssrcId && line.attribute === 'cname');
1359 1363
 
1360
-        cnameLine.value = `recvonly-${ssrcId}`;
1364
+        cnameLine.value = `${MediaDirection.RECVONLY}-${ssrcId}`;
1361 1365
 
1362 1366
         // Remove all of lines for the ssrc.
1363 1367
         filteredLines
@@ -1382,23 +1386,23 @@ const enforceSendRecv = function(localDescription, options) {
1382 1386
     }
1383 1387
 
1384 1388
     const transformer = new SdpTransformWrap(localDescription.sdp);
1385
-    const audioMedia = transformer.selectMedia('audio');
1389
+    const audioMedia = transformer.selectMedia(MediaType.AUDIO);
1386 1390
     let changed = false;
1387 1391
 
1388
-    if (audioMedia && audioMedia.direction !== 'sendrecv') {
1392
+    if (audioMedia && audioMedia.direction !== MediaDirection.SENDRECV) {
1389 1393
         if (options.startSilent) {
1390
-            audioMedia.direction = 'inactive';
1394
+            audioMedia.direction = MediaDirection.INACTIVE;
1391 1395
         } else {
1392
-            audioMedia.direction = 'sendrecv';
1396
+            audioMedia.direction = MediaDirection.SENDRECV;
1393 1397
         }
1394 1398
 
1395 1399
         changed = true;
1396 1400
     }
1397 1401
 
1398
-    const videoMedia = transformer.selectMedia('video');
1402
+    const videoMedia = transformer.selectMedia(MediaType.VIDEO);
1399 1403
 
1400
-    if (videoMedia && videoMedia.direction !== 'sendrecv') {
1401
-        videoMedia.direction = 'sendrecv';
1404
+    if (videoMedia && videoMedia.direction !== MediaDirection.SENDRECV) {
1405
+        videoMedia.direction = MediaDirection.SENDRECV;
1402 1406
         changed = true;
1403 1407
     }
1404 1408
 
@@ -1534,12 +1538,15 @@ const getters = {
1534 1538
         }
1535 1539
         this.trace('getRemoteDescription::preTransform', dumpSDP(desc));
1536 1540
 
1537
-        // If the browser is running in unified plan mode and this is a jvb connection,
1538
-        // transform the SDP to Plan B first.
1539
-        if (this._usesUnifiedPlan && !this.isP2P) {
1540
-            desc = this.interop.toPlanB(desc);
1541
-            this.trace(
1542
-                'getRemoteDescription::postTransform (Plan B)', dumpSDP(desc));
1541
+        if (this._usesUnifiedPlan) {
1542
+            if (this.isP2P) {
1543
+                // Adjust the media direction for p2p based on whether a local source has been added.
1544
+                desc = this._adjustRemoteMediaDirection(desc);
1545
+            } else {
1546
+                // If this is a jvb connection, transform the SDP to Plan B first.
1547
+                desc = this.interop.toPlanB(desc);
1548
+                this.trace('getRemoteDescription::postTransform (Plan B)', dumpSDP(desc));
1549
+            }
1543 1550
         }
1544 1551
 
1545 1552
         return desc;
@@ -2048,19 +2055,17 @@ TraceablePeerConnection.prototype._ensureSimulcastGroupIsLast = function(
2048 2055
  * Will adjust audio and video media direction in the given SDP object to
2049 2056
  * reflect the current status of the {@link audioTransferActive} and
2050 2057
  * {@link videoTransferActive} flags.
2051
- * @param {Object} localDescription the WebRTC session description instance for
2058
+ * @param {RTCSessionDescription} localDescription the WebRTC session description instance for
2052 2059
  * the local description.
2053 2060
  * @private
2054 2061
  */
2055
-TraceablePeerConnection.prototype._adjustLocalMediaDirection = function(
2056
-        localDescription) {
2062
+TraceablePeerConnection.prototype._adjustLocalMediaDirection = function(localDescription) {
2057 2063
     const transformer = new SdpTransformWrap(localDescription.sdp);
2058 2064
     let modifiedDirection = false;
2059
-    const audioMedia = transformer.selectMedia('audio');
2065
+    const audioMedia = transformer.selectMedia(MediaType.AUDIO);
2060 2066
 
2061 2067
     if (audioMedia) {
2062
-        const desiredAudioDirection
2063
-            = this._getDesiredMediaDirection(MediaType.AUDIO);
2068
+        const desiredAudioDirection = this.getDesiredMediaDirection(MediaType.AUDIO);
2064 2069
 
2065 2070
         if (audioMedia.direction !== desiredAudioDirection) {
2066 2071
             audioMedia.direction = desiredAudioDirection;
@@ -2071,11 +2076,10 @@ TraceablePeerConnection.prototype._adjustLocalMediaDirection = function(
2071 2076
         logger.warn(`${this} No "audio" media found in the local description`);
2072 2077
     }
2073 2078
 
2074
-    const videoMedia = transformer.selectMedia('video');
2079
+    const videoMedia = transformer.selectMedia(MediaType.VIDEO);
2075 2080
 
2076 2081
     if (videoMedia) {
2077
-        const desiredVideoDirection
2078
-            = this._getDesiredMediaDirection(MediaType.VIDEO);
2082
+        const desiredVideoDirection = this.getDesiredMediaDirection(MediaType.VIDEO);
2079 2083
 
2080 2084
         if (videoMedia.direction !== desiredVideoDirection) {
2081 2085
             videoMedia.direction = desiredVideoDirection;
@@ -2096,6 +2100,33 @@ TraceablePeerConnection.prototype._adjustLocalMediaDirection = function(
2096 2100
     return localDescription;
2097 2101
 };
2098 2102
 
2103
+/**
2104
+ * Adjusts the media direction on the remote description based on availability of local and remote sources in a p2p
2105
+ * media connection.
2106
+ *
2107
+ * @param {RTCSessionDescription} remoteDescription the WebRTC session description instance for the remote description.
2108
+ * @returns the transformed remoteDescription.
2109
+ * @private
2110
+ */
2111
+TraceablePeerConnection.prototype._adjustRemoteMediaDirection = function(remoteDescription) {
2112
+    const transformer = new SdpTransformWrap(remoteDescription.sdp);
2113
+
2114
+    [ MediaType.AUDIO, MediaType.VIDEO ].forEach(mediaType => {
2115
+        const media = transformer.selectMedia(mediaType);
2116
+        const hasLocalSource = this.hasAnyTracksOfType(mediaType);
2117
+        const hasRemoteSource = this.getRemoteTracks(null, mediaType).length > 0;
2118
+
2119
+        media.direction = hasLocalSource && hasRemoteSource
2120
+            ? MediaDirection.SENDRECV
2121
+            : hasLocalSource ? MediaDirection.RECVONLY : MediaDirection.SENDONLY;
2122
+    });
2123
+
2124
+    return new RTCSessionDescription({
2125
+        type: remoteDescription.type,
2126
+        sdp: transformer.toRawSDP()
2127
+    });
2128
+};
2129
+
2099 2130
 /**
2100 2131
  * Munges the stereo flag as well as the opusMaxAverageBitrate in the SDP, based
2101 2132
  * on values set through config.js, if present.
@@ -2417,12 +2448,14 @@ TraceablePeerConnection.prototype.setRemoteDescription = function(description) {
2417 2448
             this.trace(
2418 2449
                 'setRemoteDescription::postTransform (sim receive)',
2419 2450
                 dumpSDP(description));
2420
-
2421
-            // eslint-disable-next-line no-param-reassign
2422
-            description = this.tpcUtils.ensureCorrectOrderOfSsrcs(description);
2423 2451
         }
2424 2452
     }
2425 2453
 
2454
+    if (this._usesUnifiedPlan) {
2455
+        // eslint-disable-next-line no-param-reassign
2456
+        description = this.tpcUtils.ensureCorrectOrderOfSsrcs(description);
2457
+    }
2458
+
2426 2459
     return new Promise((resolve, reject) => {
2427 2460
         this.peerconnection.setRemoteDescription(description)
2428 2461
             .then(() => {

+ 30
- 2
modules/xmpp/JingleSessionPC.js 查看文件

@@ -4,6 +4,7 @@ import { getLogger } from 'jitsi-meet-logger';
4 4
 import { $iq, Strophe } from 'strophe.js';
5 5
 
6 6
 import * as CodecMimeType from '../../service/RTC/CodecMimeType';
7
+import MediaDirection from '../../service/RTC/MediaDirection';
7 8
 import {
8 9
     ICE_DURATION,
9 10
     ICE_STATE_CHANGED
@@ -1821,8 +1822,23 @@ export default class JingleSessionPC extends JingleSession {
1821 1822
                     if (mid > -1) {
1822 1823
                         remoteSdp.media[mid] = remoteSdp.media[mid].replace(`${line}\r\n`, '');
1823 1824
 
1824
-                        // Change the direction to "inactive".
1825
-                        remoteSdp.media[mid] = remoteSdp.media[mid].replace('a=sendonly', 'a=inactive');
1825
+                        // The current direction of the transceiver for p2p will depend on whether a local sources is
1826
+                        // added or not. It will be 'sendrecv' if the local source is present, 'sendonly' otherwise.
1827
+                        if (this.isP2P) {
1828
+                            const mediaType = SDPUtil.parseMLine(remoteSdp.media[mid].split('\r\n')[0])?.media;
1829
+                            const desiredDirection = this.peerconnection.getDesiredMediaDirection(mediaType, false);
1830
+
1831
+                            [ MediaDirection.SENDRECV, MediaDirection.SENDONLY ].forEach(direction => {
1832
+                                remoteSdp.media[mid] = remoteSdp.media[mid]
1833
+                                    .replace(`a=${direction}`, `a=${desiredDirection}`);
1834
+                            });
1835
+
1836
+                        // Jvb connections will have direction set to 'sendonly' when the remote ssrc is present.
1837
+                        } else {
1838
+                            // Change the direction to "inactive" always for jvb connection.
1839
+                            remoteSdp.media[mid] = remoteSdp.media[mid]
1840
+                                .replace(`a=${MediaDirection.SENDONLY}`, `a=${MediaDirection.INACTIVE}`);
1841
+                        }
1826 1842
                     }
1827 1843
                 });
1828 1844
             } else {
@@ -1849,6 +1865,18 @@ export default class JingleSessionPC extends JingleSession {
1849 1865
 
1850 1866
         addSsrcInfo.forEach((lines, idx) => {
1851 1867
             remoteSdp.media[idx] += lines;
1868
+
1869
+            // Make sure to change the direction to 'sendrecv' only for p2p connections. For jvb connections, a new
1870
+            // m-line is added for the new remote sources.
1871
+            if (this.isP2P && this.usesUnifiedPlan) {
1872
+                const mediaType = SDPUtil.parseMLine(remoteSdp.media[idx].split('\r\n')[0])?.media;
1873
+                const desiredDirection = this.peerconnection.getDesiredMediaDirection(mediaType, true);
1874
+
1875
+                [ MediaDirection.RECVONLY, MediaDirection.INACTIVE ].forEach(direction => {
1876
+                    remoteSdp.media[idx] = remoteSdp.media[idx]
1877
+                        .replace(`a=${direction}`, `a=${desiredDirection}`);
1878
+                });
1879
+            }
1852 1880
         });
1853 1881
         remoteSdp.raw = remoteSdp.session + remoteSdp.media.join('');
1854 1882
 

Loading…
取消
儲存