Procházet zdrojové kódy

ref(JingleSession) Always call sRD->cA-sLD for renegotiation.

For renegotiations triggered by the application, it is ok to execute sRD->cA-sLD cycle on the p2p initiator instead of executing cO->sLD->sRD cycle. Chrome sometimes creates a third m-line for p2p when createOffer is called which is unexpected and therefore it breaks the client's renegotiation cycle. This has been done in other places already, i.e., when remote sources are signaled, etc. so making it uniform across all renegotiations.
release-8443
Jaya Allamsetty před 2 roky
rodič
revize
53e69d6ea5
2 změnil soubory, kde provedl 32 přidání a 121 odebrání
  1. 5
    5
      modules/RTC/TraceablePeerConnection.js
  2. 27
    116
      modules/xmpp/JingleSessionPC.js

+ 5
- 5
modules/RTC/TraceablePeerConnection.js Zobrazit soubor

2509
  * @returns {Promise} promise that will be resolved when the operation is successful and rejected otherwise.
2509
  * @returns {Promise} promise that will be resolved when the operation is successful and rejected otherwise.
2510
  */
2510
  */
2511
 TraceablePeerConnection.prototype.configureSenderVideoEncodings = function(localVideoTrack = null) {
2511
 TraceablePeerConnection.prototype.configureSenderVideoEncodings = function(localVideoTrack = null) {
2512
-    // If media is suspended on the peerconnection, make sure that media stays disabled. The default 'active' state for
2513
-    // the encodings after the source is added to the peerconnection is 'true', so it needs to be explicitly disabled
2514
-    // after the source is added.
2515
-    if (!(this.videoTransferActive && this.audioTransferActive)) {
2512
+    // If media is suspended on the jvb peerconnection, make sure that media stays disabled. The default 'active' state
2513
+    // for the encodings after the source is added to the peerconnection is 'true', so it needs to be explicitly
2514
+    // disabled after the source is added.
2515
+    if (!this.isP2P && !(this.videoTransferActive && this.audioTransferActive)) {
2516
         return this.tpcUtils.setMediaTransferActive(false);
2516
         return this.tpcUtils.setMediaTransferActive(false);
2517
     }
2517
     }
2518
 
2518
 
2651
 
2651
 
2652
     // Ignore sender constraints if the media on the peerconnection is suspended (jvb conn when p2p is currently active)
2652
     // Ignore sender constraints if the media on the peerconnection is suspended (jvb conn when p2p is currently active)
2653
     // or if the video track is muted.
2653
     // or if the video track is muted.
2654
-    if (!this.videoTransferActive || localVideoTrack.isMuted()) {
2654
+    if ((!this.isP2P && !this.videoTransferActive) || localVideoTrack.isMuted()) {
2655
         this._senderMaxHeights.set(sourceName, frameHeight);
2655
         this._senderMaxHeights.set(sourceName, frameHeight);
2656
 
2656
 
2657
         return Promise.resolve();
2657
         return Promise.resolve();

+ 27
- 116
modules/xmpp/JingleSessionPC.js Zobrazit soubor

1170
             addTracks.push(this.peerconnection.addTrack(track, this.isInitiator));
1170
             addTracks.push(this.peerconnection.addTrack(track, this.isInitiator));
1171
         }
1171
         }
1172
         const newRemoteSdp = this._processNewJingleOfferIq(jingleOfferAnswerIq);
1172
         const newRemoteSdp = this._processNewJingleOfferIq(jingleOfferAnswerIq);
1173
-        const oldLocalSdp = this.peerconnection.localDescription.sdp;
1174
-
1175
         const bridgeSession = $(jingleOfferAnswerIq).find('>bridge-session[xmlns="http://jitsi.org/protocol/focus"]');
1173
         const bridgeSession = $(jingleOfferAnswerIq).find('>bridge-session[xmlns="http://jitsi.org/protocol/focus"]');
1176
         const bridgeSessionId = bridgeSession.attr('id');
1174
         const bridgeSessionId = bridgeSession.attr('id');
1177
 
1175
 
1178
         if (bridgeSessionId !== this._bridgeSessionId) {
1176
         if (bridgeSessionId !== this._bridgeSessionId) {
1179
             this._bridgeSessionId = bridgeSessionId;
1177
             this._bridgeSessionId = bridgeSessionId;
1180
         }
1178
         }
1181
-        const remoteDescription = new RTCSessionDescription({
1182
-            type: 'offer',
1183
-            sdp: newRemoteSdp.raw
1184
-        });
1185
 
1179
 
1186
         Promise.all(addTracks)
1180
         Promise.all(addTracks)
1187
-            .then(() => this._responderRenegotiate(remoteDescription))
1181
+            .then(() => this._renegotiate(newRemoteSdp.raw))
1188
             .then(() => {
1182
             .then(() => {
1189
                 this.peerconnection.processLocalSdpForTransceiverInfo(tracks);
1183
                 this.peerconnection.processLocalSdpForTransceiverInfo(tracks);
1190
                 if (this.state === JingleSessionState.PENDING) {
1184
                 if (this.state === JingleSessionState.PENDING) {
1197
                     // interested in receiving video content. Changing media direction in the remote SDP will mess
1191
                     // interested in receiving video content. Changing media direction in the remote SDP will mess
1198
                     // up our SDP translation chain (simulcast, video mute, RTX etc.)
1192
                     // up our SDP translation chain (simulcast, video mute, RTX etc.)
1199
                     // #2 Sends the max frame height if it was set, before the session-initiate/accept
1193
                     // #2 Sends the max frame height if it was set, before the session-initiate/accept
1200
-                    if (this.isP2P
1201
-                        && (!this._localVideoActive || this._sourceReceiverConstraints)) {
1194
+                    if (this.isP2P && (!this._localVideoActive || this._sourceReceiverConstraints)) {
1202
                         this.sendContentModify();
1195
                         this.sendContentModify();
1203
                     }
1196
                     }
1204
                 }
1197
                 }
1205
 
1198
 
1206
-                // Old local SDP will be available when we're setting answer for the first time, but not when offer
1207
-                // and it's fine since we're generating an answer now it will contain all our SSRCs.
1208
-                if (oldLocalSdp) {
1209
-                    const newLocalSdp = new SDP(this.peerconnection.localDescription.sdp);
1210
-
1211
-                    this.notifyMySSRCUpdate(new SDP(oldLocalSdp), newLocalSdp);
1212
-                }
1213
             })
1199
             })
1214
             .then(() => {
1200
             .then(() => {
1215
                 logger.debug(`${this} setOfferAnswerCycle task done`);
1201
                 logger.debug(`${this} setOfferAnswerCycle task done`);
1955
 
1941
 
1956
             logger.log(`${this} Processing ${logPrefix}`);
1942
             logger.log(`${this} Processing ${logPrefix}`);
1957
 
1943
 
1958
-            const oldLocalSdp = new SDP(this.peerconnection.localDescription.sdp);
1959
             const sdp = new SDP(this.peerconnection.remoteDescription.sdp);
1944
             const sdp = new SDP(this.peerconnection.remoteDescription.sdp);
1960
             const addOrRemoveSsrcInfo
1945
             const addOrRemoveSsrcInfo
1961
                 = isAdd
1946
                 = isAdd
1965
                 = isAdd
1950
                 = isAdd
1966
                     ? this._processRemoteAddSource(addOrRemoveSsrcInfo)
1951
                     ? this._processRemoteAddSource(addOrRemoveSsrcInfo)
1967
                     : this._processRemoteRemoveSource(addOrRemoveSsrcInfo);
1952
                     : this._processRemoteRemoveSource(addOrRemoveSsrcInfo);
1968
-            const remoteDescription = new RTCSessionDescription({
1969
-                type: 'offer',
1970
-                sdp: newRemoteSdp.raw
1971
-            });
1972
-
1973
-            // Always initiate a sRD->cA->sLD cycle when a remote source is added or removed irrespective of whether
1974
-            // the local endpoint is an initiator or responder. Fixes bugs on Chromium where decoders are not created
1975
-            // when sLD->cO->sRD cycle is initiated for p2p cases when remote sources are received.
1976
-            this._responderRenegotiate(remoteDescription).then(() => {
1977
-                const newLocalSdp = new SDP(this.peerconnection.localDescription.sdp);
1978
 
1953
 
1954
+            this._renegotiate(newRemoteSdp.raw).then(() => {
1979
                 logger.log(`${this} ${logPrefix} - OK`);
1955
                 logger.log(`${this} ${logPrefix} - OK`);
1980
-                this.notifyMySSRCUpdate(oldLocalSdp, newLocalSdp);
1981
                 finishedCallback();
1956
                 finishedCallback();
1982
             }, error => {
1957
             }, error => {
1983
                 logger.error(`${this} ${logPrefix} failed:`, error);
1958
                 logger.error(`${this} ${logPrefix} failed:`, error);
2117
     }
2092
     }
2118
 
2093
 
2119
     /**
2094
     /**
2120
-     * Do a new o/a flow using the existing remote description
2121
-     * @param {string} [optionalRemoteSdp] optional, raw remote sdp
2122
-     *  to use.  If not provided, the remote sdp from the
2123
-     *  peerconnection will be used
2124
-     * @returns {Promise} promise which resolves when the
2125
-     *  o/a flow is complete with no arguments or
2126
-     *  rejects with an error {string}
2095
+     * Does a new offer/answer flow using the existing remote description (if not provided) and signals any new sources
2096
+     * to Jicofo or the remote peer.
2097
+     *
2098
+     * @param {string} [optionalRemoteSdp] optional, raw remote sdp to use.  If not provided, the remote sdp from the
2099
+     * peerconnection will be used.
2100
+     * @returns {Promise} promise which resolves when the o/a flow is complete with no arguments or rejects with an
2101
+     * error {string}
2127
      */
2102
      */
2128
     _renegotiate(optionalRemoteSdp) {
2103
     _renegotiate(optionalRemoteSdp) {
2129
         if (this.peerconnection.signalingState === 'closed') {
2104
         if (this.peerconnection.signalingState === 'closed') {
2134
             return Promise.reject(error);
2109
             return Promise.reject(error);
2135
         }
2110
         }
2136
 
2111
 
2137
-        const remoteSdp
2138
-            = optionalRemoteSdp || this.peerconnection.remoteDescription.sdp;
2112
+        const remoteSdp = optionalRemoteSdp || this.peerconnection.remoteDescription.sdp;
2139
 
2113
 
2140
         if (!remoteSdp) {
2114
         if (!remoteSdp) {
2141
             const error = new Error(`Can not renegotiate without remote description, current state: ${this.state}`);
2115
             const error = new Error(`Can not renegotiate without remote description, current state: ${this.state}`);
2146
         }
2120
         }
2147
 
2121
 
2148
         const remoteDescription = new RTCSessionDescription({
2122
         const remoteDescription = new RTCSessionDescription({
2149
-            type: this.isInitiator ? 'answer' : 'offer',
2123
+            type: 'offer',
2150
             sdp: remoteSdp
2124
             sdp: remoteSdp
2151
         });
2125
         });
2152
 
2126
 
2153
-        const promise = this.isInitiator
2154
-            ? this._initiatorRenegotiate(remoteDescription)
2155
-            : this._responderRenegotiate(remoteDescription);
2156
-        const oldLocalSDP = new SDP(this.peerconnection.localDescription.sdp);
2157
-
2158
-        return promise.then(() => {
2159
-            const newLocalSDP = new SDP(this.peerconnection.localDescription.sdp);
2160
-
2161
-            // Send the source updates after every renegotiation cycle.
2162
-            oldLocalSDP && this.notifyMySSRCUpdate(oldLocalSDP, newLocalSDP);
2163
-        });
2164
-    }
2127
+        const oldLocalSDP = this.peerconnection.localDescription.sdp;
2165
 
2128
 
2166
-    /**
2167
-     * Renegotiate cycle implementation for the responder case.
2168
-     * @param {object} remoteDescription the SDP object as defined by the WebRTC
2169
-     * which will be used as remote description in the cycle.
2170
-     * @private
2171
-     */
2172
-    _responderRenegotiate(remoteDescription) {
2173
         logger.debug(`${this} Renegotiate: setting remote description`);
2129
         logger.debug(`${this} Renegotiate: setting remote description`);
2174
 
2130
 
2175
         return this.peerconnection.setRemoteDescription(remoteDescription)
2131
         return this.peerconnection.setRemoteDescription(remoteDescription)
2176
             .then(() => {
2132
             .then(() => {
2177
                 logger.debug(`${this} Renegotiate: creating answer`);
2133
                 logger.debug(`${this} Renegotiate: creating answer`);
2178
 
2134
 
2179
-                return this.peerconnection.createAnswer(this.mediaConstraints)
2180
-                    .then(answer => {
2181
-                        logger.debug(`${this} Renegotiate: setting local description`);
2182
-
2183
-                        return this.peerconnection.setLocalDescription(answer);
2184
-                    });
2185
-            });
2186
-    }
2187
-
2188
-    /**
2189
-     * Renegotiate cycle implementation for the initiator's case.
2190
-     * @param {object} remoteDescription the SDP object as defined by the WebRTC
2191
-     * which will be used as remote description in the cycle.
2192
-     * @private
2193
-     */
2194
-    _initiatorRenegotiate(remoteDescription) {
2195
-        logger.debug(`${this} Renegotiate: creating offer`);
2196
-
2197
-        return this.peerconnection.createOffer(this.mediaConstraints)
2198
-            .then(offer => {
2135
+                return this.peerconnection.createAnswer(this.mediaConstraints);
2136
+            })
2137
+            .then(answer => {
2199
                 logger.debug(`${this} Renegotiate: setting local description`);
2138
                 logger.debug(`${this} Renegotiate: setting local description`);
2200
 
2139
 
2201
-                return this.peerconnection.setLocalDescription(offer)
2202
-                    .then(() => {
2203
-                        logger.debug(`${this} Renegotiate: setting remote description`);
2204
-
2205
-                        // eslint-disable-next-line max-len
2206
-                        return this.peerconnection.setRemoteDescription(remoteDescription);
2207
-                    });
2140
+                return this.peerconnection.setLocalDescription(answer);
2141
+            })
2142
+            .then(() => {
2143
+                if (oldLocalSDP) {
2144
+                    // Send the source updates after every renegotiation cycle.
2145
+                    this.notifyMySSRCUpdate(new SDP(oldLocalSDP), new SDP(this.peerconnection.localDescription.sdp));
2146
+                }
2208
             });
2147
             });
2209
     }
2148
     }
2210
 
2149
 
2240
                 }
2179
                 }
2241
             }
2180
             }
2242
 
2181
 
2243
-            const remoteDescription = new RTCSessionDescription({
2244
-                type: 'offer',
2245
-                sdp: remoteSdp.raw
2246
-            });
2247
-
2248
-            // Always initiate a responder renegotiate since the new m-line is added to remote SDP.
2249
-            this._responderRenegotiate(remoteDescription)
2182
+            this._renegotiate(remoteSdp.raw)
2250
                 .then(() => {
2183
                 .then(() => {
2251
                     // Replace the tracks on the newly generated transceivers.
2184
                     // Replace the tracks on the newly generated transceivers.
2252
                     for (const track of localTracks) {
2185
                     for (const track of localTracks) {
2318
         const workFunction = finishedCallback => {
2251
         const workFunction = finishedCallback => {
2319
             logger.debug(`${this} replaceTrack worker started. oldTrack = ${oldTrack}, newTrack = ${newTrack}`);
2252
             logger.debug(`${this} replaceTrack worker started. oldTrack = ${oldTrack}, newTrack = ${newTrack}`);
2320
 
2253
 
2321
-            const oldLocalSdp = this.peerconnection.localDescription.sdp;
2322
-
2323
             if (!this.usesUnifiedPlan) {
2254
             if (!this.usesUnifiedPlan) {
2324
                 // NOTE the code below assumes that no more than 1 video track
2255
                 // NOTE the code below assumes that no more than 1 video track
2325
                 // can be added to the peer connection.
2256
                 // can be added to the peer connection.
2362
                     logger.debug(`${this} TPC.replaceTrack finished. shouldRenegotiate = ${
2293
                     logger.debug(`${this} TPC.replaceTrack finished. shouldRenegotiate = ${
2363
                         shouldRenegotiate}, JingleSessionState = ${this.state}`);
2294
                         shouldRenegotiate}, JingleSessionState = ${this.state}`);
2364
 
2295
 
2365
-                    if (shouldRenegotiate
2366
-                        && (oldTrack || newTrack)
2367
-                        && this.state === JingleSessionState.ACTIVE) {
2368
-                        const remoteSdp = this.peerconnection.remoteDescription.sdp;
2369
-                        const remoteDescription = new RTCSessionDescription({
2370
-                            type: 'offer',
2371
-                            sdp: remoteSdp
2372
-                        });
2373
-
2374
-                        // Always initiate a sRD->cA->sLD cycle since renegotiation fails in the following scenario.
2375
-                        // In a p2p call when channelLastN=0, the direction on the video tranceiver is set to
2376
-                        // 'inactive'. At this point, if the user unmutes, the track is replaced on the video sender.
2377
-                        // If a cO->sLD->sRD is triggered, the browser adds a third m-line which isn't expected and
2378
-                        // possibly is a bug. All renegotiations fail as a result. However, the browser does not add a
2379
-                        // third m-line in the answer it generates and renegotiation succeeds.
2380
-                        promise = this._responderRenegotiate(remoteDescription).then(() => {
2381
-                            const newLocalSDP = new SDP(this.peerconnection.localDescription.sdp);
2382
-
2383
-                            this.notifyMySSRCUpdate(new SDP(oldLocalSdp), newLocalSDP);
2384
-                        });
2296
+                    if (shouldRenegotiate && (oldTrack || newTrack) && this.state === JingleSessionState.ACTIVE) {
2297
+                        promise = this._renegotiate();
2385
                     }
2298
                     }
2386
 
2299
 
2387
                     return promise.then(() => {
2300
                     return promise.then(() => {
2388
                         // Set the source name of the new track.
2301
                         // Set the source name of the new track.
2389
-                        if (oldTrack
2390
-                            && newTrack
2391
-                            && oldTrack.isVideoTrack()) {
2302
+                        if (oldTrack && newTrack && oldTrack.isVideoTrack()) {
2392
                             newTrack.setSourceName(oldTrack.getSourceName());
2303
                             newTrack.setSourceName(oldTrack.getSourceName());
2393
                         }
2304
                         }
2394
                     });
2305
                     });

Načítá se…
Zrušit
Uložit