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": {
|
||||
"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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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<Props> {
|
|||
* @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 (
|
||||
<li
|
||||
|
@ -98,14 +98,13 @@ class OverflowMenuVideoQualityItem extends Component<Props> {
|
|||
* @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
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Props> {
|
|||
* @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<Props> {
|
|||
}
|
||||
|
||||
const matchingOption = _sliderOptions.find(
|
||||
({ videoQuality }) => videoQuality === _receiverVideoQuality);
|
||||
({ videoQuality }) => videoQuality === _sendrecvVideoQuality);
|
||||
|
||||
return _sliderOptions.indexOf(matchingOption);
|
||||
}
|
||||
|
@ -352,7 +352,7 @@ class VideoQualitySlider extends Component<Props> {
|
|||
* @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<Props> {
|
|||
// 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<Props> {
|
|||
* @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<Props> {
|
|||
* @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()
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue