Browse Source

fix(codec-selection): Fix VP9 codec switching issue in Chrome unified-plan.

Munge only the m-line that corresponds to the source that the browser will be sending.
Do not select VP9 on Firefox.
Detect support for RTCRtpTransceiver#setCodecPreferences correctly.
dev1
Jaya Allamsetty 4 years ago
parent
commit
3a313a244d

+ 10
- 5
modules/RTC/CodecSelection.js View File

@@ -126,17 +126,22 @@ export class CodecSelection {
126 126
      */
127 127
     _selectPreferredCodec(mediaSession = null, preferredCodec = null, disabledCodec = null) {
128 128
         const session = mediaSession ? mediaSession : this.conference.jvbJingleSession;
129
-        const codec = preferredCodec ? preferredCodec : this.jvbPreferredCodec;
130
-        let selectedCodec = codec;
129
+        const currentCodec = preferredCodec ? preferredCodec : this.jvbPreferredCodec;
130
+        let selectedCodec = currentCodec;
131 131
 
132 132
         if (session && !session.isP2P && !this.options.enforcePreferredCodec) {
133 133
             const remoteParticipants = this.conference.getParticipants().map(participant => participant.getId());
134 134
 
135 135
             for (const remote of remoteParticipants) {
136 136
                 const peerMediaInfo = session.signalingLayer.getPeerMediaInfo(remote, MediaType.VIDEO);
137
-
138
-                if (peerMediaInfo && peerMediaInfo.codecType && peerMediaInfo.codecType !== codec) {
139
-                    selectedCodec = peerMediaInfo.codecType;
137
+                const peerCodec = peerMediaInfo?.codecType;
138
+
139
+                // We do not want Firefox to switch to VP9 because of the following bug.
140
+                // https://bugzilla.mozilla.org/show_bug.cgi?id=1492500.
141
+                if (peerCodec
142
+                    && peerCodec !== currentCodec
143
+                    && !(browser.isFirefox() && peerCodec === CodecMimeType.VP9)) {
144
+                    selectedCodec = peerCodec;
140 145
                 }
141 146
             }
142 147
         }

+ 50
- 42
modules/RTC/TraceablePeerConnection.js View File

@@ -1608,48 +1608,54 @@ TraceablePeerConnection.prototype._isSharingScreen = function() {
1608 1608
  * @returns {RTCSessionDescription} the munged description.
1609 1609
  */
1610 1610
 TraceablePeerConnection.prototype._mungeCodecOrder = function(description) {
1611
-    if (!this.codecPreference || this._usesTransceiverCodecPreferences) {
1611
+    if (!this.codecPreference) {
1612 1612
         return description;
1613 1613
     }
1614 1614
 
1615 1615
     const parsedSdp = transform.parse(description.sdp);
1616 1616
 
1617
-    for (const mLine of parsedSdp.media) {
1618
-        if (this.codecPreference.enable && mLine.type === this.codecPreference.mediaType) {
1619
-            SDPUtil.preferCodec(mLine, this.codecPreference.mimeType);
1620
-
1621
-            // Strip the high profile H264 codecs on mobile clients for p2p connection.
1622
-            // High profile codecs give better quality at the expense of higher load which
1623
-            // we do not want on mobile clients.
1624
-            // Jicofo offers only the baseline code for the jvb connection.
1625
-            // TODO - add check for mobile browsers once js-utils provides that check.
1626
-            if (this.codecPreference.mimeType === CodecMimeType.H264 && browser.isReactNative() && this.isP2P) {
1627
-                SDPUtil.stripCodec(mLine, this.codecPreference.mimeType, true /* high profile */);
1628
-            }
1617
+    // Only the m-line that defines the source the browser will be sending should need to change.
1618
+    // This is typically the first m-line with the matching media type.
1619
+    const mLine = parsedSdp.media.find(m => m.type === this.codecPreference.mediaType);
1629 1620
 
1630
-            // Set the max bitrate here on the SDP so that the configured max. bitrate is effective
1631
-            // as soon as the browser switches to VP9.
1632
-            if (this.codecPreference.mimeType === CodecMimeType.VP9) {
1633
-                const bitrates = this.videoBitrates.VP9 || this.videoBitrates;
1634
-                const hdBitrate = bitrates.high ? bitrates.high : HD_BITRATE;
1635
-                const limit = Math.floor((this._isSharingScreen() ? HD_BITRATE : hdBitrate) / 1000);
1636
-
1637
-                // Use only the HD bitrate for now as there is no API available yet for configuring
1638
-                // the bitrates on the individual SVC layers.
1639
-                mLine.bandwidth = [ {
1640
-                    type: 'AS',
1641
-                    limit
1642
-                } ];
1643
-            } else {
1644
-                // Clear the bandwidth limit in SDP when VP9 is no longer the preferred codec.
1645
-                // This is needed on react native clients as react-native-webrtc returns the
1646
-                // SDP that the application passed instead of returning the SDP off the native side.
1647
-                // This line automatically gets cleared on web on every renegotiation.
1648
-                mLine.bandwidth = undefined;
1649
-            }
1650
-        } else if (mLine.type === this.codecPreference.mediaType) {
1651
-            SDPUtil.stripCodec(mLine, this.codecPreference.mimeType);
1621
+    if (!mLine) {
1622
+        return description;
1623
+    }
1624
+
1625
+    if (this.codecPreference.enable) {
1626
+        SDPUtil.preferCodec(mLine, this.codecPreference.mimeType);
1627
+
1628
+        // Strip the high profile H264 codecs on mobile clients for p2p connection.
1629
+        // High profile codecs give better quality at the expense of higher load which
1630
+        // we do not want on mobile clients.
1631
+        // Jicofo offers only the baseline code for the jvb connection.
1632
+        // TODO - add check for mobile browsers once js-utils provides that check.
1633
+        if (this.codecPreference.mimeType === CodecMimeType.H264 && browser.isReactNative() && this.isP2P) {
1634
+            SDPUtil.stripCodec(mLine, this.codecPreference.mimeType, true /* high profile */);
1635
+        }
1636
+
1637
+        // Set the max bitrate here on the SDP so that the configured max. bitrate is effective
1638
+        // as soon as the browser switches to VP9.
1639
+        if (this.codecPreference.mimeType === CodecMimeType.VP9) {
1640
+            const bitrates = this.videoBitrates.VP9 || this.videoBitrates;
1641
+            const hdBitrate = bitrates.high ? bitrates.high : HD_BITRATE;
1642
+            const limit = Math.floor((this._isSharingScreen() ? HD_BITRATE : hdBitrate) / 1000);
1643
+
1644
+            // Use only the HD bitrate for now as there is no API available yet for configuring
1645
+            // the bitrates on the individual SVC layers.
1646
+            mLine.bandwidth = [ {
1647
+                type: 'AS',
1648
+                limit
1649
+            } ];
1650
+        } else {
1651
+            // Clear the bandwidth limit in SDP when VP9 is no longer the preferred codec.
1652
+            // This is needed on react native clients as react-native-webrtc returns the
1653
+            // SDP that the application passed instead of returning the SDP off the native side.
1654
+            // This line automatically gets cleared on web on every renegotiation.
1655
+            mLine.bandwidth = undefined;
1652 1656
         }
1657
+    } else {
1658
+        SDPUtil.stripCodec(mLine, this.codecPreference.mimeType);
1653 1659
     }
1654 1660
 
1655 1661
     return new RTCSessionDescription({
@@ -2228,9 +2234,6 @@ TraceablePeerConnection.prototype.setLocalDescription = function(description) {
2228 2234
 
2229 2235
     this.trace('setLocalDescription::preTransform', dumpSDP(localSdp));
2230 2236
 
2231
-    // Munge the order of the codecs based on the preferences set through config.js
2232
-    localSdp = this._mungeCodecOrder(localSdp);
2233
-
2234 2237
     // Munge stereo flag and opusMaxAverageBitrate based on config.js
2235 2238
     localSdp = this._mungeOpus(localSdp);
2236 2239
 
@@ -2246,6 +2249,11 @@ TraceablePeerConnection.prototype.setLocalDescription = function(description) {
2246 2249
             dumpSDP(localSdp));
2247 2250
     }
2248 2251
 
2252
+    // Munge the order of the codecs based on the preferences set through config.js if we are using SDP munging.
2253
+    if (!this._usesTransceiverCodecPreferences) {
2254
+        localSdp = this._mungeCodecOrder(localSdp);
2255
+    }
2256
+
2249 2257
     return new Promise((resolve, reject) => {
2250 2258
         this.peerconnection.setLocalDescription(localSdp)
2251 2259
             .then(() => {
@@ -2426,10 +2434,6 @@ TraceablePeerConnection.prototype.setRemoteDescription = function(description) {
2426 2434
     this.trace('setRemoteDescription::preTransform', dumpSDP(description));
2427 2435
 
2428 2436
     /* eslint-disable no-param-reassign */
2429
-
2430
-    // Munge the order of the codecs based on the preferences set through config.js
2431
-    description = this._mungeCodecOrder(description);
2432
-
2433 2437
     // Munge stereo flag and opusMaxAverageBitrate based on config.js
2434 2438
     description = this._mungeOpus(description);
2435 2439
 
@@ -2468,6 +2472,10 @@ TraceablePeerConnection.prototype.setRemoteDescription = function(description) {
2468 2472
         }
2469 2473
     }
2470 2474
 
2475
+    // Munge the order of the codecs based on the preferences set through config.js.
2476
+    // eslint-disable-next-line no-param-reassign
2477
+    description = this._mungeCodecOrder(description);
2478
+
2471 2479
     if (this._usesUnifiedPlan) {
2472 2480
         // eslint-disable-next-line no-param-reassign
2473 2481
         description = this.tpcUtils.ensureCorrectOrderOfSsrcs(description);

+ 1
- 1
modules/browser/BrowserCapabilities.js View File

@@ -132,7 +132,7 @@ export default class BrowserCapabilities extends BrowserDetection {
132 132
      */
133 133
     supportsCodecPreferences() {
134 134
         return Boolean(window.RTCRtpTransceiver
135
-            && typeof window.RTCRtpTransceiver.setCodecPreferences !== 'undefined'
135
+            && 'setCodecPreferences' in window.RTCRtpTransceiver.prototype
136 136
             && window.RTCRtpReceiver
137 137
             && typeof window.RTCRtpReceiver.getCapabilities !== 'undefined')
138 138
 

Loading…
Cancel
Save