From b5676c37295f52c3c73b300b1f0ff463aef112fc Mon Sep 17 00:00:00 2001 From: Jaya Allamsetty Date: Mon, 27 Apr 2020 22:51:40 -0400 Subject: [PATCH] feat(video-quality):control sender resolution based on user pref --- package-lock.json | 4 +-- package.json | 2 +- react/features/base/conference/actionTypes.js | 9 +++--- react/features/base/conference/actions.js | 19 ++++++------ react/features/base/conference/middleware.js | 31 ++++++++++++++++--- react/features/base/conference/reducer.js | 10 +++--- react/features/conference/middleware.js | 4 +-- .../OverflowMenuVideoQualityItem.web.js | 15 +++++---- .../components/VideoQualitySlider.web.js | 24 +++++++------- 9 files changed, 68 insertions(+), 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index e713c8bea..32cd1e227 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10884,8 +10884,8 @@ } }, "lib-jitsi-meet": { - "version": "github:jitsi/lib-jitsi-meet#f97c37d0140a0f12644ae29f4dd93757b8b8610f", - "from": "github:jitsi/lib-jitsi-meet#f97c37d0140a0f12644ae29f4dd93757b8b8610f", + "version": "github:jitsi/lib-jitsi-meet#47b292e332e6c6e13de74f17540a0e6a6a80e165", + "from": "github:jitsi/lib-jitsi-meet#47b292e332e6c6e13de74f17540a0e6a6a80e165", "requires": { "@jitsi/sdp-interop": "1.0.2", "@jitsi/sdp-simulcast": "0.3.0", diff --git a/package.json b/package.json index 6ca650886..7e4187321 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "js-utils": "github:jitsi/js-utils#df68966e3c65b5c57fcd2670da1326a2c77518d1", "jsrsasign": "8.0.12", "jwt-decode": "2.2.0", - "lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#f97c37d0140a0f12644ae29f4dd93757b8b8610f", + "lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#47b292e332e6c6e13de74f17540a0e6a6a80e165", "libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d", "lodash": "4.17.13", "moment": "2.19.4", diff --git a/react/features/base/conference/actionTypes.js b/react/features/base/conference/actionTypes.js index 2a9bbec39..6b506dff9 100644 --- a/react/features/base/conference/actionTypes.js +++ b/react/features/base/conference/actionTypes.js @@ -212,15 +212,14 @@ 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 received from remote participants. + * should be sent to and received from remote participants. * * { - * type: SET_PREFERRED_RECEIVER_VIDEO_QUALITY, - * preferredReceiverVideoQuality: number + * type: SET_PREFERRED_VIDEO_QUALITY, + * preferredVideoQuality: number * } */ -export const SET_PREFERRED_RECEIVER_VIDEO_QUALITY - = 'SET_PREFERRED_RECEIVER_VIDEO_QUALITY'; +export const SET_PREFERRED_VIDEO_QUALITY = 'SET_PREFERRED_VIDEO_QUALITY'; /** * The type of (redux) action which sets the name of the room of the diff --git a/react/features/base/conference/actions.js b/react/features/base/conference/actions.js index 1f67a7d00..6f5634c31 100644 --- a/react/features/base/conference/actions.js +++ b/react/features/base/conference/actions.js @@ -48,7 +48,7 @@ import { SET_MAX_RECEIVER_VIDEO_QUALITY, SET_PASSWORD, SET_PASSWORD_FAILED, - SET_PREFERRED_RECEIVER_VIDEO_QUALITY, + SET_PREFERRED_VIDEO_QUALITY, SET_ROOM, SET_PENDING_SUBJECT_CHANGE, SET_START_MUTED_POLICY @@ -699,21 +699,20 @@ export function setPassword( } /** - * Sets the max frame height the user prefers to receive from remote participant - * videos. + * Sets the max frame height the user prefers to send and receive from the + * remote participants. * - * @param {number} preferredReceiverVideoQuality - The max video resolution to + * @param {number} preferredVideoQuality - The max video resolution to send and * receive. * @returns {{ - * type: SET_PREFERRED_RECEIVER_VIDEO_QUALITY, - * preferredReceiverVideoQuality: number + * type: SET_PREFERRED_VIDEO_QUALITY, + * preferredVideoQuality: number * }} */ -export function setPreferredReceiverVideoQuality( - preferredReceiverVideoQuality: number) { +export function setPreferredVideoQuality(preferredVideoQuality: number) { return { - type: SET_PREFERRED_RECEIVER_VIDEO_QUALITY, - preferredReceiverVideoQuality + type: SET_PREFERRED_VIDEO_QUALITY, + preferredVideoQuality }; } diff --git a/react/features/base/conference/middleware.js b/react/features/base/conference/middleware.js index 3de1bbcb4..c37c7b573 100644 --- a/react/features/base/conference/middleware.js +++ b/react/features/base/conference/middleware.js @@ -114,14 +114,17 @@ StateListenerRegistry.register( const { conference, maxReceiverVideoQuality, - preferredReceiverVideoQuality + preferredVideoQuality } = currentState; const changedPreferredVideoQuality - = preferredReceiverVideoQuality !== previousState.preferredReceiverVideoQuality; + = preferredVideoQuality !== previousState.preferredVideoQuality; const changedMaxVideoQuality = maxReceiverVideoQuality !== previousState.maxReceiverVideoQuality; if (changedPreferredVideoQuality || changedMaxVideoQuality) { - _setReceiverVideoConstraint(conference, preferredReceiverVideoQuality, maxReceiverVideoQuality); + _setReceiverVideoConstraint(conference, preferredVideoQuality, maxReceiverVideoQuality); + } + if (changedPreferredVideoQuality) { + _setSenderVideoConstraint(conference, preferredVideoQuality); } }); @@ -433,6 +436,24 @@ function _setReceiverVideoConstraint(conference, preferred, max) { } } +/** + * 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 * {@code SET_ROOM} is being dispatched within a specific @@ -502,12 +523,12 @@ function _syncReceiveVideoQuality({ getState }, next, action) { const { conference, maxReceiverVideoQuality, - preferredReceiverVideoQuality + preferredVideoQuality } = getState()['features/base/conference']; _setReceiverVideoConstraint( conference, - preferredReceiverVideoQuality, + preferredVideoQuality, maxReceiverVideoQuality); return next(action); diff --git a/react/features/base/conference/reducer.js b/react/features/base/conference/reducer.js index 1b528dc71..81c332d97 100644 --- a/react/features/base/conference/reducer.js +++ b/react/features/base/conference/reducer.js @@ -21,7 +21,7 @@ import { SET_MAX_RECEIVER_VIDEO_QUALITY, SET_PASSWORD, SET_PENDING_SUBJECT_CHANGE, - SET_PREFERRED_RECEIVER_VIDEO_QUALITY, + SET_PREFERRED_VIDEO_QUALITY, SET_ROOM, SET_SIP_GATEWAY_ENABLED, SET_START_MUTED_POLICY @@ -38,7 +38,7 @@ const DEFAULT_STATE = { maxReceiverVideoQuality: VIDEO_QUALITY_LEVELS.HIGH, password: undefined, passwordRequired: undefined, - preferredReceiverVideoQuality: VIDEO_QUALITY_LEVELS.HIGH + preferredVideoQuality: VIDEO_QUALITY_LEVELS.HIGH }; /** @@ -101,11 +101,11 @@ ReducerRegistry.register( case SET_PENDING_SUBJECT_CHANGE: return set(state, 'pendingSubjectChange', action.subject); - case SET_PREFERRED_RECEIVER_VIDEO_QUALITY: + case SET_PREFERRED_VIDEO_QUALITY: return set( state, - 'preferredReceiverVideoQuality', - action.preferredReceiverVideoQuality); + 'preferredVideoQuality', + action.preferredVideoQuality); case SET_ROOM: return _setRoom(state, action); diff --git a/react/features/conference/middleware.js b/react/features/conference/middleware.js index 8e727cb81..850c538d4 100644 --- a/react/features/conference/middleware.js +++ b/react/features/conference/middleware.js @@ -7,7 +7,7 @@ import { VIDEO_QUALITY_LEVELS, conferenceLeft, getCurrentConference, - setPreferredReceiverVideoQuality + setPreferredVideoQuality } from '../base/conference'; import { hideDialog, isDialogOpen } from '../base/dialog'; import { setActiveModalId } from '../base/modal'; @@ -32,7 +32,7 @@ MiddlewareRegistry.register(store => next => action => { dispatch(setFilmstripEnabled(!reducedUI)); dispatch( - setPreferredReceiverVideoQuality( + setPreferredVideoQuality( reducedUI ? VIDEO_QUALITY_LEVELS.LOW : VIDEO_QUALITY_LEVELS.HIGH)); diff --git a/react/features/video-quality/components/OverflowMenuVideoQualityItem.web.js b/react/features/video-quality/components/OverflowMenuVideoQualityItem.web.js index 1c390c71a..5e643a591 100644 --- a/react/features/video-quality/components/OverflowMenuVideoQualityItem.web.js +++ b/react/features/video-quality/components/OverflowMenuVideoQualityItem.web.js @@ -38,9 +38,9 @@ type Props = { /** * The currently configured maximum quality resolution to be received from - * remote participants. + * and sent to remote participants. */ - _receiverVideoQuality: number, + _videoQuality: number, /** * Callback to invoke when {@link OverflowMenuVideoQualityItem} is clicked. @@ -68,10 +68,10 @@ class OverflowMenuVideoQualityItem extends Component { * @returns {ReactElement} */ render() { - const { _audioOnly, _receiverVideoQuality } = this.props; - const icon = _audioOnly || !_receiverVideoQuality + const { _audioOnly, _videoQuality } = this.props; + const icon = _audioOnly || !_videoQuality ? IconVideoQualityAudioOnly - : VIDEO_QUALITY_TO_ICON[_receiverVideoQuality]; + : VIDEO_QUALITY_TO_ICON[_videoQuality]; return (
  • { * @private * @returns {{ * _audioOnly: boolean, - * _receiverVideoQuality: number + * _videoQuality: number * }} */ function _mapStateToProps(state) { return { _audioOnly: state['features/base/audio-only'].enabled, - _receiverVideoQuality: - state['features/base/conference'].preferredReceiverVideoQuality + _videoQuality: state['features/base/conference'].preferredVideoQuality }; } diff --git a/react/features/video-quality/components/VideoQualitySlider.web.js b/react/features/video-quality/components/VideoQualitySlider.web.js index d8f948d3c..743f1a1c7 100644 --- a/react/features/video-quality/components/VideoQualitySlider.web.js +++ b/react/features/video-quality/components/VideoQualitySlider.web.js @@ -6,7 +6,7 @@ import type { Dispatch } from 'redux'; import { createToolbarEvent, sendAnalytics } from '../../analytics'; import { setAudioOnly } from '../../base/audio-only'; -import { VIDEO_QUALITY_LEVELS, setPreferredReceiverVideoQuality } from '../../base/conference'; +import { VIDEO_QUALITY_LEVELS, setPreferredVideoQuality } from '../../base/conference'; import { translate } from '../../base/i18n'; import JitsiMeetJS from '../../base/lib-jitsi-meet'; import { connect } from '../../base/redux'; @@ -51,10 +51,10 @@ type Props = { _p2p: Boolean, /** - * The currently configured maximum quality resolution to be received - * from remote participants. + * The currently configured maximum quality resolution to be sent and + * received from the remote participants. */ - _receiverVideoQuality: Number, + _sendrecvVideoQuality: Number, /** * Whether or not displaying video is supported in the current @@ -326,7 +326,7 @@ class VideoQualitySlider extends Component { * @returns {void} */ _mapCurrentQualityToSliderValue() { - const { _audioOnly, _receiverVideoQuality } = this.props; + const { _audioOnly, _sendrecvVideoQuality } = this.props; const { _sliderOptions } = this; if (_audioOnly) { @@ -337,7 +337,7 @@ class VideoQualitySlider extends Component { } const matchingOption = _sliderOptions.find( - ({ videoQuality }) => videoQuality === _receiverVideoQuality); + ({ videoQuality }) => videoQuality === _sendrecvVideoQuality); return _sliderOptions.indexOf(matchingOption); } @@ -352,7 +352,7 @@ class VideoQualitySlider extends Component { * @returns {void} */ _onSliderChange(event) { - const { _audioOnly, _receiverVideoQuality } = this.props; + const { _audioOnly, _sendrecvVideoQuality } = this.props; const { audioOnly, onSelect, @@ -362,7 +362,7 @@ class VideoQualitySlider extends Component { // Take no action if the newly chosen option does not change audio only // or video quality state. if ((_audioOnly && audioOnly) - || (!_audioOnly && videoQuality === _receiverVideoQuality)) { + || (!_audioOnly && videoQuality === _sendrecvVideoQuality)) { return; } @@ -379,7 +379,7 @@ class VideoQualitySlider extends Component { * @returns {void} */ _setPreferredVideoQuality(qualityLevel) { - this.props.dispatch(setPreferredReceiverVideoQuality(qualityLevel)); + this.props.dispatch(setPreferredVideoQuality(qualityLevel)); if (this.props._audioOnly) { this.props.dispatch(setAudioOnly(false)); @@ -396,17 +396,17 @@ class VideoQualitySlider extends Component { * @returns {{ * _audioOnly: boolean, * _p2p: boolean, - * _receiverVideoQuality: boolean + * _sendrecvVideoQuality: number * }} */ function _mapStateToProps(state) { const { enabled: audioOnly } = state['features/base/audio-only']; - const { p2p, preferredReceiverVideoQuality } = state['features/base/conference']; + const { p2p, preferredVideoQuality } = state['features/base/conference']; return { _audioOnly: audioOnly, _p2p: p2p, - _receiverVideoQuality: preferredReceiverVideoQuality, + _sendrecvVideoQuality: preferredVideoQuality, _videoSupported: JitsiMeetJS.mediaDevices.supportsVideo() }; }