|
|
@@ -1,6 +1,7 @@
|
|
1
|
1
|
/* global __filename, RTCSessionDescription */
|
|
2
|
2
|
|
|
3
|
3
|
import { getLogger } from 'jitsi-meet-logger';
|
|
|
4
|
+import { Interop } from '@jitsi/sdp-interop';
|
|
4
|
5
|
import transform from 'sdp-transform';
|
|
5
|
6
|
|
|
6
|
7
|
import * as GlobalOnErrorHandler from '../util/GlobalOnErrorHandler';
|
|
|
@@ -220,7 +221,6 @@ export default function TraceablePeerConnection(
|
|
220
|
221
|
* 300 values, i.e. 5 minutes; set to 0 to disable
|
|
221
|
222
|
*/
|
|
222
|
223
|
this.maxstats = options.maxstats;
|
|
223
|
|
- const Interop = require('@jitsi/sdp-interop').Interop;
|
|
224
|
224
|
|
|
225
|
225
|
this.interop = new Interop();
|
|
226
|
226
|
const Simulcast = require('@jitsi/sdp-simulcast');
|
|
|
@@ -267,10 +267,23 @@ export default function TraceablePeerConnection(
|
|
267
|
267
|
this.onicecandidate(event);
|
|
268
|
268
|
}
|
|
269
|
269
|
};
|
|
270
|
|
- this.peerconnection.onaddstream
|
|
271
|
|
- = event => this._remoteStreamAdded(event.stream);
|
|
272
|
|
- this.peerconnection.onremovestream
|
|
273
|
|
- = event => this._remoteStreamRemoved(event.stream);
|
|
|
270
|
+
|
|
|
271
|
+ // Use stream events in plan-b and track events in unified plan.
|
|
|
272
|
+ if (browser.usesPlanB()) {
|
|
|
273
|
+ this.peerconnection.onaddstream
|
|
|
274
|
+ = event => this._remoteStreamAdded(event.stream);
|
|
|
275
|
+ this.peerconnection.onremovestream
|
|
|
276
|
+ = event => this._remoteStreamRemoved(event.stream);
|
|
|
277
|
+ } else {
|
|
|
278
|
+ this.peerconnection.ontrack = event => {
|
|
|
279
|
+ const stream = event.streams[0];
|
|
|
280
|
+
|
|
|
281
|
+ this._remoteTrackAdded(stream, event.track, event.transceiver);
|
|
|
282
|
+ stream.onremovetrack = evt => {
|
|
|
283
|
+ this._remoteTrackRemoved(stream, evt.track);
|
|
|
284
|
+ };
|
|
|
285
|
+ };
|
|
|
286
|
+ }
|
|
274
|
287
|
this.onsignalingstatechange = null;
|
|
275
|
288
|
this.peerconnection.onsignalingstatechange = event => {
|
|
276
|
289
|
this.trace('onsignalingstatechange', this.signalingState);
|
|
|
@@ -421,16 +434,7 @@ TraceablePeerConnection.prototype._getDesiredMediaDirection = function(
|
|
421
|
434
|
* <tt>false</tt> if it's turned off.
|
|
422
|
435
|
*/
|
|
423
|
436
|
TraceablePeerConnection.prototype.isSimulcastOn = function() {
|
|
424
|
|
- return !this.options.disableSimulcast
|
|
425
|
|
- && browser.supportsSimulcast()
|
|
426
|
|
-
|
|
427
|
|
- // Firefox has been added as supporting simulcast, but it is
|
|
428
|
|
- // experimental so we only want to do it for firefox if the config
|
|
429
|
|
- // option is set. Unfortunately, browser::supportsSimulcast()
|
|
430
|
|
- // doesn't have a reference to the config options, so we have
|
|
431
|
|
- // to do it here
|
|
432
|
|
- && (!browser.isFirefox()
|
|
433
|
|
- || this.options.enableFirefoxSimulcast);
|
|
|
437
|
+ return !this.options.disableSimulcast;
|
|
434
|
438
|
};
|
|
435
|
439
|
|
|
436
|
440
|
/**
|
|
|
@@ -644,12 +648,21 @@ TraceablePeerConnection.prototype._remoteStreamAdded = function(stream) {
|
|
644
|
648
|
* @param {MediaStream} stream the WebRTC MediaStream instance which is
|
|
645
|
649
|
* the parent of the track
|
|
646
|
650
|
* @param {MediaStreamTrack} track the WebRTC MediaStreamTrack added for remote
|
|
647
|
|
- * participant
|
|
|
651
|
+ * participant.
|
|
|
652
|
+ * @param {RTCRtpTransceiver} transceiver the WebRTC transceiver that is created
|
|
|
653
|
+ * for the remote participant in unified plan.
|
|
648
|
654
|
*/
|
|
649
|
|
-TraceablePeerConnection.prototype._remoteTrackAdded = function(stream, track) {
|
|
|
655
|
+TraceablePeerConnection.prototype._remoteTrackAdded = function(stream, track, transceiver = null) {
|
|
650
|
656
|
const streamId = RTC.getStreamID(stream);
|
|
651
|
657
|
const mediaType = track.kind;
|
|
652
|
658
|
|
|
|
659
|
+ if (!this.isP2P && !RTC.isUserStreamById(streamId)) {
|
|
|
660
|
+ logger.info(
|
|
|
661
|
+ `${this} ignored remote 'stream added' event for non-user stream`
|
|
|
662
|
+ + `id: ${streamId}`);
|
|
|
663
|
+
|
|
|
664
|
+ return;
|
|
|
665
|
+ }
|
|
653
|
666
|
logger.info(`${this} remote track added:`, streamId, mediaType);
|
|
654
|
667
|
|
|
655
|
668
|
// look up an associated JID for a stream id
|
|
|
@@ -663,9 +676,26 @@ TraceablePeerConnection.prototype._remoteTrackAdded = function(stream, track) {
|
|
663
|
676
|
return;
|
|
664
|
677
|
}
|
|
665
|
678
|
|
|
666
|
|
- const remoteSDP = new SDP(this.remoteDescription.sdp);
|
|
667
|
|
- const mediaLines
|
|
668
|
|
- = remoteSDP.media.filter(mls => mls.startsWith(`m=${mediaType}`));
|
|
|
679
|
+ const remoteSDP = browser.usesPlanB()
|
|
|
680
|
+ ? new SDP(this.remoteDescription.sdp)
|
|
|
681
|
+ : new SDP(this.peerconnection.remoteDescription.sdp);
|
|
|
682
|
+ let mediaLines;
|
|
|
683
|
+
|
|
|
684
|
+ if (browser.usesUnifiedPlan()) {
|
|
|
685
|
+ if (transceiver && transceiver.mid) {
|
|
|
686
|
+ const mid = transceiver.mid;
|
|
|
687
|
+
|
|
|
688
|
+ mediaLines = remoteSDP.media.filter(mls => SDPUtil.findLine(mls, `a=mid:${mid}`));
|
|
|
689
|
+ } else {
|
|
|
690
|
+ mediaLines = remoteSDP.media.filter(mls => {
|
|
|
691
|
+ const msid = SDPUtil.findLine(mls, 'a=msid');
|
|
|
692
|
+
|
|
|
693
|
+ return typeof msid !== 'undefined' && streamId === msid.substring(7).split(' ')[0];
|
|
|
694
|
+ });
|
|
|
695
|
+ }
|
|
|
696
|
+ } else {
|
|
|
697
|
+ mediaLines = remoteSDP.media.filter(mls => mls.startsWith(`m=${mediaType}`));
|
|
|
698
|
+ }
|
|
669
|
699
|
|
|
670
|
700
|
if (!mediaLines.length) {
|
|
671
|
701
|
GlobalOnErrorHandler.callErrorHandler(
|
|
|
@@ -1321,24 +1351,24 @@ const getters = {
|
|
1321
|
1351
|
desc = this._injectSsrcGroupForUnifiedSimulcast(desc);
|
|
1322
|
1352
|
this.trace('getLocalDescription::postTransform (inject ssrc group)',
|
|
1323
|
1353
|
dumpSDP(desc));
|
|
1324
|
|
- }
|
|
|
1354
|
+ } else {
|
|
|
1355
|
+ if (browser.doesVideoMuteByStreamRemove()) {
|
|
|
1356
|
+ desc = this.localSdpMunger.maybeAddMutedLocalVideoTracksToSDP(desc);
|
|
|
1357
|
+ logger.debug(
|
|
|
1358
|
+ 'getLocalDescription::postTransform (munge local SDP)', desc);
|
|
|
1359
|
+ }
|
|
1325
|
1360
|
|
|
1326
|
|
- if (browser.doesVideoMuteByStreamRemove()) {
|
|
1327
|
|
- desc = this.localSdpMunger.maybeAddMutedLocalVideoTracksToSDP(desc);
|
|
1328
|
|
- logger.debug(
|
|
1329
|
|
- 'getLocalDescription::postTransform (munge local SDP)', desc);
|
|
|
1361
|
+ // What comes out of this getter will be signalled over Jingle to
|
|
|
1362
|
+ // the other peer, so we need to make sure the media direction is
|
|
|
1363
|
+ // 'sendrecv' because we won't change the direction later and don't want
|
|
|
1364
|
+ // the other peer to think we can't send or receive.
|
|
|
1365
|
+ //
|
|
|
1366
|
+ // Note that the description we set in chrome does have the accurate
|
|
|
1367
|
+ // direction (e.g. 'recvonly'), since that is technically what is
|
|
|
1368
|
+ // happening (check setLocalDescription impl).
|
|
|
1369
|
+ desc = enforceSendRecv(desc, this.options);
|
|
1330
|
1370
|
}
|
|
1331
|
1371
|
|
|
1332
|
|
- // What comes out of this getter will be signalled over Jingle to
|
|
1333
|
|
- // the other peer, so we need to make sure the media direction is
|
|
1334
|
|
- // 'sendrecv' because we won't change the direction later and don't want
|
|
1335
|
|
- // the other peer to think we can't send or receive.
|
|
1336
|
|
- //
|
|
1337
|
|
- // Note that the description we set in chrome does have the accurate
|
|
1338
|
|
- // direction (e.g. 'recvonly'), since that is technically what is
|
|
1339
|
|
- // happening (check setLocalDescription impl).
|
|
1340
|
|
- desc = enforceSendRecv(desc, this.options);
|
|
1341
|
|
-
|
|
1342
|
1372
|
// See the method's doc for more info about this transformation.
|
|
1343
|
1373
|
desc = this.localSdpMunger.transformStreamIdentifiers(desc);
|
|
1344
|
1374
|
|
|
|
@@ -1347,6 +1377,11 @@ const getters = {
|
|
1347
|
1377
|
remoteDescription() {
|
|
1348
|
1378
|
let desc = this.peerconnection.remoteDescription;
|
|
1349
|
1379
|
|
|
|
1380
|
+ if (!desc) {
|
|
|
1381
|
+ logger.debug('getRemoteDescription no remoteDescription found');
|
|
|
1382
|
+
|
|
|
1383
|
+ return {};
|
|
|
1384
|
+ }
|
|
1350
|
1385
|
this.trace('getRemoteDescription::preTransform', dumpSDP(desc));
|
|
1351
|
1386
|
|
|
1352
|
1387
|
// if we're running on FF, transform to Plan B first.
|
|
|
@@ -1356,7 +1391,7 @@ const getters = {
|
|
1356
|
1391
|
'getRemoteDescription::postTransform (Plan B)', dumpSDP(desc));
|
|
1357
|
1392
|
}
|
|
1358
|
1393
|
|
|
1359
|
|
- return desc || {};
|
|
|
1394
|
+ return desc;
|
|
1360
|
1395
|
}
|
|
1361
|
1396
|
};
|
|
1362
|
1397
|
|
|
|
@@ -1406,7 +1441,7 @@ TraceablePeerConnection.prototype.addTrack = function(track, isInitiator = false
|
|
1406
|
1441
|
}
|
|
1407
|
1442
|
|
|
1408
|
1443
|
// Muted video tracks do not have WebRTC stream
|
|
1409
|
|
- if (browser.doesVideoMuteByStreamRemove()
|
|
|
1444
|
+ if (browser.usesPlanB() && browser.doesVideoMuteByStreamRemove()
|
|
1410
|
1445
|
&& track.isVideoTrack() && track.isMuted()) {
|
|
1411
|
1446
|
const ssrcInfo = this.generateNewStreamSSRCInfo(track);
|
|
1412
|
1447
|
|
|
|
@@ -1793,12 +1828,12 @@ TraceablePeerConnection.prototype.setLocalDescription = function(description) {
|
|
1793
|
1828
|
dumpSDP(localSdp));
|
|
1794
|
1829
|
}
|
|
1795
|
1830
|
|
|
1796
|
|
- localSdp = this._adjustLocalMediaDirection(localSdp);
|
|
1797
|
|
-
|
|
1798
|
|
- localSdp = this._ensureSimulcastGroupIsLast(localSdp);
|
|
|
1831
|
+ if (browser.usesPlanB()) {
|
|
|
1832
|
+ localSdp = this._adjustLocalMediaDirection(localSdp);
|
|
|
1833
|
+ localSdp = this._ensureSimulcastGroupIsLast(localSdp);
|
|
|
1834
|
+ } else {
|
|
1799
|
1835
|
|
|
1800
|
|
- // if we're using unified plan, transform to it first.
|
|
1801
|
|
- if (browser.usesUnifiedPlan()) {
|
|
|
1836
|
+ // if we're using unified plan, transform to it first.
|
|
1802
|
1837
|
localSdp = this.interop.toUnifiedPlan(localSdp);
|
|
1803
|
1838
|
this.trace(
|
|
1804
|
1839
|
'setLocalDescription::postTransform (Unified Plan)',
|
|
|
@@ -1889,7 +1924,7 @@ TraceablePeerConnection.prototype.setMaxBitRate = function(localTrack) {
|
|
1889
|
1924
|
if (!parameters.encodings || !parameters.encodings.length) {
|
|
1890
|
1925
|
return;
|
|
1891
|
1926
|
}
|
|
1892
|
|
- logger.info('Setting max bitrate on video stream');
|
|
|
1927
|
+ logger.debug('Setting max bitrate on video stream');
|
|
1893
|
1928
|
for (const encoding in parameters.encodings) {
|
|
1894
|
1929
|
if (parameters.encodings.hasOwnProperty(encoding)) {
|
|
1895
|
1930
|
parameters.encodings[encoding].maxBitrate
|
|
|
@@ -1915,64 +1950,51 @@ TraceablePeerConnection.prototype.setMaxBitRate = function(localTrack) {
|
|
1915
|
1950
|
TraceablePeerConnection.prototype.setRemoteDescription = function(description) {
|
|
1916
|
1951
|
this.trace('setRemoteDescription::preTransform', dumpSDP(description));
|
|
1917
|
1952
|
|
|
1918
|
|
- // TODO the focus should squeze or explode the remote simulcast
|
|
1919
|
|
- // eslint-disable-next-line no-param-reassign
|
|
1920
|
|
- description = this.simulcast.mungeRemoteDescription(description);
|
|
1921
|
|
- this.trace(
|
|
1922
|
|
- 'setRemoteDescription::postTransform (simulcast)',
|
|
1923
|
|
- dumpSDP(description));
|
|
|
1953
|
+ if (browser.usesPlanB()) {
|
|
|
1954
|
+ // TODO the focus should squeze or explode the remote simulcast
|
|
|
1955
|
+ // eslint-disable-next-line no-param-reassign
|
|
|
1956
|
+ description = this.simulcast.mungeRemoteDescription(description);
|
|
|
1957
|
+ this.trace(
|
|
|
1958
|
+ 'setRemoteDescription::postTransform (simulcast)',
|
|
|
1959
|
+ dumpSDP(description));
|
|
1924
|
1960
|
|
|
1925
|
|
- if (this.options.preferH264) {
|
|
1926
|
|
- const parsedSdp = transform.parse(description.sdp);
|
|
1927
|
|
- const videoMLine = parsedSdp.media.find(m => m.type === 'video');
|
|
|
1961
|
+ if (this.options.preferH264) {
|
|
|
1962
|
+ const parsedSdp = transform.parse(description.sdp);
|
|
|
1963
|
+ const videoMLine = parsedSdp.media.find(m => m.type === 'video');
|
|
1928
|
1964
|
|
|
1929
|
|
- SDPUtil.preferVideoCodec(videoMLine, 'h264');
|
|
|
1965
|
+ SDPUtil.preferVideoCodec(videoMLine, 'h264');
|
|
1930
|
1966
|
|
|
1931
|
|
- // eslint-disable-next-line no-param-reassign
|
|
1932
|
|
- description = new RTCSessionDescription({
|
|
1933
|
|
- type: description.type,
|
|
1934
|
|
- sdp: transform.write(parsedSdp)
|
|
1935
|
|
- });
|
|
1936
|
|
- }
|
|
|
1967
|
+ // eslint-disable-next-line no-param-reassign
|
|
|
1968
|
+ description = new RTCSessionDescription({
|
|
|
1969
|
+ type: description.type,
|
|
|
1970
|
+ sdp: transform.write(parsedSdp)
|
|
|
1971
|
+ });
|
|
|
1972
|
+ }
|
|
1937
|
1973
|
|
|
1938
|
|
- // If the browser uses unified plan, transform to it first
|
|
1939
|
|
- if (browser.usesUnifiedPlan()) {
|
|
1940
|
1974
|
// eslint-disable-next-line no-param-reassign
|
|
1941
|
|
- description = new RTCSessionDescription({
|
|
1942
|
|
- type: description.type,
|
|
1943
|
|
- sdp: this.rtxModifier.stripRtx(description.sdp)
|
|
1944
|
|
- });
|
|
1945
|
|
-
|
|
1946
|
|
- this.trace(
|
|
1947
|
|
- 'setRemoteDescription::postTransform (stripRtx)',
|
|
1948
|
|
- dumpSDP(description));
|
|
|
1975
|
+ description = normalizePlanB(description);
|
|
|
1976
|
+ } else {
|
|
|
1977
|
+ const currentDescription = this.peerconnection.remoteDescription;
|
|
1949
|
1978
|
|
|
1950
|
1979
|
// eslint-disable-next-line no-param-reassign
|
|
1951
|
|
- description = this.interop.toUnifiedPlan(description);
|
|
|
1980
|
+ description = this.interop.toUnifiedPlan(description, currentDescription);
|
|
1952
|
1981
|
this.trace(
|
|
1953
|
|
- 'setRemoteDescription::postTransform (Plan A)',
|
|
|
1982
|
+ 'setRemoteDescription::postTransform (Unified)',
|
|
1954
|
1983
|
dumpSDP(description));
|
|
1955
|
1984
|
|
|
1956
|
1985
|
if (this.isSimulcastOn()) {
|
|
|
1986
|
+ // eslint-disable-next-line no-param-reassign
|
|
|
1987
|
+ description = this.simulcast.mungeRemoteDescription(description);
|
|
|
1988
|
+
|
|
1957
|
1989
|
// eslint-disable-next-line no-param-reassign
|
|
1958
|
1990
|
description = this.tpcUtils._insertUnifiedPlanSimulcastReceive(description);
|
|
1959
|
1991
|
this.trace(
|
|
1960
|
1992
|
'setRemoteDescription::postTransform (sim receive)',
|
|
1961
|
1993
|
dumpSDP(description));
|
|
1962
|
|
- }
|
|
1963
|
|
- } else {
|
|
1964
|
|
- // Plan B
|
|
1965
|
|
- // eslint-disable-next-line no-param-reassign
|
|
1966
|
|
- description = normalizePlanB(description);
|
|
1967
|
|
- }
|
|
1968
|
1994
|
|
|
1969
|
|
- // Safari WebRTC errors when no supported video codec is found in the offer.
|
|
1970
|
|
- // To prevent the error, inject H264 into the video mLine.
|
|
1971
|
|
- if (browser.isSafariWithWebrtc() && !browser.isSafariWithVP8()) {
|
|
1972
|
|
- logger.debug('Maybe injecting H264 into the remote description');
|
|
1973
|
|
-
|
|
1974
|
|
- // eslint-disable-next-line no-param-reassign
|
|
1975
|
|
- description = this._injectH264IfNotPresent(description);
|
|
|
1995
|
+ // eslint-disable-next-line no-param-reassign
|
|
|
1996
|
+ description = this.tpcUtils._ensureCorrectOrderOfSsrcs(description);
|
|
|
1997
|
+ }
|
|
1976
|
1998
|
}
|
|
1977
|
1999
|
|
|
1978
|
2000
|
return new Promise((resolve, reject) => {
|
|
|
@@ -1998,76 +2020,6 @@ TraceablePeerConnection.prototype.setRemoteDescription = function(description) {
|
|
1998
|
2020
|
});
|
|
1999
|
2021
|
};
|
|
2000
|
2022
|
|
|
2001
|
|
-/**
|
|
2002
|
|
- * Inserts an H264 payload into the description if not already present. This is
|
|
2003
|
|
- * need for Safari WebRTC, which errors when no supported video codec is found
|
|
2004
|
|
- * in the offer. Related bug reports:
|
|
2005
|
|
- * https://bugs.webkit.org/show_bug.cgi?id=173141
|
|
2006
|
|
- * https://bugs.chromium.org/p/webrtc/issues/detail?id=4957
|
|
2007
|
|
- *
|
|
2008
|
|
- * @param {RTCSessionDescription} description - An RTCSessionDescription
|
|
2009
|
|
- * to inject with an H264 payload.
|
|
2010
|
|
- * @private
|
|
2011
|
|
- * @returns {RTCSessionDescription}
|
|
2012
|
|
- */
|
|
2013
|
|
-TraceablePeerConnection.prototype._injectH264IfNotPresent = function(
|
|
2014
|
|
- description) {
|
|
2015
|
|
- const parsedSdp = transform.parse(description.sdp);
|
|
2016
|
|
- const videoMLine = parsedSdp.media.find(m => m.type === 'video');
|
|
2017
|
|
-
|
|
2018
|
|
- if (!videoMLine) {
|
|
2019
|
|
- logger.debug('No videoMLine found, no need to inject H264.');
|
|
2020
|
|
-
|
|
2021
|
|
- return description;
|
|
2022
|
|
- }
|
|
2023
|
|
-
|
|
2024
|
|
- if (videoMLine.rtp.some(rtp => rtp.codec.toLowerCase() === 'h264')) {
|
|
2025
|
|
- logger.debug('H264 codec found in video mLine, no need to inject.');
|
|
2026
|
|
-
|
|
2027
|
|
- return description;
|
|
2028
|
|
- }
|
|
2029
|
|
-
|
|
2030
|
|
- const { fmtp, payloads, rtp } = videoMLine;
|
|
2031
|
|
- const payloadsArray = payloads.toString().split(' ');
|
|
2032
|
|
- let dummyPayloadType;
|
|
2033
|
|
-
|
|
2034
|
|
- for (let i = 127; i >= 96; i--) {
|
|
2035
|
|
- if (!payloadsArray.includes(i)) {
|
|
2036
|
|
- dummyPayloadType = i;
|
|
2037
|
|
- payloadsArray.push(i);
|
|
2038
|
|
- videoMLine.payloads = payloadsArray.join(' ');
|
|
2039
|
|
- break;
|
|
2040
|
|
- }
|
|
2041
|
|
- }
|
|
2042
|
|
-
|
|
2043
|
|
- if (typeof dummyPayloadType === 'undefined') {
|
|
2044
|
|
- logger.error('Could not find valid payload type to inject.');
|
|
2045
|
|
-
|
|
2046
|
|
- return description;
|
|
2047
|
|
- }
|
|
2048
|
|
-
|
|
2049
|
|
- rtp.push({
|
|
2050
|
|
- codec: 'H264',
|
|
2051
|
|
- payload: dummyPayloadType,
|
|
2052
|
|
- rate: 90000
|
|
2053
|
|
- });
|
|
2054
|
|
-
|
|
2055
|
|
- fmtp.push({
|
|
2056
|
|
- config: 'level-asymmetry-allowed=1;'
|
|
2057
|
|
- + 'packetization-mode=1;'
|
|
2058
|
|
- + 'profile-level-id=42e01f',
|
|
2059
|
|
- payload: dummyPayloadType
|
|
2060
|
|
- });
|
|
2061
|
|
-
|
|
2062
|
|
- logger.debug(
|
|
2063
|
|
- `Injecting H264 payload type ${dummyPayloadType} into video mLine.`);
|
|
2064
|
|
-
|
|
2065
|
|
- return new RTCSessionDescription({
|
|
2066
|
|
- type: description.type,
|
|
2067
|
|
- sdp: transform.write(parsedSdp)
|
|
2068
|
|
- });
|
|
2069
|
|
-};
|
|
2070
|
|
-
|
|
2071
|
2023
|
/**
|
|
2072
|
2024
|
* Enables/disables video media transmission on this peer connection. When
|
|
2073
|
2025
|
* disabled the SDP video media direction in the local SDP will be adjusted to
|
|
|
@@ -2278,17 +2230,6 @@ const _fixAnswerRFC4145Setup = function(offer, answer) {
|
|
2278
|
2230
|
};
|
|
2279
|
2231
|
|
|
2280
|
2232
|
TraceablePeerConnection.prototype.createAnswer = function(constraints) {
|
|
2281
|
|
- if (browser.isFirefox() && this.isSimulcastOn()) {
|
|
2282
|
|
- const videoSender
|
|
2283
|
|
- = this.peerconnection.getSenders().find(sender =>
|
|
2284
|
|
- sender.track !== null && sender.track.kind === 'video');
|
|
2285
|
|
- const simParams = {
|
|
2286
|
|
- encodings: this.tpcUtils.simulcastEncodings
|
|
2287
|
|
- };
|
|
2288
|
|
-
|
|
2289
|
|
- videoSender.setParameters(simParams);
|
|
2290
|
|
- }
|
|
2291
|
|
-
|
|
2292
|
2233
|
return this._createOfferOrAnswer(false /* answer */, constraints);
|
|
2293
|
2234
|
};
|
|
2294
|
2235
|
|
|
|
@@ -2319,32 +2260,7 @@ TraceablePeerConnection.prototype._createOfferOrAnswer = function(
|
|
2319
|
2260
|
this.trace(
|
|
2320
|
2261
|
`create${logName}OnSuccess::preTransform`, dumpSDP(resultSdp));
|
|
2321
|
2262
|
|
|
2322
|
|
- // if we're using unified plan, transform to Plan B.
|
|
2323
|
|
- if (browser.usesUnifiedPlan()) {
|
|
2324
|
|
- // eslint-disable-next-line no-param-reassign
|
|
2325
|
|
- resultSdp = this.interop.toPlanB(resultSdp);
|
|
2326
|
|
- this.trace(
|
|
2327
|
|
- `create${logName}OnSuccess::postTransform (Plan B)`,
|
|
2328
|
|
- dumpSDP(resultSdp));
|
|
2329
|
|
- if (this.isSimulcastOn()) {
|
|
2330
|
|
- // eslint-disable-next-line no-param-reassign
|
|
2331
|
|
- resultSdp
|
|
2332
|
|
- = this._injectSsrcGroupForUnifiedSimulcast(resultSdp);
|
|
2333
|
|
- this.trace(
|
|
2334
|
|
- `create${logName}OnSuccess::postTransform`
|
|
2335
|
|
- + '(inject ssrc group)', dumpSDP(resultSdp));
|
|
2336
|
|
- }
|
|
2337
|
|
- }
|
|
2338
|
|
-
|
|
2339
|
|
- /**
|
|
2340
|
|
- * We don't keep ssrcs consitent for Firefox because rewriting
|
|
2341
|
|
- * the ssrcs between createAnswer and setLocalDescription breaks
|
|
2342
|
|
- * the caching in sdp-interop (sdp-interop must know about all
|
|
2343
|
|
- * ssrcs, and it updates its cache in toPlanB so if we rewrite them
|
|
2344
|
|
- * after that, when we try and go back to unified plan it will
|
|
2345
|
|
- * complain about unmapped ssrcs)
|
|
2346
|
|
- */
|
|
2347
|
|
- if (!browser.usesUnifiedPlan()) {
|
|
|
2263
|
+ if (browser.usesPlanB()) {
|
|
2348
|
2264
|
// If there are no local video tracks, then a "recvonly"
|
|
2349
|
2265
|
// SSRC needs to be generated
|
|
2350
|
2266
|
if (!this.hasAnyTracksOfType(MediaType.VIDEO)
|