|
|
@@ -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(() => {
|