|
@@ -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
|
/**
|