feat(video-quality):control sender resolution based on user pref
This commit is contained in:
parent
3ab6b97b8b
commit
b5676c3729
|
@ -10884,8 +10884,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lib-jitsi-meet": {
|
"lib-jitsi-meet": {
|
||||||
"version": "github:jitsi/lib-jitsi-meet#f97c37d0140a0f12644ae29f4dd93757b8b8610f",
|
"version": "github:jitsi/lib-jitsi-meet#47b292e332e6c6e13de74f17540a0e6a6a80e165",
|
||||||
"from": "github:jitsi/lib-jitsi-meet#f97c37d0140a0f12644ae29f4dd93757b8b8610f",
|
"from": "github:jitsi/lib-jitsi-meet#47b292e332e6c6e13de74f17540a0e6a6a80e165",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@jitsi/sdp-interop": "1.0.2",
|
"@jitsi/sdp-interop": "1.0.2",
|
||||||
"@jitsi/sdp-simulcast": "0.3.0",
|
"@jitsi/sdp-simulcast": "0.3.0",
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
"js-utils": "github:jitsi/js-utils#df68966e3c65b5c57fcd2670da1326a2c77518d1",
|
"js-utils": "github:jitsi/js-utils#df68966e3c65b5c57fcd2670da1326a2c77518d1",
|
||||||
"jsrsasign": "8.0.12",
|
"jsrsasign": "8.0.12",
|
||||||
"jwt-decode": "2.2.0",
|
"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",
|
"libflacjs": "github:mmig/libflac.js#93d37e7f811f01cf7d8b6a603e38bd3c3810907d",
|
||||||
"lodash": "4.17.13",
|
"lodash": "4.17.13",
|
||||||
"moment": "2.19.4",
|
"moment": "2.19.4",
|
||||||
|
|
|
@ -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
|
* 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,
|
* type: SET_PREFERRED_VIDEO_QUALITY,
|
||||||
* preferredReceiverVideoQuality: number
|
* preferredVideoQuality: number
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
export const SET_PREFERRED_RECEIVER_VIDEO_QUALITY
|
export const SET_PREFERRED_VIDEO_QUALITY = 'SET_PREFERRED_VIDEO_QUALITY';
|
||||||
= 'SET_PREFERRED_RECEIVER_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
|
||||||
|
|
|
@ -48,7 +48,7 @@ import {
|
||||||
SET_MAX_RECEIVER_VIDEO_QUALITY,
|
SET_MAX_RECEIVER_VIDEO_QUALITY,
|
||||||
SET_PASSWORD,
|
SET_PASSWORD,
|
||||||
SET_PASSWORD_FAILED,
|
SET_PASSWORD_FAILED,
|
||||||
SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
|
SET_PREFERRED_VIDEO_QUALITY,
|
||||||
SET_ROOM,
|
SET_ROOM,
|
||||||
SET_PENDING_SUBJECT_CHANGE,
|
SET_PENDING_SUBJECT_CHANGE,
|
||||||
SET_START_MUTED_POLICY
|
SET_START_MUTED_POLICY
|
||||||
|
@ -699,21 +699,20 @@ export function setPassword(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the max frame height the user prefers to receive from remote participant
|
* Sets the max frame height the user prefers to send and receive from the
|
||||||
* videos.
|
* remote participants.
|
||||||
*
|
*
|
||||||
* @param {number} preferredReceiverVideoQuality - The max video resolution to
|
* @param {number} preferredVideoQuality - The max video resolution to send and
|
||||||
* receive.
|
* receive.
|
||||||
* @returns {{
|
* @returns {{
|
||||||
* type: SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
|
* type: SET_PREFERRED_VIDEO_QUALITY,
|
||||||
* preferredReceiverVideoQuality: number
|
* preferredVideoQuality: number
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
export function setPreferredReceiverVideoQuality(
|
export function setPreferredVideoQuality(preferredVideoQuality: number) {
|
||||||
preferredReceiverVideoQuality: number) {
|
|
||||||
return {
|
return {
|
||||||
type: SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
|
type: SET_PREFERRED_VIDEO_QUALITY,
|
||||||
preferredReceiverVideoQuality
|
preferredVideoQuality
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,14 +114,17 @@ StateListenerRegistry.register(
|
||||||
const {
|
const {
|
||||||
conference,
|
conference,
|
||||||
maxReceiverVideoQuality,
|
maxReceiverVideoQuality,
|
||||||
preferredReceiverVideoQuality
|
preferredVideoQuality
|
||||||
} = currentState;
|
} = currentState;
|
||||||
const changedPreferredVideoQuality
|
const changedPreferredVideoQuality
|
||||||
= preferredReceiverVideoQuality !== previousState.preferredReceiverVideoQuality;
|
= preferredVideoQuality !== previousState.preferredVideoQuality;
|
||||||
const changedMaxVideoQuality = maxReceiverVideoQuality !== previousState.maxReceiverVideoQuality;
|
const changedMaxVideoQuality = maxReceiverVideoQuality !== previousState.maxReceiverVideoQuality;
|
||||||
|
|
||||||
if (changedPreferredVideoQuality || changedMaxVideoQuality) {
|
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
|
* 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
|
||||||
|
@ -502,12 +523,12 @@ function _syncReceiveVideoQuality({ getState }, next, action) {
|
||||||
const {
|
const {
|
||||||
conference,
|
conference,
|
||||||
maxReceiverVideoQuality,
|
maxReceiverVideoQuality,
|
||||||
preferredReceiverVideoQuality
|
preferredVideoQuality
|
||||||
} = getState()['features/base/conference'];
|
} = getState()['features/base/conference'];
|
||||||
|
|
||||||
_setReceiverVideoConstraint(
|
_setReceiverVideoConstraint(
|
||||||
conference,
|
conference,
|
||||||
preferredReceiverVideoQuality,
|
preferredVideoQuality,
|
||||||
maxReceiverVideoQuality);
|
maxReceiverVideoQuality);
|
||||||
|
|
||||||
return next(action);
|
return next(action);
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {
|
||||||
SET_MAX_RECEIVER_VIDEO_QUALITY,
|
SET_MAX_RECEIVER_VIDEO_QUALITY,
|
||||||
SET_PASSWORD,
|
SET_PASSWORD,
|
||||||
SET_PENDING_SUBJECT_CHANGE,
|
SET_PENDING_SUBJECT_CHANGE,
|
||||||
SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
|
SET_PREFERRED_VIDEO_QUALITY,
|
||||||
SET_ROOM,
|
SET_ROOM,
|
||||||
SET_SIP_GATEWAY_ENABLED,
|
SET_SIP_GATEWAY_ENABLED,
|
||||||
SET_START_MUTED_POLICY
|
SET_START_MUTED_POLICY
|
||||||
|
@ -38,7 +38,7 @@ const DEFAULT_STATE = {
|
||||||
maxReceiverVideoQuality: VIDEO_QUALITY_LEVELS.HIGH,
|
maxReceiverVideoQuality: VIDEO_QUALITY_LEVELS.HIGH,
|
||||||
password: undefined,
|
password: undefined,
|
||||||
passwordRequired: undefined,
|
passwordRequired: undefined,
|
||||||
preferredReceiverVideoQuality: VIDEO_QUALITY_LEVELS.HIGH
|
preferredVideoQuality: VIDEO_QUALITY_LEVELS.HIGH
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,11 +101,11 @@ ReducerRegistry.register(
|
||||||
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_RECEIVER_VIDEO_QUALITY:
|
case SET_PREFERRED_VIDEO_QUALITY:
|
||||||
return set(
|
return set(
|
||||||
state,
|
state,
|
||||||
'preferredReceiverVideoQuality',
|
'preferredVideoQuality',
|
||||||
action.preferredReceiverVideoQuality);
|
action.preferredVideoQuality);
|
||||||
|
|
||||||
case SET_ROOM:
|
case SET_ROOM:
|
||||||
return _setRoom(state, action);
|
return _setRoom(state, action);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
VIDEO_QUALITY_LEVELS,
|
VIDEO_QUALITY_LEVELS,
|
||||||
conferenceLeft,
|
conferenceLeft,
|
||||||
getCurrentConference,
|
getCurrentConference,
|
||||||
setPreferredReceiverVideoQuality
|
setPreferredVideoQuality
|
||||||
} from '../base/conference';
|
} from '../base/conference';
|
||||||
import { hideDialog, isDialogOpen } from '../base/dialog';
|
import { hideDialog, isDialogOpen } from '../base/dialog';
|
||||||
import { setActiveModalId } from '../base/modal';
|
import { setActiveModalId } from '../base/modal';
|
||||||
|
@ -32,7 +32,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
dispatch(setFilmstripEnabled(!reducedUI));
|
dispatch(setFilmstripEnabled(!reducedUI));
|
||||||
|
|
||||||
dispatch(
|
dispatch(
|
||||||
setPreferredReceiverVideoQuality(
|
setPreferredVideoQuality(
|
||||||
reducedUI
|
reducedUI
|
||||||
? VIDEO_QUALITY_LEVELS.LOW
|
? VIDEO_QUALITY_LEVELS.LOW
|
||||||
: VIDEO_QUALITY_LEVELS.HIGH));
|
: VIDEO_QUALITY_LEVELS.HIGH));
|
||||||
|
|
|
@ -38,9 +38,9 @@ type Props = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currently configured maximum quality resolution to be received from
|
* 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.
|
* Callback to invoke when {@link OverflowMenuVideoQualityItem} is clicked.
|
||||||
|
@ -68,10 +68,10 @@ class OverflowMenuVideoQualityItem extends Component<Props> {
|
||||||
* @returns {ReactElement}
|
* @returns {ReactElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const { _audioOnly, _receiverVideoQuality } = this.props;
|
const { _audioOnly, _videoQuality } = this.props;
|
||||||
const icon = _audioOnly || !_receiverVideoQuality
|
const icon = _audioOnly || !_videoQuality
|
||||||
? IconVideoQualityAudioOnly
|
? IconVideoQualityAudioOnly
|
||||||
: VIDEO_QUALITY_TO_ICON[_receiverVideoQuality];
|
: VIDEO_QUALITY_TO_ICON[_videoQuality];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
|
@ -98,14 +98,13 @@ class OverflowMenuVideoQualityItem extends Component<Props> {
|
||||||
* @private
|
* @private
|
||||||
* @returns {{
|
* @returns {{
|
||||||
* _audioOnly: boolean,
|
* _audioOnly: boolean,
|
||||||
* _receiverVideoQuality: number
|
* _videoQuality: number
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
function _mapStateToProps(state) {
|
function _mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
_audioOnly: state['features/base/audio-only'].enabled,
|
_audioOnly: state['features/base/audio-only'].enabled,
|
||||||
_receiverVideoQuality:
|
_videoQuality: state['features/base/conference'].preferredVideoQuality
|
||||||
state['features/base/conference'].preferredReceiverVideoQuality
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ 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, setPreferredReceiverVideoQuality } from '../../base/conference';
|
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';
|
||||||
|
@ -51,10 +51,10 @@ type Props = {
|
||||||
_p2p: Boolean,
|
_p2p: Boolean,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currently configured maximum quality resolution to be received
|
* The currently configured maximum quality resolution to be sent and
|
||||||
* from remote participants.
|
* received from the remote participants.
|
||||||
*/
|
*/
|
||||||
_receiverVideoQuality: Number,
|
_sendrecvVideoQuality: Number,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not displaying video is supported in the current
|
* Whether or not displaying video is supported in the current
|
||||||
|
@ -326,7 +326,7 @@ class VideoQualitySlider extends Component<Props> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_mapCurrentQualityToSliderValue() {
|
_mapCurrentQualityToSliderValue() {
|
||||||
const { _audioOnly, _receiverVideoQuality } = this.props;
|
const { _audioOnly, _sendrecvVideoQuality } = this.props;
|
||||||
const { _sliderOptions } = this;
|
const { _sliderOptions } = this;
|
||||||
|
|
||||||
if (_audioOnly) {
|
if (_audioOnly) {
|
||||||
|
@ -337,7 +337,7 @@ class VideoQualitySlider extends Component<Props> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const matchingOption = _sliderOptions.find(
|
const matchingOption = _sliderOptions.find(
|
||||||
({ videoQuality }) => videoQuality === _receiverVideoQuality);
|
({ videoQuality }) => videoQuality === _sendrecvVideoQuality);
|
||||||
|
|
||||||
return _sliderOptions.indexOf(matchingOption);
|
return _sliderOptions.indexOf(matchingOption);
|
||||||
}
|
}
|
||||||
|
@ -352,7 +352,7 @@ class VideoQualitySlider extends Component<Props> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_onSliderChange(event) {
|
_onSliderChange(event) {
|
||||||
const { _audioOnly, _receiverVideoQuality } = this.props;
|
const { _audioOnly, _sendrecvVideoQuality } = this.props;
|
||||||
const {
|
const {
|
||||||
audioOnly,
|
audioOnly,
|
||||||
onSelect,
|
onSelect,
|
||||||
|
@ -362,7 +362,7 @@ class VideoQualitySlider extends Component<Props> {
|
||||||
// Take no action if the newly chosen option does not change audio only
|
// Take no action if the newly chosen option does not change audio only
|
||||||
// or video quality state.
|
// or video quality state.
|
||||||
if ((_audioOnly && audioOnly)
|
if ((_audioOnly && audioOnly)
|
||||||
|| (!_audioOnly && videoQuality === _receiverVideoQuality)) {
|
|| (!_audioOnly && videoQuality === _sendrecvVideoQuality)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,7 +379,7 @@ class VideoQualitySlider extends Component<Props> {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
_setPreferredVideoQuality(qualityLevel) {
|
_setPreferredVideoQuality(qualityLevel) {
|
||||||
this.props.dispatch(setPreferredReceiverVideoQuality(qualityLevel));
|
this.props.dispatch(setPreferredVideoQuality(qualityLevel));
|
||||||
|
|
||||||
if (this.props._audioOnly) {
|
if (this.props._audioOnly) {
|
||||||
this.props.dispatch(setAudioOnly(false));
|
this.props.dispatch(setAudioOnly(false));
|
||||||
|
@ -396,17 +396,17 @@ class VideoQualitySlider extends Component<Props> {
|
||||||
* @returns {{
|
* @returns {{
|
||||||
* _audioOnly: boolean,
|
* _audioOnly: boolean,
|
||||||
* _p2p: boolean,
|
* _p2p: boolean,
|
||||||
* _receiverVideoQuality: boolean
|
* _sendrecvVideoQuality: number
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
function _mapStateToProps(state) {
|
function _mapStateToProps(state) {
|
||||||
const { enabled: audioOnly } = state['features/base/audio-only'];
|
const { enabled: audioOnly } = state['features/base/audio-only'];
|
||||||
const { p2p, preferredReceiverVideoQuality } = state['features/base/conference'];
|
const { p2p, preferredVideoQuality } = state['features/base/conference'];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_audioOnly: audioOnly,
|
_audioOnly: audioOnly,
|
||||||
_p2p: p2p,
|
_p2p: p2p,
|
||||||
_receiverVideoQuality: preferredReceiverVideoQuality,
|
_sendrecvVideoQuality: preferredVideoQuality,
|
||||||
_videoSupported: JitsiMeetJS.mediaDevices.supportsVideo()
|
_videoSupported: JitsiMeetJS.mediaDevices.supportsVideo()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue