Files
jitsi-meet/react/features/video-quality/middleware.js
paweldomas d3d5847605 feat: configurable quality levels for video height
Allows to adjust thresholds which control the video quality level
in the thumbnail view.

Changes the default behaviour to request the SD (360p) resolution only
when the thumbnails are at least 360 pixels tall and the height of
720 is required for the high quality level.

The thresholds can be configured with the 'videoQuality.minHeightForQualityLvl'
config property. Check the description in the config.js for more details.
2020-08-20 11:07:36 -07:00

95 lines
3.5 KiB
JavaScript

// @flow
import {
CONFERENCE_JOINED,
VIDEO_QUALITY_LEVELS,
setMaxReceiverVideoQuality,
setPreferredVideoQuality
} from '../base/conference';
import { getParticipantCount } from '../base/participants';
import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
import { shouldDisplayTileView } from '../video-layout';
import { getReceiverVideoQualityLevel } from './functions';
import logger from './logger';
import { getMinHeightForQualityLvlMap } from './selector';
/**
* Implements the middleware of the feature video-quality.
*
* @param {Store} store - The redux store.
* @returns {Function}
*/
MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
const result = next(action);
switch (action.type) {
case CONFERENCE_JOINED: {
if (navigator.product === 'ReactNative') {
const { resolution } = getState()['features/base/config'];
if (typeof resolution !== 'undefined') {
dispatch(setPreferredVideoQuality(Number.parseInt(resolution, 10)));
logger.info(`Configured preferred receiver video frame height to: ${resolution}`);
}
}
break;
}
}
return result;
});
/**
* Implements a state listener in order to calculate max receiver video quality.
*/
StateListenerRegistry.register(
/* selector */ state => {
const { reducedUI } = state['features/base/responsive-ui'];
const _shouldDisplayTileView = shouldDisplayTileView(state);
const thumbnailSize = state['features/filmstrip']?.tileViewDimensions?.thumbnailSize;
const participantCount = getParticipantCount(state);
return {
displayTileView: _shouldDisplayTileView,
participantCount,
reducedUI,
thumbnailHeight: thumbnailSize?.height
};
},
/* listener */ ({ displayTileView, participantCount, reducedUI, thumbnailHeight }, { dispatch, getState }) => {
const state = getState();
const { maxReceiverVideoQuality } = state['features/base/conference'];
const { maxFullResolutionParticipants = 2 } = state['features/base/config'];
let newMaxRecvVideoQuality = VIDEO_QUALITY_LEVELS.HIGH;
if (reducedUI) {
newMaxRecvVideoQuality = VIDEO_QUALITY_LEVELS.LOW;
} else if (displayTileView && !Number.isNaN(thumbnailHeight)) {
newMaxRecvVideoQuality = getReceiverVideoQualityLevel(thumbnailHeight, getMinHeightForQualityLvlMap(state));
// Override HD level calculated for the thumbnail height when # of participants threshold is exceeded
if (maxReceiverVideoQuality !== newMaxRecvVideoQuality && maxFullResolutionParticipants !== -1) {
const override
= participantCount > maxFullResolutionParticipants
&& newMaxRecvVideoQuality > VIDEO_QUALITY_LEVELS.STANDARD;
logger.info(`Video quality level for thumbnail height: ${thumbnailHeight}, `
+ `is: ${newMaxRecvVideoQuality}, `
+ `override: ${String(override)}, `
+ `max full res N: ${maxFullResolutionParticipants}`);
if (override) {
newMaxRecvVideoQuality = VIDEO_QUALITY_LEVELS.STANDARD;
}
}
}
if (maxReceiverVideoQuality !== newMaxRecvVideoQuality) {
dispatch(setMaxReceiverVideoQuality(newMaxRecvVideoQuality));
}
}, {
deepEquals: true
});