Sfoglia il codice sorgente

fix(codec-selection): Codec selection fixes.

1. Checks peer's preferred codec in p2p case. Mobile and web have different preferred codecs.
2. Log an error message when the preferred codec is not offered by JVB.
3. Clean up code related to deprecated config.js settings 'preferH264' and 'disableH264'.
4. Refactor the codec selection logic so that correct codec is picked.
tags/v0.0.2
Jaya Allamsetty 2 anni fa
parent
commit
2d4cd935cb
4 ha cambiato i file con 85 aggiunte e 88 eliminazioni
  1. 20
    11
      JitsiConference.js
  2. 59
    68
      modules/RTC/CodecSelection.js
  3. 2
    0
      modules/sdp/SDPUtil.js
  4. 4
    9
      modules/xmpp/JingleSessionPC.js

+ 20
- 11
JitsiConference.js Vedi File

@@ -80,6 +80,21 @@ const logger = getLogger(__filename);
80 80
  */
81 81
 const JINGLE_SI_TIMEOUT = 5000;
82 82
 
83
+/**
84
+ * Checks if a given string is a valid video codec mime type.
85
+ *
86
+ * @param {string} codec the codec string that needs to be validated.
87
+ * @returns {CodecMimeType|null} mime type if valid, null otherwise.
88
+ * @private
89
+ */
90
+function _getCodecMimeType(codec) {
91
+    if (typeof codec === 'string') {
92
+        return Object.values(CodecMimeType).find(value => value === codec.toLowerCase());
93
+    }
94
+
95
+    return null;
96
+}
97
+
83 98
 /**
84 99
  * Creates a JitsiConference object with the given name and properties.
85 100
  * Note: this constructor is not a part of the public API (objects should be
@@ -355,18 +370,12 @@ JitsiConference.prototype._init = function(options = {}) {
355 370
     const { config } = this.options;
356 371
 
357 372
     // Get the codec preference settings from config.js.
358
-    // 'preferH264' and 'disableH264' settings have been deprecated for a while,
359
-    // 'preferredCodec' and 'disabledCodec' will have precedence over them.
360 373
     const codecSettings = {
361
-        disabledCodec: config.videoQuality
362
-            ? config.videoQuality.disabledCodec
363
-            : config.p2p && config.p2p.disableH264 && CodecMimeType.H264,
364
-        enforcePreferredCodec: config.videoQuality && config.videoQuality.enforcePreferredCodec,
365
-        jvbCodec: (config.videoQuality && config.videoQuality.preferredCodec)
366
-            || (config.preferH264 && CodecMimeType.H264),
367
-        p2pCodec: config.p2p
368
-            ? config.p2p.preferredCodec || (config.p2p.preferH264 && CodecMimeType.H264)
369
-            : CodecMimeType.VP8
374
+        jvbDisabledCodec: _getCodecMimeType(config.videoQuality?.disabledCodec),
375
+        p2pDisabledCodec: _getCodecMimeType(config.p2p?.disabledCodec),
376
+        enforcePreferredCodec: config.videoQuality?.enforcePreferredCodec,
377
+        jvbPreferredCodec: _getCodecMimeType(config.videoQuality?.preferredCodec),
378
+        p2pPreferredCodec: _getCodecMimeType(config.p2p?.preferredCodec)
370 379
     };
371 380
 
372 381
     this.codecSelection = new CodecSelection(this, codecSettings);

+ 59
- 68
modules/RTC/CodecSelection.js Vedi File

@@ -32,24 +32,29 @@ export class CodecSelection {
32 32
     constructor(conference, options) {
33 33
         this.conference = conference;
34 34
         this.options = options;
35
-
36
-        // VP8 cannot be disabled and it will be the default codec when no preference is set.
37
-        this.disabledCodec = options.disabledCodec === CodecMimeType.VP8
38
-            ? undefined
39
-            : this._getCodecMimeType(options.disabledCodec);
40
-
41
-        // Check if the codec values passed are valid.
42
-        const jvbCodec = this._getCodecMimeType(options.jvbCodec);
43
-        const p2pCodec = this._getCodecMimeType(options.p2pCodec);
44
-
45
-        this.jvbPreferredCodec = jvbCodec && this._isCodecSupported(jvbCodec) ? jvbCodec : CodecMimeType.VP8;
46
-        this.p2pPreferredCodec = p2pCodec && this._isCodecSupported(p2pCodec) ? p2pCodec : CodecMimeType.VP8;
47
-        logger.debug(`Codec preferences for the conference are JVB: ${this.jvbPreferredCodec},
48
-            P2P: ${this.p2pPreferredCodec}`);
49
-
50
-        if (this.jvbPreferredCodec === CodecMimeType.VP9 && !browser.supportsVP9()) {
51
-            this.jvbPreferredCodec = CodecMimeType.VP8;
52
-        }
35
+        this.enforcePreferredCodec = options.enforcePreferredCodec;
36
+
37
+        // VP8 cannot be disabled since it the default codec.
38
+        this.p2pDisabledCodec = options.p2pDisabledCodec !== CodecMimeType.VP8
39
+            && this._isCodecSupported(options.p2pDisabledCodec)
40
+            && options.p2pDisabledCodec;
41
+        this.jvbDisabledCodec = options.jvbDisabledCodec !== CodecMimeType.VP8
42
+            && this._isCodecSupported(options.jvbDisabledCodec)
43
+            && options.jvbDisabledCodec;
44
+
45
+        // Determine the preferred codecs.
46
+        this.p2pPreferredCodec = this._isCodecSupported(options.p2pPreferredCodec)
47
+            && options.p2pPreferredCodec !== options.p2pDisabledCodec
48
+            ? options.p2pPreferredCodec
49
+            : CodecMimeType.VP8;
50
+        this.jvbPreferredCodec = this._isCodecSupported(options.jvbPreferredCodec)
51
+            && options.jvbPreferredCodec !== options.jvbDisabledCodec
52
+            ? options.jvbPreferredCodec
53
+            : CodecMimeType.VP8;
54
+
55
+        logger.debug(`Codec preferences for the conference are JVB: preferred=${this.jvbPreferredCodec},`
56
+            + `disabled=${this.jvbDisabledCodec} P2P: preferred=${this.p2pPreferredCodec},`
57
+            + `disabled=${this.p2pDisabledCodec}`);
53 58
 
54 59
         this.conference.on(
55 60
             JitsiConferenceEvents.USER_JOINED,
@@ -59,22 +64,7 @@ export class CodecSelection {
59 64
             () => this._selectPreferredCodec());
60 65
         this.conference.on(
61 66
             JitsiConferenceEvents._MEDIA_SESSION_STARTED,
62
-            session => this._onMediaSessionStarted(session));
63
-    }
64
-
65
-    /**
66
-     * Checks if a given string is a valid video codec mime type.
67
-     *
68
-     * @param {string} codec the codec string that needs to be validated.
69
-     * @returns {CodecMimeType|null} mime type if valid, null otherwise.
70
-     * @private
71
-     */
72
-    _getCodecMimeType(codec) {
73
-        if (typeof codec === 'string') {
74
-            return Object.values(CodecMimeType).find(value => value === codec.toLowerCase());
75
-        }
76
-
77
-        return null;
67
+            session => this._selectPreferredCodec(session));
78 68
     }
