瀏覽代碼

fix(codec-selection) Apply codec preferences to initial offer/answer.

This fixes an issue where p2p clients (with different codec preferences) fail to decode video because the negotiated codecs are removed from the supported codecs list after the media session is established. The codec preferences will be applied when the first offer/answer is created.
master
Jaya Allamsetty 2 年之前
父節點
當前提交
5155e55021
共有 4 個文件被更改,包括 45 次插入48 次删除
  1. 15
    0
      JitsiConference.js
  2. 0
    3
      modules/RTC/CodecSelection.js
  3. 29
    45
      modules/RTC/TraceablePeerConnection.js
  4. 1
    0
      modules/xmpp/JingleSessionPC.js

+ 15
- 0
JitsiConference.js 查看文件

@@ -2254,6 +2254,11 @@ JitsiConference.prototype._acceptJvbIncomingCall = function(jingleSession, jingl
2254 2254
             this._signalingLayer,
2255 2255
             {
2256 2256
                 ...this.options.config,
2257
+                codecSettings: {
2258
+                    mediaType: MediaType.VIDEO,
2259
+                    preferred: this.codecSelection.jvbPreferredCodec,
2260
+                    disabled: this.codecSelection.jvbDisabledCodec
2261
+                },
2257 2262
                 enableInsertableStreams: this.isE2EEEnabled() || FeatureFlags.isRunInLiteModeEnabled()
2258 2263
             });
