123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
-
- import { getLogger } from 'jitsi-meet-logger';
-
- import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
- import CodecMimeType from '../../service/RTC/CodecMimeType';
- import * as MediaType from '../../service/RTC/MediaType';
- import browser from '../browser';
-
- const logger = getLogger(__filename);
-
- /**
- * This class handles the codec selection mechanism for the conference based on the config.js settings.
- * The preferred codec is selected based on the settings and the list of codecs supported by the browser.
- * The preferred codec is published in presence which is then used by the other endpoints in the
- * conference to pick a supported codec at join time and when the call transitions between p2p and jvb
- * connections.
- */
- export class CodecSelection {
- /**
- * Creates a new instance for a given conference.
- *
- * @param {JitsiConference} conference the conference instance
- * @param {*} options
- * @param {string} options.disabledCodec the codec that needs to be disabled.
- * @param {boolean} options.enforcePreferredCodec whether codec preference has to be
- * enforced even when an endpoints that doesn't support the preferred codec joins the call.
- * Falling back to the standard codec will be skipped when this option is true, endpoints
- * that do not support the preferred codec may not be able to encode/decode video when this happens.
- * @param {string} options.jvbCodec the codec that is preferred on jvb connection.
- * @param {string} options.p2pCodec the codec that is preferred on p2p connection.
- */
- constructor(conference, options) {
- this.conference = conference;
- this.options = options;
-
- // VP8 cannot be disabled and it will be the default codec when no preference is set.
- this.disabledCodec = options.disabledCodec === CodecMimeType.VP8
- ? undefined
- : this._getCodecMimeType(options.disabledCodec);
-
- // Check if the codec values passed are valid.
- const jvbCodec = this._getCodecMimeType(options.jvbCodec);
- const p2pCodec = this._getCodecMimeType(options.p2pCodec);
-
- this.jvbPreferredCodec = jvbCodec && this._isCodecSupported(jvbCodec) ? jvbCodec : CodecMimeType.VP8;
- this.p2pPreferredCodec = p2pCodec && this._isCodecSupported(p2pCodec) ? p2pCodec : CodecMimeType.VP8;
- logger.debug(`Codec preferences for the conference are JVB: ${this.jvbPreferredCodec},
- P2P: ${this.p2pPreferredCodec}`);
-
- if (this.jvbPreferredCodec === CodecMimeType.VP9 && !browser.supportsVP9()) {
- this.jvbPreferredCodec = CodecMimeType.VP8;
- }
-
- this.conference.on(
- JitsiConferenceEvents.USER_JOINED,
- () => this._selectPreferredCodec());
- this.conference.on(
- JitsiConferenceEvents.USER_LEFT,
- () => this._selectPreferredCodec());
- this.conference.on(
- JitsiConferenceEvents._MEDIA_SESSION_STARTED,
- session => this._onMediaSessionStared(session));
- }
-
- /**
- * Checks if a given string is a valid video codec mime type.
- *
- * @param {string} codec the codec string that needs to be validated.
- * @returns {CodecMimeType|null} mime type if valid, null otherwise.
- * @private
- */
- _getCodecMimeType(codec) {
- if (typeof codec === 'string') {
- return Object.values(CodecMimeType).find(value => value === codec.toLowerCase());
- }
-
- return null;
- }
-
- /**
- * Checks if the given codec is supported by the browser.
- *
- * @param {CodecMimeType} preferredCodec codec to be checked.
- * @returns {boolean} true if the given codec is supported, false otherwise.
- * @private
- */
- _isCodecSupported(preferredCodec) {
- // Skip the check on FF and RN because they do not support the getCapabilities API.
- // It is safe to assume both of them support all the codecs supported by Chrome.
- if (browser.isFirefox() || browser.isReactNative()) {
- return true;
- }
-
- return window.RTCRtpReceiver
- && window.RTCRtpReceiver.getCapabilities
- && window.RTCRtpReceiver.getCapabilities('video').codecs
- .some(codec => codec.mimeType.toLowerCase() === `video/${preferredCodec}`);
- }
-
- /**
- * Handles the {@link JitsiConferenceEvents._MEDIA_SESSION_STARTED} event. Codecs need to be
- * configured on the media session that is newly created.
- *
- * @param {JingleSessionPC} mediaSession media session that started.
- * @returns {void}
- * @private
- */
- _onMediaSessionStared(mediaSession) {
- const preferredCodec = mediaSession.isP2P ? this.p2pPreferredCodec : this.jvbPreferredCodec;
- const disabledCodec = this.disabledCodec && this._isCodecSupported(this.disabledCodec)
- ? this.disabledCodec
- : null;
-
- this._selectPreferredCodec(mediaSession, preferredCodec, disabledCodec);
- }
-
- /**
- * Sets the codec on the media session based on the preferred codec setting and the supported codecs
- * published by the remote participants in their presence.
- *
- * @param {JingleSessionPC} mediaSession session for which the codec selection has to be made.
- * @param {CodecMimeType} preferredCodec preferred codec.
- * @param {CodecMimeType} disabledCodec codec that needs to be disabled.
- */
- _selectPreferredCodec(mediaSession = null, preferredCodec = null, disabledCodec = null) {
- const session = mediaSession ? mediaSession : this.conference.jvbJingleSession;
- const currentCodec = preferredCodec ? preferredCodec : this.jvbPreferredCodec;
- let selectedCodec = currentCodec;
-
- if (session && !session.isP2P && !this.options.enforcePreferredCodec) {
- const remoteParticipants = this.conference.getParticipants().map(participant => participant.getId());
-
- for (const remote of remoteParticipants) {
- const peerMediaInfo = session._signalingLayer.getPeerMediaInfo(remote, MediaType.VIDEO);
- const peerCodec = peerMediaInfo?.codecType;
-
- if (peerCodec
- && peerCodec !== currentCodec
- && (peerCodec !== CodecMimeType.VP9 || browser.supportsVP9())) {
- selectedCodec = peerCodec;
- }
- }
- }
- session && session.setVideoCodecs(selectedCodec, disabledCodec);
- }
-
- /**
- * Returns the preferred codec for the conference. The preferred codec for the JVB media session
- * is the one that gets published in presence and a comparision is made whenever a participant joins
- * or leaves the call.
- *
- * @returns {CodecMimeType} preferred codec.
- */
- getPreferredCodec() {
- return this.jvbPreferredCodec;
- }
- }
|