79 69
 
80 70
     /**
@@ -85,8 +75,16 @@ export class CodecSelection {
85 75
      * @private
86 76
      */
87 77
     _isCodecSupported(preferredCodec) {
78
+        if (!preferredCodec) {
79
+            return false;
80
+        }
81
+
82
+        if (preferredCodec === CodecMimeType.VP9 && !this.enforcePreferredCodec && !browser.supportsVP9()) {
83
+            return false;
84
+        }
85
+
88 86
         // Skip the check on FF because it does not support the getCapabilities API.
89
-        // It is safe to assume both of them support all the codecs supported by Chrome.
87
+        // It is safe to assume that Firefox supports all the codecs supported by Chrome.
90 88
         if (browser.isFirefox()) {
91 89
             return true;
92 90
         }
@@ -98,50 +96,43 @@ export class CodecSelection {
98 96
     }
99 97
 
100 98
     /**
101
-     * Handles the {@link JitsiConferenceEvents._MEDIA_SESSION_STARTED} event. Codecs need to be
102
-     * configured on the media session that is newly created.
103
-     *
104
-     * @param {JingleSessionPC} mediaSession media session that started.
105
-     * @returns {void}
106
-     * @private
107
-     */
108
-    _onMediaSessionStarted(mediaSession) {
109
-        const preferredCodec = mediaSession.isP2P ? this.p2pPreferredCodec : this.jvbPreferredCodec;
110
-        const disabledCodec = this.disabledCodec && this._isCodecSupported(this.disabledCodec)
111
-            ? this.disabledCodec
112
-            : null;
113
-
114
-        this._selectPreferredCodec(mediaSession, preferredCodec, disabledCodec);
115
-    }
116
-
117
-    /**
118
-     * Sets the codec on the media session based on the preferred codec setting and the supported codecs
99
+     * Sets the codec on the media session based on the preferred/disabled codec setting and the supported codecs
119 100
      * published by the remote participants in their presence.
120 101
      *
121 102
      * @param {JingleSessionPC} mediaSession session for which the codec selection has to be made.
122
-     * @param {CodecMimeType} preferredCodec preferred codec.
123
-     * @param {CodecMimeType} disabledCodec codec that needs to be disabled.
124 103
      */
125
-    _selectPreferredCodec(mediaSession = null, preferredCodec = null, disabledCodec = null) {
104
+    _selectPreferredCodec(mediaSession) {
126 105
         const session = mediaSession ? mediaSession : this.conference.jvbJingleSession;
127
-        const currentCodec = preferredCodec ? preferredCodec : this.jvbPreferredCodec;
128
-        let selectedCodec = currentCodec;
129 106
 
130
-        if (session && !session.isP2P && !this.options.enforcePreferredCodec) {
131
-            const remoteParticipants = this.conference.getParticipants().map(participant => participant.getId());
107
+        if (!session) {
108
+            return;
109
+        }
110
+        const preferredCodec = session.isP2P ? this.p2pPreferredCodec : this.jvbPreferredCodec;
111
+        const disabledCodec = session.isP2P ? this.p2pDisabledCodec : this.jvbDisabledCodec;
112
+        const currentCodec = session?.peerconnection.getConfiguredVideoCodec();
113
+        let selectedCodec = preferredCodec ?? currentCodec;
132 114
 
133
-            for (const remote of remoteParticipants) {
115
+        if (!this.enforcePreferredCodec) {
116
+            const remoteParticipants = this.conference.getParticipants().map(participant => participant.getId());
117
+            const remoteCodecs = remoteParticipants?.map(remote => {
134 118
                 const peerMediaInfo = session._signalingLayer.getPeerMediaInfo(remote, MediaType.VIDEO);
135
-                const peerCodec = peerMediaInfo?.codecType;
136 119
 
137
-                if (peerCodec
138
-                    && peerCodec !== currentCodec
139
-                    && (peerCodec !== CodecMimeType.VP9 || browser.supportsVP9())) {
140
-                    selectedCodec = peerCodec;
141
-                }
120
+                return peerMediaInfo?.codecType;
121
+            });
122
+
123
+            const nonPreferredCodecs = remoteCodecs.filter(codec => codec !== selectedCodec && codec !== disabledCodec);
124
+
125
+            // Find the fallback codec when there are endpoints in the call that don't have the same preferred codec
126
+            // set.
127
+            if (nonPreferredCodecs.length) {
128
+                // Always prefer VP8 as that is the default codec supported on all client types.
129
+                selectedCodec = nonPreferredCodecs.find(codec => codec === CodecMimeType.VP8)
130
+                    ?? nonPreferredCodecs.find(codec => this._isCodecSupported(codec));
142 131
             }
143 132
         }
144
-        session && session.setVideoCodecs(selectedCodec, disabledCodec);
133
+        if (selectedCodec !== currentCodec || disabledCodec) {
134
+            session.setVideoCodecs(selectedCodec, disabledCodec);
135
+        }
145 136
     }
146 137
 
147 138
     /**

+ 2
- 0
modules/sdp/SDPUtil.js Vedi File

@@ -645,6 +645,8 @@ const SDPUtil = {
645 645
                 payloadTypes.unshift(pt);
646 646
             }
647 647
             mline.payloads = payloadTypes.join(' ');
648
+        } else {
649
+            logger.error(`No matching RTP payload type found for ${codecName}, failed to set preferred codecs`);
648 650
         }
649 651
     },
650 652
 

+ 4
- 9
modules/xmpp/JingleSessionPC.js Vedi File

@@ -90,7 +90,6 @@ function _addSourceElement(description, s, ssrc_, msid) {
90 90
  * @property {Object} abTesting - A/B testing related options (ask George).
91 91
  * @property {boolean} abTesting.enableSuspendVideoTest - enables the suspend
92 92
  * video test ?(ask George).
93
- * @property {boolean} disableH264 - Described in the config.js[1].
94 93
  * @property {boolean} disableRtx - Described in the config.js[1].
95 94
  * @property {boolean} disableSimulcast - Described in the config.js[1].
96 95
  * @property {boolean} enableInsertableStreams - Set to true when the insertable streams constraints is to be enabled
@@ -443,11 +442,9 @@ export default class JingleSessionPC extends JingleSession {
443 442
                 pcOptions.abtestSuspendVideo = abtestSuspendVideo;
444 443
             }
445 444
         } else {
446
-            // H264 does not support simulcast, so it needs to be disabled.
445
+            // H264 scalability is not supported on jvb, so simulcast needs to be disabled when H264 is preferred.
447 446
             pcOptions.disableSimulcast
448
-                = options.disableSimulcast
449
-                    || (options.preferH264 && !options.disableH264)
450
-                    || (options.videoQuality && options.videoQuality.preferredCodec === CodecMimeType.H264);
447
+                = options.disableSimulcast || options.videoQuality?.preferredCodec === CodecMimeType.H264;
451 448
 
452 449
             // Disable simulcast for low fps screenshare and enable it for high fps screenshare.
453 450
             // testing.capScreenshareBitrate config.js setting has now been deprecated.
@@ -1285,10 +1282,8 @@ export default class JingleSessionPC extends JingleSession {
1285 1282
      * @param {CodecMimeType} disabled the codec that needs to be disabled.
1286 1283
      */
1287 1284
     setVideoCodecs(preferred = null, disabled = null) {
1288
-        const current = this.peerconnection.getConfiguredVideoCodec();
1289
-
1290
-        if (this._assertNotEnded() && preferred !== current) {
1291
-            logger.info(`${this} Switching video codec from ${current} to ${preferred}`);
1285
+        if (this._assertNotEnded()) {
1286
+            logger.info(`${this} setVideoCodecs: preferred=${preferred}, disabled=${disabled}`);
1292 1287
             this.peerconnection.setVideoCodecs(preferred, disabled);
1293 1288
 
1294 1289
             // Initiate a renegotiate for the codec setting to take effect.

Loading…
Annulla
Salva