2259 2264
     } catch (error) {
@@ -3033,6 +3038,11 @@ JitsiConference.prototype._acceptP2PIncomingCall = function(jingleSession, jingl
3033 3038
         this._signalingLayer,
3034 3039
         {
3035 3040
             ...this.options.config,
3041
+            codecSettings: {
3042
+                mediaType: MediaType.VIDEO,
3043
+                preferred: this.codecSelection.p2pPreferredCodec,
3044
+                disabled: this.codecSelection.p2pDisabledCodec
3045
+            },
3036 3046
             enableInsertableStreams: this.isE2EEEnabled() || FeatureFlags.isRunInLiteModeEnabled()
3037 3047
         });
3038 3048
 
@@ -3396,6 +3406,11 @@ JitsiConference.prototype._startP2PSession = function(remoteJid) {
3396 3406
         this._signalingLayer,
3397 3407
         {
3398 3408
             ...this.options.config,
3409
+            codecSettings: {
3410
+                mediaType: MediaType.VIDEO,
3411
+                preferred: this.codecSelection.p2pPreferredCodec,
3412
+                disabled: this.codecSelection.p2pDisabledCodec
3413
+            },
3399 3414
             enableInsertableStreams: this.isE2EEEnabled() || FeatureFlags.isRunInLiteModeEnabled()
3400 3415
         });
3401 3416
 

+ 0
- 3
modules/RTC/CodecSelection.js 查看文件

@@ -62,9 +62,6 @@ export class CodecSelection {
62 62
         this.conference.on(
63 63
             JitsiConferenceEvents.USER_LEFT,
64 64
             () => this._selectPreferredCodec());
65
-        this.conference.on(
66
-            JitsiConferenceEvents._MEDIA_SESSION_STARTED,
67
-            session => this._selectPreferredCodec(session));
68 65
     }
69 66
 
70 67
     /**

+ 29
- 45
modules/RTC/TraceablePeerConnection.js 查看文件

@@ -253,6 +253,11 @@ export default function TraceablePeerConnection(
253 253
     */
254 254
     this._usesUnifiedPlan = options.usesUnifiedPlan;
255 255
 
256
+    /**
257
+     * Codec preferences set for the peerconnection through config.js.
258
+     */
259
+    this.codecSettings = this.options.codecSettings;
260
+
256 261
     /**
257 262
      * Flag used to indicate if RTCRtpTransceiver#setCodecPreferences is to be used instead of SDP
258 263
      * munging for codec selection.
@@ -1617,31 +1622,27 @@ TraceablePeerConnection.prototype._isSharingScreen = function() {
1617 1622
  * @returns {RTCSessionDescription} the munged description.
1618 1623
  */
1619 1624
 TraceablePeerConnection.prototype._mungeCodecOrder = function(description) {
1620
-    if (!this.codecPreference) {
1621
-        return description;
1622
-    }
1623
-
1624 1625
     const parsedSdp = transform.parse(description.sdp);
1625
-    const mLines = parsedSdp.media.filter(m => m.type === this.codecPreference.mediaType);
1626
+    const mLines = parsedSdp.media.filter(m => m.type === this.codecSettings.mediaType);
1626 1627
 
1627 1628
     if (!mLines.length) {
1628 1629
         return description;
1629 1630
     }
1630 1631
 
1631 1632
     for (const mLine of mLines) {
1632
-        if (this.codecPreference.disabledCodecMimeType) {
1633
-            SDPUtil.stripCodec(mLine, this.codecPreference.disabledCodecMimeType);
1633
+        if (this.codecSettings.disabled) {
1634
+            SDPUtil.stripCodec(mLine, this.codecSettings.disabled);
1634 1635
         }
1635 1636
 
1636
-        if (this.codecPreference.mimeType !== this.codecPreference.disabledCodecMimeType) {
1637
-            SDPUtil.preferCodec(mLine, this.codecPreference.mimeType);
1637
+        if (this.codecSettings.preferred) {
1638
+            SDPUtil.preferCodec(mLine, this.codecSettings.preferred);
1638 1639
 
1639 1640
             // Strip the high profile H264 codecs on mobile clients for p2p connection. High profile codecs give better
1640 1641
             // quality at the expense of higher load which we do not want on mobile clients. Jicofo offers only the
1641 1642
             // baseline code for the jvb connection and therefore this is not needed for jvb connection.
1642 1643
             // TODO - add check for mobile browsers once js-utils provides that check.
1643
-            if (this.codecPreference.mimeType === CodecMimeType.H264 && browser.isReactNative() && this.isP2P) {
1644
-                SDPUtil.stripCodec(mLine, this.codecPreference.mimeType, true /* high profile */);
1644
+            if (this.codecSettings.preferred === CodecMimeType.H264 && browser.isReactNative() && this.isP2P) {
1645
+                SDPUtil.stripCodec(mLine, this.codecSettings.preferred, true /* high profile */);
1645 1646
             }
1646 1647
         }
1647 1648
     }
@@ -1883,21 +1884,9 @@ TraceablePeerConnection.prototype.setDesktopSharingFrameRate = function(maxFps)
1883 1884
  * @param {CodecMimeType} disabledCodec the codec that needs to be disabled.
1884 1885
  * @returns {void}
1885 1886
  */
1886
-TraceablePeerConnection.prototype.setVideoCodecs = function(preferredCodec = null, disabledCodec = null) {
1887
-    // If both enable and disable are set, disable settings will prevail.
1888
-    if (this.codecPreference && (preferredCodec || disabledCodec)) {
1889
-        this.codecPreference.mimeType = preferredCodec;
1890
-        this.codecPreference.disabledCodecMimeType = disabledCodec;
1891
-    } else if (preferredCodec || disabledCodec) {
1892
-        this.codecPreference = {
1893
-            mediaType: MediaType.VIDEO,
1894
-            mimeType: preferredCodec,
1895
-            disabledCodecMimeType: disabledCodec
1896
-        };
1897
-    } else {
1898
-        logger.warn(`${this} Invalid codec settings[preferred=${preferredCodec},disabled=${disabledCodec}],
1899
-            atleast one value is needed`);
1900
-    }
1887
+TraceablePeerConnection.prototype.setVideoCodecs = function(preferredCodec, disabledCodec) {
1888
+    preferredCodec && (this.codecSettings.preferred = preferredCodec);
1889
+    disabledCodec && (this.codecSettings.disabled = disabledCodec);
1901 1890
 };
1902 1891
 
1903 1892
 /**
@@ -2391,10 +2380,6 @@ TraceablePeerConnection.prototype._initializeDtlsTransport = function() {
2391 2380
  * @returns RTCSessionDescription
2392 2381
  */
2393 2382
 TraceablePeerConnection.prototype._setVp9MaxBitrates = function(description, isLocalSdp = false) {
2394
-    if (!this.codecPreference) {
2395
-        return description;
2396
-    }
2397
-
2398 2383
     const parsedSdp = transform.parse(description.sdp);
2399 2384
 
2400 2385
     // Find all the m-lines associated with the local sources.
@@ -2402,7 +2387,7 @@ TraceablePeerConnection.prototype._setVp9MaxBitrates = function(description, isL
2402 2387
     const mLines = parsedSdp.media.filter(m => m.type === MediaType.VIDEO && m.direction !== direction);
2403 2388
 
2404 2389
     for (const mLine of mLines) {
2405
-        if (this.codecPreference.mimeType === CodecMimeType.VP9) {
2390
+        if (this.codecSettings.preferred === CodecMimeType.VP9) {
2406 2391
             const bitrates = this.tpcUtils.videoBitrates.VP9 || this.tpcUtils.videoBitrates;
2407 2392
             const hdBitrate = bitrates.high ? bitrates.high : HD_BITRATE;
2408 2393
             const ssHdBitrate = bitrates.ssHigh ? bitrates.ssHigh : HD_BITRATE;
@@ -2943,39 +2928,38 @@ TraceablePeerConnection.prototype._createOfferOrAnswer = function(
2943 2928
     // Set the codec preference before creating an offer or answer so that the generated SDP will have
2944 2929
     // the correct preference order.
2945 2930
     if (this._usesTransceiverCodecPreferences) {
2946
-        const transceiver = this.peerconnection.getTransceivers()
2947
-            .find(t => t.receiver && t.receiver?.track?.kind === MediaType.VIDEO);
2931
+        const { mediaType } = this.codecSettings;
2932
+        const transceivers = this.peerconnection.getTransceivers()
2933
+            .filter(t => t.receiver && t.receiver?.track?.kind === mediaType);
2948 2934
 
2949
-        if (transceiver) {
2950
-            let capabilities = RTCRtpReceiver.getCapabilities(MediaType.VIDEO)?.codecs;
2951
-            const disabledCodecMimeType = this.codecPreference?.disabledCodecMimeType;
2952
-            const mimeType = this.codecPreference?.mimeType;
2935
+        if (transceivers.length) {
2936
+            let capabilities = RTCRtpReceiver.getCapabilities(mediaType)?.codecs;
2937
+            const disabledCodecMimeType = this.codecSettings?.disabled;
2938
+            const preferredCodecMimeType = this.codecSettings?.preferred;
2953 2939
 
2954 2940
             if (capabilities && disabledCodecMimeType) {
2955 2941
                 capabilities = capabilities
2956
-                    .filter(caps => caps.mimeType.toLowerCase() !== `${MediaType.VIDEO}/${disabledCodecMimeType}`);
2942
+                    .filter(caps => caps.mimeType.toLowerCase() !== `${mediaType}/${disabledCodecMimeType}`);
2957 2943
             }
2958 2944
 
2959
-            if (capabilities && mimeType && mimeType !== disabledCodecMimeType) {
2945
+            if (capabilities && preferredCodecMimeType) {
2960 2946
                 // Move the desired codec (all variations of it as well) to the beginning of the list.
2961 2947
                 /* eslint-disable-next-line arrow-body-style */
2962 2948
                 capabilities.sort(caps => {
2963
-                    return caps.mimeType.toLowerCase() === `${MediaType.VIDEO}/${mimeType}` ? -1 : 1;
2949
+                    return caps.mimeType.toLowerCase() === `${mediaType}/${preferredCodecMimeType}` ? -1 : 1;
2964 2950
                 });
2965 2951
             }
2966 2952
 
2967 2953
             // Disable ulpfec on Google Chrome and derivatives because
2968 2954
             // https://bugs.chromium.org/p/chromium/issues/detail?id=1276427
2969
-            if (browser.isChromiumBased()) {
2955
+            if (browser.isChromiumBased() && mediaType === MediaType.VIDEO) {
2970 2956
                 capabilities = capabilities
2971 2957
                     .filter(caps => caps.mimeType.toLowerCase() !== `${MediaType.VIDEO}/${CodecMimeType.ULPFEC}`);
2972 2958
             }
2973 2959
 
2974
-            try {
2960
+            // Apply codec preference to all the transceivers associated with the given media type.
2961
+            for (const transceiver of transceivers) {
2975 2962
                 transceiver.setCodecPreferences(capabilities);
2976
-            } catch (err) {
2977
-                logger.warn(`${this} Setting codec[preference=${mimeType},disabledCodecMimeType=${
2978
-                    disabledCodecMimeType}] failed`, err);
2979 2963
             }
2980 2964
         }
2981 2965
     }

+ 1
- 0
modules/xmpp/JingleSessionPC.js 查看文件

@@ -400,6 +400,7 @@ export default class JingleSessionPC extends JingleSession {
400 400
             pcOptions.maxstats = DEFAULT_MAX_STATS;
401 401
         }
402 402
         pcOptions.capScreenshareBitrate = false;
403
+        pcOptions.codecSettings = options.codecSettings;
403 404
         pcOptions.enableInsertableStreams = options.enableInsertableStreams;
404 405
         pcOptions.videoQuality = options.videoQuality;
405 406
         pcOptions.forceTurnRelay = options.forceTurnRelay;

Loading…
取消
儲存