Procházet zdrojové kódy

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 před 2 roky
rodič
revize
5155e55021

+ 15
- 0
JitsiConference.js Zobrazit soubor

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

+ 0
- 3
modules/RTC/CodecSelection.js Zobrazit soubor

62
         this.conference.on(
62
         this.conference.on(
63
             JitsiConferenceEvents.USER_LEFT,
63
             JitsiConferenceEvents.USER_LEFT,
64
             () => this._selectPreferredCodec());
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 Zobrazit soubor

253
     */
253
     */
254
     this._usesUnifiedPlan = options.usesUnifiedPlan;
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
      * Flag used to indicate if RTCRtpTransceiver#setCodecPreferences is to be used instead of SDP
262
      * Flag used to indicate if RTCRtpTransceiver#setCodecPreferences is to be used instead of SDP
258
      * munging for codec selection.
263
      * munging for codec selection.
1617
  * @returns {RTCSessionDescription} the munged description.
1622
  * @returns {RTCSessionDescription} the munged description.
1618
  */
1623
  */
1619
 TraceablePeerConnection.prototype._mungeCodecOrder = function(description) {
1624
 TraceablePeerConnection.prototype._mungeCodecOrder = function(description) {
1620
-    if (!this.codecPreference) {
1621
-        return description;
1622
-    }
1623
-
1624
     const parsedSdp = transform.parse(description.sdp);
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
     if (!mLines.length) {
1628
     if (!mLines.length) {
1628
         return description;
1629
         return description;
1629
     }
1630
     }
1630
 
1631
 
1631
     for (const mLine of mLines) {
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
             // Strip the high profile H264 codecs on mobile clients for p2p connection. High profile codecs give better
1640
             // Strip the high profile H264 codecs on mobile clients for p2p connection. High profile codecs give better
1640
             // quality at the expense of higher load which we do not want on mobile clients. Jicofo offers only the
1641
             // quality at the expense of higher load which we do not want on mobile clients. Jicofo offers only the
1641
             // baseline code for the jvb connection and therefore this is not needed for jvb connection.
1642
             // baseline code for the jvb connection and therefore this is not needed for jvb connection.
1642
             // TODO - add check for mobile browsers once js-utils provides that check.
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
  * @param {CodecMimeType} disabledCodec the codec that needs to be disabled.
1884
  * @param {CodecMimeType} disabledCodec the codec that needs to be disabled.
1884
  * @returns {void}
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
  * @returns RTCSessionDescription
2380
  * @returns RTCSessionDescription
2392
  */
2381
  */
2393
 TraceablePeerConnection.prototype._setVp9MaxBitrates = function(description, isLocalSdp = false) {
2382
 TraceablePeerConnection.prototype._setVp9MaxBitrates = function(description, isLocalSdp = false) {
2394
-    if (!this.codecPreference) {
2395
-        return description;
2396
-    }
2397
-
2398
     const parsedSdp = transform.parse(description.sdp);
2383
     const parsedSdp = transform.parse(description.sdp);
2399
 
2384
 
2400
     // Find all the m-lines associated with the local sources.
2385
     // Find all the m-lines associated with the local sources.
2402
     const mLines = parsedSdp.media.filter(m => m.type === MediaType.VIDEO && m.direction !== direction);
2387
     const mLines = parsedSdp.media.filter(m => m.type === MediaType.VIDEO && m.direction !== direction);
2403
 
2388
 
2404
     for (const mLine of mLines) {
2389
     for (const mLine of mLines) {
2405
-        if (this.codecPreference.mimeType === CodecMimeType.VP9) {
2390
+        if (this.codecSettings.preferred === CodecMimeType.VP9) {
2406
             const bitrates = this.tpcUtils.videoBitrates.VP9 || this.tpcUtils.videoBitrates;
2391
             const bitrates = this.tpcUtils.videoBitrates.VP9 || this.tpcUtils.videoBitrates;
2407
             const hdBitrate = bitrates.high ? bitrates.high : HD_BITRATE;
2392
             const hdBitrate = bitrates.high ? bitrates.high : HD_BITRATE;
2408
             const ssHdBitrate = bitrates.ssHigh ? bitrates.ssHigh : HD_BITRATE;
2393
             const ssHdBitrate = bitrates.ssHigh ? bitrates.ssHigh : HD_BITRATE;
2943
     // Set the codec preference before creating an offer or answer so that the generated SDP will have
2928
     // Set the codec preference before creating an offer or answer so that the generated SDP will have
2944
     // the correct preference order.
2929
     // the correct preference order.
2945
     if (this._usesTransceiverCodecPreferences) {
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
             if (capabilities && disabledCodecMimeType) {
2940
             if (capabilities && disabledCodecMimeType) {
2955
                 capabilities = capabilities
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
                 // Move the desired codec (all variations of it as well) to the beginning of the list.
2946
                 // Move the desired codec (all variations of it as well) to the beginning of the list.
2961
                 /* eslint-disable-next-line arrow-body-style */
2947
                 /* eslint-disable-next-line arrow-body-style */
2962
                 capabilities.sort(caps => {
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
             // Disable ulpfec on Google Chrome and derivatives because
2953
             // Disable ulpfec on Google Chrome and derivatives because
2968
             // https://bugs.chromium.org/p/chromium/issues/detail?id=1276427
2954
             // https://bugs.chromium.org/p/chromium/issues/detail?id=1276427
2969
-            if (browser.isChromiumBased()) {
2955
+            if (browser.isChromiumBased() && mediaType === MediaType.VIDEO) {
2970
                 capabilities = capabilities
2956
                 capabilities = capabilities
2971
                     .filter(caps => caps.mimeType.toLowerCase() !== `${MediaType.VIDEO}/${CodecMimeType.ULPFEC}`);
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
                 transceiver.setCodecPreferences(capabilities);
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 Zobrazit soubor

400
             pcOptions.maxstats = DEFAULT_MAX_STATS;
400
             pcOptions.maxstats = DEFAULT_MAX_STATS;
401
         }
401
         }
402
         pcOptions.capScreenshareBitrate = false;
402
         pcOptions.capScreenshareBitrate = false;
403
+        pcOptions.codecSettings = options.codecSettings;
403
         pcOptions.enableInsertableStreams = options.enableInsertableStreams;
404
         pcOptions.enableInsertableStreams = options.enableInsertableStreams;
404
         pcOptions.videoQuality = options.videoQuality;
405
         pcOptions.videoQuality = options.videoQuality;
405
         pcOptions.forceTurnRelay = options.forceTurnRelay;
406
         pcOptions.forceTurnRelay = options.forceTurnRelay;

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