ref(video-quality): Move all related code.
This commit is contained in:
parent
651d713206
commit
b02d96231c
|
@ -163,19 +163,6 @@ export const SET_DESKTOP_SHARING_ENABLED
|
||||||
*/
|
*/
|
||||||
export const SET_FOLLOW_ME = 'SET_FOLLOW_ME';
|
export const SET_FOLLOW_ME = 'SET_FOLLOW_ME';
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of (redux) action which sets the maximum video height that should be
|
|
||||||
* received from remote participants, even if the user prefers a larger video
|
|
||||||
* height.
|
|
||||||
*
|
|
||||||
* {
|
|
||||||
* type: SET_MAX_RECEIVER_VIDEO_QUALITY,
|
|
||||||
* maxReceiverVideoQuality: number
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
export const SET_MAX_RECEIVER_VIDEO_QUALITY
|
|
||||||
= 'SET_MAX_RECEIVER_VIDEO_QUALITY';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of (redux) action which sets the password to join or lock a specific
|
* The type of (redux) action which sets the password to join or lock a specific
|
||||||
* {@code JitsiConference}.
|
* {@code JitsiConference}.
|
||||||
|
@ -210,17 +197,6 @@ export const SET_PASSWORD_FAILED = 'SET_PASSWORD_FAILED';
|
||||||
*/
|
*/
|
||||||
export const SET_PENDING_SUBJECT_CHANGE = 'SET_PENDING_SUBJECT_CHANGE';
|
export const SET_PENDING_SUBJECT_CHANGE = 'SET_PENDING_SUBJECT_CHANGE';
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of (redux) action which sets the preferred maximum video height that
|
|
||||||
* should be sent to and received from remote participants.
|
|
||||||
*
|
|
||||||
* {
|
|
||||||
* type: SET_PREFERRED_VIDEO_QUALITY,
|
|
||||||
* preferredVideoQuality: number
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
export const SET_PREFERRED_VIDEO_QUALITY = 'SET_PREFERRED_VIDEO_QUALITY';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of (redux) action which sets the name of the room of the
|
* The type of (redux) action which sets the name of the room of the
|
||||||
* conference to be joined.
|
* conference to be joined.
|
||||||
|
|
|
@ -45,10 +45,8 @@ import {
|
||||||
SEND_TONES,
|
SEND_TONES,
|
||||||
SET_DESKTOP_SHARING_ENABLED,
|
SET_DESKTOP_SHARING_ENABLED,
|
||||||
SET_FOLLOW_ME,
|
SET_FOLLOW_ME,
|
||||||
SET_MAX_RECEIVER_VIDEO_QUALITY,
|
|
||||||
SET_PASSWORD,
|
SET_PASSWORD,
|
||||||
SET_PASSWORD_FAILED,
|
SET_PASSWORD_FAILED,
|
||||||
SET_PREFERRED_VIDEO_QUALITY,
|
|
||||||
SET_ROOM,
|
SET_ROOM,
|
||||||
SET_PENDING_SUBJECT_CHANGE,
|
SET_PENDING_SUBJECT_CHANGE,
|
||||||
SET_START_MUTED_POLICY
|
SET_START_MUTED_POLICY
|
||||||
|
@ -615,23 +613,6 @@ export function setFollowMe(enabled: boolean) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the max frame height that should be received from remote videos.
|
|
||||||
*
|
|
||||||
* @param {number} maxReceiverVideoQuality - The max video frame height to
|
|
||||||
* receive.
|
|
||||||
* @returns {{
|
|
||||||
* type: SET_MAX_RECEIVER_VIDEO_QUALITY,
|
|
||||||
* maxReceiverVideoQuality: number
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
export function setMaxReceiverVideoQuality(maxReceiverVideoQuality: number) {
|
|
||||||
return {
|
|
||||||
type: SET_MAX_RECEIVER_VIDEO_QUALITY,
|
|
||||||
maxReceiverVideoQuality
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the password to join or lock a specific JitsiConference.
|
* Sets the password to join or lock a specific JitsiConference.
|
||||||
*
|
*
|
||||||
|
@ -698,24 +679,6 @@ export function setPassword(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the max frame height the user prefers to send and receive from the
|
|
||||||
* remote participants.
|
|
||||||
*
|
|
||||||
* @param {number} preferredVideoQuality - The max video resolution to send and
|
|
||||||
* receive.
|
|
||||||
* @returns {{
|
|
||||||
* type: SET_PREFERRED_VIDEO_QUALITY,
|
|
||||||
* preferredVideoQuality: number
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
export function setPreferredVideoQuality(preferredVideoQuality: number) {
|
|
||||||
return {
|
|
||||||
type: SET_PREFERRED_VIDEO_QUALITY,
|
|
||||||
preferredVideoQuality
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets (the name of) the room of the conference to be joined.
|
* Sets (the name of) the room of the conference to be joined.
|
||||||
*
|
*
|
||||||
|
|
|
@ -34,15 +34,3 @@ export const EMAIL_COMMAND = 'email';
|
||||||
* from the outside is not cool but it should suffice for now.
|
* from the outside is not cool but it should suffice for now.
|
||||||
*/
|
*/
|
||||||
export const JITSI_CONFERENCE_URL_KEY = Symbol('url');
|
export const JITSI_CONFERENCE_URL_KEY = Symbol('url');
|
||||||
|
|
||||||
/**
|
|
||||||
* The supported remote video resolutions. The values are currently based on
|
|
||||||
* available simulcast layers.
|
|
||||||
*
|
|
||||||
* @type {object}
|
|
||||||
*/
|
|
||||||
export const VIDEO_QUALITY_LEVELS = {
|
|
||||||
HIGH: 720,
|
|
||||||
STANDARD: 360,
|
|
||||||
LOW: 180
|
|
||||||
};
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
PARTICIPANT_UPDATED,
|
PARTICIPANT_UPDATED,
|
||||||
PIN_PARTICIPANT
|
PIN_PARTICIPANT
|
||||||
} from '../participants';
|
} from '../participants';
|
||||||
import { MiddlewareRegistry, StateListenerRegistry } from '../redux';
|
import { MiddlewareRegistry } from '../redux';
|
||||||
import { TRACK_ADDED, TRACK_REMOVED } from '../tracks';
|
import { TRACK_ADDED, TRACK_REMOVED } from '../tracks';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -28,7 +28,6 @@ import {
|
||||||
CONFERENCE_JOINED,
|
CONFERENCE_JOINED,
|
||||||
CONFERENCE_SUBJECT_CHANGED,
|
CONFERENCE_SUBJECT_CHANGED,
|
||||||
CONFERENCE_WILL_LEAVE,
|
CONFERENCE_WILL_LEAVE,
|
||||||
DATA_CHANNEL_OPENED,
|
|
||||||
SEND_TONES,
|
SEND_TONES,
|
||||||
SET_PENDING_SUBJECT_CHANGE,
|
SET_PENDING_SUBJECT_CHANGE,
|
||||||
SET_ROOM
|
SET_ROOM
|
||||||
|
@ -81,9 +80,6 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
_conferenceWillLeave();
|
_conferenceWillLeave();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_CHANNEL_OPENED:
|
|
||||||
return _syncReceiveVideoQuality(store, next, action);
|
|
||||||
|
|
||||||
case PARTICIPANT_UPDATED:
|
case PARTICIPANT_UPDATED:
|
||||||
return _updateLocalParticipantInConference(store, next, action);
|
return _updateLocalParticipantInConference(store, next, action);
|
||||||
|
|
||||||
|
@ -104,31 +100,6 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
return next(action);
|
return next(action);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers a change handler for state['features/base/conference'] to update
|
|
||||||
* the preferred video quality levels based on user preferred and internal
|
|
||||||
* settings.
|
|
||||||
*/
|
|
||||||
StateListenerRegistry.register(
|
|
||||||
/* selector */ state => state['features/base/conference'],
|
|
||||||
/* listener */ (currentState, store, previousState = {}) => {
|
|
||||||
const {
|
|
||||||
conference,
|
|
||||||
maxReceiverVideoQuality,
|
|
||||||
preferredVideoQuality
|
|
||||||
} = currentState;
|
|
||||||
const changedConference = conference !== previousState.conference;
|
|
||||||
const changedPreferredVideoQuality
|
|
||||||
= preferredVideoQuality !== previousState.preferredVideoQuality;
|
|
||||||
const changedMaxVideoQuality = maxReceiverVideoQuality !== previousState.maxReceiverVideoQuality;
|
|
||||||
|
|
||||||
if (changedConference || changedPreferredVideoQuality || changedMaxVideoQuality) {
|
|
||||||
_setReceiverVideoConstraint(conference, preferredVideoQuality, maxReceiverVideoQuality);
|
|
||||||
}
|
|
||||||
if (changedConference || changedPreferredVideoQuality) {
|
|
||||||
_setSenderVideoConstraint(conference, preferredVideoQuality);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes sure to leave a failed conference in order to release any allocated
|
* Makes sure to leave a failed conference in order to release any allocated
|
||||||
|
@ -448,44 +419,6 @@ function _sendTones({ getState }, next, action) {
|
||||||
return next(action);
|
return next(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function for updating the preferred receiver video constraint, based
|
|
||||||
* on the user preference and the internal maximum.
|
|
||||||
*
|
|
||||||
* @param {JitsiConference} conference - The JitsiConference instance for the
|
|
||||||
* current call.
|
|
||||||
* @param {number} preferred - The user preferred max frame height.
|
|
||||||
* @param {number} max - The maximum frame height the application should
|
|
||||||
* receive.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
function _setReceiverVideoConstraint(conference, preferred, max) {
|
|
||||||
if (conference) {
|
|
||||||
const value = Math.min(preferred, max);
|
|
||||||
|
|
||||||
conference.setReceiverVideoConstraint(value);
|
|
||||||
logger.info(`setReceiverVideoConstraint: ${value}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function for updating the preferred sender video constraint, based
|
|
||||||
* on the user preference.
|
|
||||||
*
|
|
||||||
* @param {JitsiConference} conference - The JitsiConference instance for the
|
|
||||||
* current call.
|
|
||||||
* @param {number} preferred - The user preferred max frame height.
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
function _setSenderVideoConstraint(conference, preferred) {
|
|
||||||
if (conference) {
|
|
||||||
conference.setSenderVideoConstraint(preferred)
|
|
||||||
.catch(err => {
|
|
||||||
logger.error(`Changing sender resolution to ${preferred} failed - ${err} `);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the feature base/conference that the action
|
* Notifies the feature base/conference that the action
|
||||||
* {@code SET_ROOM} is being dispatched within a specific
|
* {@code SET_ROOM} is being dispatched within a specific
|
||||||
|
@ -539,33 +472,6 @@ function _syncConferenceLocalTracksWithState({ getState }, action) {
|
||||||
return promise || Promise.resolve();
|
return promise || Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the maximum receive video quality.
|
|
||||||
*
|
|
||||||
* @param {Store} store - The redux store in which the specified {@code action}
|
|
||||||
* is being dispatched.
|
|
||||||
* @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
|
|
||||||
* specified {@code action} to the specified {@code store}.
|
|
||||||
* @param {Action} action - The redux action {@code DATA_CHANNEL_STATUS_CHANGED}
|
|
||||||
* which is being dispatched in the specified {@code store}.
|
|
||||||
* @private
|
|
||||||
* @returns {Object} The value returned by {@code next(action)}.
|
|
||||||
*/
|
|
||||||
function _syncReceiveVideoQuality({ getState }, next, action) {
|
|
||||||
const {
|
|
||||||
conference,
|
|
||||||
maxReceiverVideoQuality,
|
|
||||||
preferredVideoQuality
|
|
||||||
} = getState()['features/base/conference'];
|
|
||||||
|
|
||||||
_setReceiverVideoConstraint(
|
|
||||||
conference,
|
|
||||||
preferredVideoQuality,
|
|
||||||
maxReceiverVideoQuality);
|
|
||||||
|
|
||||||
return next(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the feature base/conference that the action {@code TRACK_ADDED}
|
* Notifies the feature base/conference that the action {@code TRACK_ADDED}
|
||||||
* or {@code TRACK_REMOVED} is being dispatched within a specific redux store.
|
* or {@code TRACK_REMOVED} is being dispatched within a specific redux store.
|
||||||
|
|
|
@ -18,15 +18,12 @@ import {
|
||||||
P2P_STATUS_CHANGED,
|
P2P_STATUS_CHANGED,
|
||||||
SET_DESKTOP_SHARING_ENABLED,
|
SET_DESKTOP_SHARING_ENABLED,
|
||||||
SET_FOLLOW_ME,
|
SET_FOLLOW_ME,
|
||||||
SET_MAX_RECEIVER_VIDEO_QUALITY,
|
|
||||||
SET_PASSWORD,
|
SET_PASSWORD,
|
||||||
SET_PENDING_SUBJECT_CHANGE,
|
SET_PENDING_SUBJECT_CHANGE,
|
||||||
SET_PREFERRED_VIDEO_QUALITY,
|
|
||||||
SET_ROOM,
|
SET_ROOM,
|
||||||
SET_SIP_GATEWAY_ENABLED,
|
SET_SIP_GATEWAY_ENABLED,
|
||||||
SET_START_MUTED_POLICY
|
SET_START_MUTED_POLICY
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
import { VIDEO_QUALITY_LEVELS } from './constants';
|
|
||||||
import { isRoomValid } from './functions';
|
import { isRoomValid } from './functions';
|
||||||
|
|
||||||
const DEFAULT_STATE = {
|
const DEFAULT_STATE = {
|
||||||
|
@ -35,11 +32,9 @@ const DEFAULT_STATE = {
|
||||||
joining: undefined,
|
joining: undefined,
|
||||||
leaving: undefined,
|
leaving: undefined,
|
||||||
locked: undefined,
|
locked: undefined,
|
||||||
maxReceiverVideoQuality: VIDEO_QUALITY_LEVELS.HIGH,
|
|
||||||
membersOnly: undefined,
|
membersOnly: undefined,
|
||||||
password: undefined,
|
password: undefined,
|
||||||
passwordRequired: undefined,
|
passwordRequired: undefined
|
||||||
preferredVideoQuality: VIDEO_QUALITY_LEVELS.HIGH
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,24 +85,12 @@ ReducerRegistry.register(
|
||||||
case SET_LOCATION_URL:
|
case SET_LOCATION_URL:
|
||||||
return set(state, 'room', undefined);
|
return set(state, 'room', undefined);
|
||||||
|
|
||||||
case SET_MAX_RECEIVER_VIDEO_QUALITY:
|
|
||||||
return set(
|
|
||||||
state,
|
|
||||||
'maxReceiverVideoQuality',
|
|
||||||
action.maxReceiverVideoQuality);
|
|
||||||
|
|
||||||
case SET_PASSWORD:
|
case SET_PASSWORD:
|
||||||
return _setPassword(state, action);
|
return _setPassword(state, action);
|
||||||
|
|
||||||
case SET_PENDING_SUBJECT_CHANGE:
|
case SET_PENDING_SUBJECT_CHANGE:
|
||||||
return set(state, 'pendingSubjectChange', action.subject);
|
return set(state, 'pendingSubjectChange', action.subject);
|
||||||
|
|
||||||
case SET_PREFERRED_VIDEO_QUALITY:
|
|
||||||
return set(
|
|
||||||
state,
|
|
||||||
'preferredVideoQuality',
|
|
||||||
action.preferredVideoQuality);
|
|
||||||
|
|
||||||
case SET_ROOM:
|
case SET_ROOM:
|
||||||
return _setRoom(state, action);
|
return _setRoom(state, action);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
* The type of (redux) action which sets the preferred maximum video height that
|
||||||
|
* should be sent to and received from remote participants.
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* type: SET_PREFERRED_VIDEO_QUALITY,
|
||||||
|
* preferredVideoQuality: number
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export const SET_PREFERRED_VIDEO_QUALITY = 'SET_PREFERRED_VIDEO_QUALITY';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of (redux) action which sets the maximum video height that should be
|
||||||
|
* received from remote participants, even if the user prefers a larger video
|
||||||
|
* height.
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* type: SET_MAX_RECEIVER_VIDEO_QUALITY,
|
||||||
|
* maxReceiverVideoQuality: number
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export const SET_MAX_RECEIVER_VIDEO_QUALITY = 'SET_MAX_RECEIVER_VIDEO_QUALITY';
|
|
@ -2,10 +2,45 @@
|
||||||
|
|
||||||
import type { Dispatch } from 'redux';
|
import type { Dispatch } from 'redux';
|
||||||
|
|
||||||
import { VIDEO_QUALITY_LEVELS } from '../base/conference';
|
import { SET_MAX_RECEIVER_VIDEO_QUALITY, SET_PREFERRED_VIDEO_QUALITY } from './actionTypes';
|
||||||
|
import { VIDEO_QUALITY_LEVELS } from './constants';
|
||||||
import logger from './logger';
|
import logger from './logger';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the max frame height the user prefers to send and receive from the
|
||||||
|
* remote participants.
|
||||||
|
*
|
||||||
|
* @param {number} preferredVideoQuality - The max video resolution to send and
|
||||||
|
* receive.
|
||||||
|
* @returns {{
|
||||||
|
* type: SET_PREFERRED_VIDEO_QUALITY,
|
||||||
|
* preferredVideoQuality: number
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
export function setPreferredVideoQuality(preferredVideoQuality: number) {
|
||||||
|
return {
|
||||||
|
type: SET_PREFERRED_VIDEO_QUALITY,
|
||||||
|
preferredVideoQuality
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the max frame height that should be received from remote videos.
|
||||||
|
*
|
||||||
|
* @param {number} maxReceiverVideoQuality - The max video frame height to
|
||||||
|
* receive.
|
||||||
|
* @returns {{
|
||||||
|
* type: SET_MAX_RECEIVER_VIDEO_QUALITY,
|
||||||
|
* maxReceiverVideoQuality: number
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
export function setMaxReceiverVideoQuality(maxReceiverVideoQuality: number) {
|
||||||
|
return {
|
||||||
|
type: SET_MAX_RECEIVER_VIDEO_QUALITY,
|
||||||
|
maxReceiverVideoQuality
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the maximum video size the local participant should send and receive from
|
* Sets the maximum video size the local participant should send and receive from
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
import { VIDEO_QUALITY_LEVELS } from '../../base/conference/constants';
|
|
||||||
import { translate } from '../../base/i18n';
|
import { translate } from '../../base/i18n';
|
||||||
import {
|
import {
|
||||||
Icon,
|
Icon,
|
||||||
|
@ -12,6 +11,7 @@ import {
|
||||||
IconVideoQualitySD
|
IconVideoQualitySD
|
||||||
} from '../../base/icons';
|
} from '../../base/icons';
|
||||||
import { connect } from '../../base/redux';
|
import { connect } from '../../base/redux';
|
||||||
|
import { VIDEO_QUALITY_LEVELS } from '../constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A map of of selectable receive resolutions to corresponding icons.
|
* A map of of selectable receive resolutions to corresponding icons.
|
||||||
|
@ -104,7 +104,7 @@ class OverflowMenuVideoQualityItem extends Component<Props> {
|
||||||
function _mapStateToProps(state) {
|
function _mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
_audioOnly: state['features/base/audio-only'].enabled,
|
_audioOnly: state['features/base/audio-only'].enabled,
|
||||||
_videoQuality: state['features/base/conference'].preferredVideoQuality
|
_videoQuality: state['features/video-quality'].preferredVideoQuality
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,11 @@ import type { Dispatch } from 'redux';
|
||||||
|
|
||||||
import { createToolbarEvent, sendAnalytics } from '../../analytics';
|
import { createToolbarEvent, sendAnalytics } from '../../analytics';
|
||||||
import { setAudioOnly } from '../../base/audio-only';
|
import { setAudioOnly } from '../../base/audio-only';
|
||||||
import { VIDEO_QUALITY_LEVELS, setPreferredVideoQuality } from '../../base/conference';
|
|
||||||
import { translate } from '../../base/i18n';
|
import { translate } from '../../base/i18n';
|
||||||
import JitsiMeetJS from '../../base/lib-jitsi-meet';
|
import JitsiMeetJS from '../../base/lib-jitsi-meet';
|
||||||
import { connect } from '../../base/redux';
|
import { connect } from '../../base/redux';
|
||||||
|
import { setPreferredVideoQuality } from '../actions';
|
||||||
|
import { VIDEO_QUALITY_LEVELS } from '../constants';
|
||||||
import logger from '../logger';
|
import logger from '../logger';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -380,7 +381,8 @@ class VideoQualitySlider extends Component<Props> {
|
||||||
*/
|
*/
|
||||||
function _mapStateToProps(state) {
|
function _mapStateToProps(state) {
|
||||||
const { enabled: audioOnly } = state['features/base/audio-only'];
|
const { enabled: audioOnly } = state['features/base/audio-only'];
|
||||||
const { p2p, preferredVideoQuality } = state['features/base/conference'];
|
const { p2p } = state['features/base/conference'];
|
||||||
|
const { preferredVideoQuality } = state['features/video-quality'];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_audioOnly: audioOnly,
|
_audioOnly: audioOnly,
|
||||||
|
|
|
@ -1,4 +1,14 @@
|
||||||
import { VIDEO_QUALITY_LEVELS } from '../base/conference';
|
/**
|
||||||
|
* The supported remote video resolutions. The values are currently based on
|
||||||
|
* available simulcast layers.
|
||||||
|
*
|
||||||
|
* @type {object}
|
||||||
|
*/
|
||||||
|
export const VIDEO_QUALITY_LEVELS = {
|
||||||
|
HIGH: 720,
|
||||||
|
STANDARD: 360,
|
||||||
|
LOW: 180
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps quality level names used in the config.videoQuality.minHeightForQualityLvl to the quality level constants used
|
* Maps quality level names used in the config.videoQuality.minHeightForQualityLvl to the quality level constants used
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import { VIDEO_QUALITY_LEVELS } from '../base/conference';
|
import { CFG_LVL_TO_APP_QUALITY_LVL, VIDEO_QUALITY_LEVELS } from './constants';
|
||||||
|
|
||||||
import { CFG_LVL_TO_APP_QUALITY_LVL } from './constants';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export * from './components';
|
export * from './components';
|
||||||
export * from './actions';
|
export * from './actions';
|
||||||
|
export * from './actionTypes';
|
||||||
|
|
||||||
import './reducer';
|
import './reducer';
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CONFERENCE_JOINED,
|
CONFERENCE_JOINED,
|
||||||
VIDEO_QUALITY_LEVELS,
|
DATA_CHANNEL_OPENED
|
||||||
setMaxReceiverVideoQuality,
|
|
||||||
setPreferredVideoQuality
|
|
||||||
} from '../base/conference';
|
} from '../base/conference';
|
||||||
import { getParticipantCount } from '../base/participants';
|
import { getParticipantCount } from '../base/participants';
|
||||||
import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
|
import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
|
||||||
import { shouldDisplayTileView } from '../video-layout';
|
import { shouldDisplayTileView } from '../video-layout';
|
||||||
|
|
||||||
|
import { setPreferredVideoQuality, setMaxReceiverVideoQuality } from './actions';
|
||||||
|
import { VIDEO_QUALITY_LEVELS } from './constants';
|
||||||
import { getReceiverVideoQualityLevel } from './functions';
|
import { getReceiverVideoQualityLevel } from './functions';
|
||||||
import logger from './logger';
|
import logger from './logger';
|
||||||
import { getMinHeightForQualityLvlMap } from './selector';
|
import { getMinHeightForQualityLvlMap } from './selector';
|
||||||
|
@ -21,6 +21,10 @@ import { getMinHeightForQualityLvlMap } from './selector';
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
|
MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
|
||||||
|
if (action.type === DATA_CHANNEL_OPENED) {
|
||||||
|
return _syncReceiveVideoQuality(getState, next, action);
|
||||||
|
}
|
||||||
|
|
||||||
const result = next(action);
|
const result = next(action);
|
||||||
|
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
@ -59,7 +63,7 @@ StateListenerRegistry.register(
|
||||||
},
|
},
|
||||||
/* listener */ ({ displayTileView, participantCount, reducedUI, thumbnailHeight }, { dispatch, getState }) => {
|
/* listener */ ({ displayTileView, participantCount, reducedUI, thumbnailHeight }, { dispatch, getState }) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const { maxReceiverVideoQuality } = state['features/base/conference'];
|
const { maxReceiverVideoQuality } = state['features/video-quality'];
|
||||||
const { maxFullResolutionParticipants = 2 } = state['features/base/config'];
|
const { maxFullResolutionParticipants = 2 } = state['features/base/config'];
|
||||||
|
|
||||||
let newMaxRecvVideoQuality = VIDEO_QUALITY_LEVELS.HIGH;
|
let newMaxRecvVideoQuality = VIDEO_QUALITY_LEVELS.HIGH;
|
||||||
|
@ -92,3 +96,108 @@ StateListenerRegistry.register(
|
||||||
}, {
|
}, {
|
||||||
deepEquals: true
|
deepEquals: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for updating the preferred receiver video constraint, based
|
||||||
|
* on the user preference and the internal maximum.
|
||||||
|
*
|
||||||
|
* @param {JitsiConference} conference - The JitsiConference instance for the
|
||||||
|
* current call.
|
||||||
|
* @param {number} preferred - The user preferred max frame height.
|
||||||
|
* @param {number} max - The maximum frame height the application should
|
||||||
|
* receive.
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function _setReceiverVideoConstraint(conference, preferred, max) {
|
||||||
|
if (conference) {
|
||||||
|
const value = Math.min(preferred, max);
|
||||||
|
|
||||||
|
conference.setReceiverVideoConstraint(value);
|
||||||
|
logger.info(`setReceiverVideoConstraint: ${value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for updating the preferred sender video constraint, based
|
||||||
|
* on the user preference.
|
||||||
|
*
|
||||||
|
* @param {JitsiConference} conference - The JitsiConference instance for the
|
||||||
|
* current call.
|
||||||
|
* @param {number} preferred - The user preferred max frame height.
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function _setSenderVideoConstraint(conference, preferred) {
|
||||||
|
if (conference) {
|
||||||
|
conference.setSenderVideoConstraint(preferred)
|
||||||
|
.catch(err => {
|
||||||
|
logger.error(`Changing sender resolution to ${preferred} failed - ${err} `);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum receive video quality.
|
||||||
|
*
|
||||||
|
* @param {Function} getState - The redux function which returns the current redux state.
|
||||||
|
* @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
|
||||||
|
* specified {@code action} to the specified {@code store}.
|
||||||
|
* @param {Action} action - The redux action {@code DATA_CHANNEL_STATUS_CHANGED}
|
||||||
|
* which is being dispatched in the specified {@code store}.
|
||||||
|
* @private
|
||||||
|
* @returns {Object} The value returned by {@code next(action)}.
|
||||||
|
*/
|
||||||
|
function _syncReceiveVideoQuality(getState, next, action) {
|
||||||
|
const state = getState();
|
||||||
|
const {
|
||||||
|
conference
|
||||||
|
} = state['features/base/conference'];
|
||||||
|
const {
|
||||||
|
maxReceiverVideoQuality,
|
||||||
|
preferredVideoQuality
|
||||||
|
} = state['features/video-quality'];
|
||||||
|
|
||||||
|
_setReceiverVideoConstraint(
|
||||||
|
conference,
|
||||||
|
preferredVideoQuality,
|
||||||
|
maxReceiverVideoQuality);
|
||||||
|
|
||||||
|
return next(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a change handler for state['features/base/conference'] to update
|
||||||
|
* the preferred video quality levels based on user preferred and internal
|
||||||
|
* settings.
|
||||||
|
*/
|
||||||
|
StateListenerRegistry.register(
|
||||||
|
/* selector */ state => {
|
||||||
|
const { conference } = state['features/base/conference'];
|
||||||
|
const {
|
||||||
|
maxReceiverVideoQuality,
|
||||||
|
preferredVideoQuality
|
||||||
|
} = state['features/video-quality'];
|
||||||
|
|
||||||
|
return {
|
||||||
|
conference,
|
||||||
|
maxReceiverVideoQuality,
|
||||||
|
preferredVideoQuality
|
||||||
|
};
|
||||||
|
},
|
||||||
|
/* listener */ (currentState, store, previousState = {}) => {
|
||||||
|
const {
|
||||||
|
conference,
|
||||||
|
maxReceiverVideoQuality,
|
||||||
|
preferredVideoQuality
|
||||||
|
} = currentState;
|
||||||
|
const changedConference = conference !== previousState.conference;
|
||||||
|
const changedPreferredVideoQuality = preferredVideoQuality !== previousState.preferredVideoQuality;
|
||||||
|
const changedMaxVideoQuality = maxReceiverVideoQuality !== previousState.maxReceiverVideoQuality;
|
||||||
|
|
||||||
|
if (changedConference || changedPreferredVideoQuality || changedMaxVideoQuality) {
|
||||||
|
_setReceiverVideoConstraint(conference, preferredVideoQuality, maxReceiverVideoQuality);
|
||||||
|
}
|
||||||
|
if (changedConference || changedPreferredVideoQuality) {
|
||||||
|
_setSenderVideoConstraint(conference, preferredVideoQuality);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
@ -1,21 +1,36 @@
|
||||||
import { VIDEO_QUALITY_LEVELS } from '../base/conference';
|
|
||||||
import { SET_CONFIG } from '../base/config';
|
import { SET_CONFIG } from '../base/config';
|
||||||
import { ReducerRegistry, set } from '../base/redux';
|
import { ReducerRegistry, set } from '../base/redux';
|
||||||
|
|
||||||
|
import { SET_MAX_RECEIVER_VIDEO_QUALITY, SET_PREFERRED_VIDEO_QUALITY } from './actionTypes';
|
||||||
|
import { VIDEO_QUALITY_LEVELS } from './constants';
|
||||||
import { validateMinHeightForQualityLvl } from './functions';
|
import { validateMinHeightForQualityLvl } from './functions';
|
||||||
import logger from './logger';
|
import logger from './logger';
|
||||||
|
|
||||||
|
const STORE_NAME = 'features/video-quality';
|
||||||
|
|
||||||
const DEFAULT_STATE = {
|
const DEFAULT_STATE = {
|
||||||
minHeightForQualityLvl: new Map()
|
maxReceiverVideoQuality: VIDEO_QUALITY_LEVELS.HIGH,
|
||||||
|
minHeightForQualityLvl: new Map(),
|
||||||
|
preferredVideoQuality: VIDEO_QUALITY_LEVELS.HIGH
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFAULT_STATE.minHeightForQualityLvl.set(360, VIDEO_QUALITY_LEVELS.STANDARD);
|
DEFAULT_STATE.minHeightForQualityLvl.set(360, VIDEO_QUALITY_LEVELS.STANDARD);
|
||||||
DEFAULT_STATE.minHeightForQualityLvl.set(720, VIDEO_QUALITY_LEVELS.HIGH);
|
DEFAULT_STATE.minHeightForQualityLvl.set(720, VIDEO_QUALITY_LEVELS.HIGH);
|
||||||
|
|
||||||
ReducerRegistry.register('features/base/videoquality', (state = DEFAULT_STATE, action) => {
|
ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case SET_CONFIG:
|
case SET_CONFIG:
|
||||||
return _setConfig(state, action);
|
return _setConfig(state, action);
|
||||||
|
case SET_MAX_RECEIVER_VIDEO_QUALITY:
|
||||||
|
return set(
|
||||||
|
state,
|
||||||
|
'maxReceiverVideoQuality',
|
||||||
|
action.maxReceiverVideoQuality);
|
||||||
|
case SET_PREFERRED_VIDEO_QUALITY:
|
||||||
|
return set(
|
||||||
|
state,
|
||||||
|
'preferredVideoQuality',
|
||||||
|
action.preferredVideoQuality);
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
|
|
|
@ -7,5 +7,5 @@
|
||||||
* @returns {Map<number,number>}
|
* @returns {Map<number,number>}
|
||||||
*/
|
*/
|
||||||
export function getMinHeightForQualityLvlMap(state: Object): Map<number, number> {
|
export function getMinHeightForQualityLvlMap(state: Object): Map<number, number> {
|
||||||
return state['features/base/videoquality'].minHeightForQualityLvl;
|
return state['features/video-quality'].minHeightForQualityLvl;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue