audio-only: implement initial "low bandwidth mode"
It's an evolution of audio-only mode, where we also allow for receiving a remote screen-share. Diving deeper: this basically sets last N to 1 or 0 depending on the availability of a screen-share.
This commit is contained in:
parent
0f77cf9e0c
commit
f3e7952e51
|
@ -24,7 +24,7 @@
|
|||
"speaker": "Speaker"
|
||||
},
|
||||
"audioOnly": {
|
||||
"audioOnly": "Audio only"
|
||||
"audioOnly": "Low bandwidth"
|
||||
},
|
||||
"calendarSync": {
|
||||
"addMeetingURL": "Add a meeting link",
|
||||
|
@ -584,8 +584,8 @@
|
|||
"videoblur": "Toggle video blur"
|
||||
},
|
||||
"addPeople": "Add people to your call",
|
||||
"audioOnlyOff": "Disable audio only mode",
|
||||
"audioOnlyOn": "Enable audio only mode",
|
||||
"audioOnlyOff": "Disable low bandwidth mode",
|
||||
"audioOnlyOn": "Enable low bandwidth mode",
|
||||
"audioRoute": "Select the sound device",
|
||||
"authenticate": "Authenticate",
|
||||
"callQuality": "Manage video quality",
|
||||
|
@ -663,13 +663,13 @@
|
|||
},
|
||||
"videoStatus": {
|
||||
"audioOnly": "AUD",
|
||||
"audioOnlyExpanded": "You are in audio only mode. This mode saves bandwidth but you won't see videos of others.",
|
||||
"audioOnlyExpanded": "You are in low bandwidth mode. In this mode you will receive only audio and screen sharing.",
|
||||
"callQuality": "Video Quality",
|
||||
"hd": "HD",
|
||||
"hdTooltip": "Viewing high definition video",
|
||||
"highDefinition": "High definition",
|
||||
"labelTooiltipNoVideo": "No video",
|
||||
"labelTooltipAudioOnly": "Audio-only mode enabled",
|
||||
"labelTooltipAudioOnly": "Low bandwidth mode enabled",
|
||||
"ld": "LD",
|
||||
"ldTooltip": "Viewing low definition video",
|
||||
"lowDefinition": "Low definition",
|
||||
|
|
|
@ -12,6 +12,7 @@ import { PresenceLabel } from '../../../react/features/presence-status';
|
|||
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
|
||||
import { VIDEO_TYPE } from '../../../react/features/base/media';
|
||||
import {
|
||||
JitsiParticipantConnectionStatus
|
||||
} from '../../../react/features/base/lib-jitsi-meet';
|
||||
|
@ -232,7 +233,7 @@ export default class LargeVideoManager {
|
|||
|
||||
const showAvatar
|
||||
= isVideoContainer
|
||||
&& (APP.conference.isAudioOnly() || !isVideoRenderable);
|
||||
&& ((APP.conference.isAudioOnly() && videoType !== VIDEO_TYPE.DESKTOP) || !isVideoRenderable);
|
||||
|
||||
let promise;
|
||||
|
||||
|
|
|
@ -3,10 +3,13 @@
|
|||
import { getLogger } from 'jitsi-meet-logger';
|
||||
|
||||
import { SET_FILMSTRIP_ENABLED } from '../../filmstrip/actionTypes';
|
||||
import { SELECT_LARGE_VIDEO_PARTICIPANT } from '../../large-video/actionTypes';
|
||||
import { APP_STATE_CHANGED } from '../../mobile/background/actionTypes';
|
||||
import { SCREEN_SHARE_PARTICIPANTS_UPDATED, SET_TILE_VIEW } from '../../video-layout/actionTypes';
|
||||
|
||||
import { SET_AUDIO_ONLY } from '../audio-only';
|
||||
import { SET_AUDIO_ONLY } from '../audio-only/actionTypes';
|
||||
import { CONFERENCE_JOINED } from '../conference/actionTypes';
|
||||
import { getParticipantById } from '../participants/functions';
|
||||
import { MiddlewareRegistry } from '../redux';
|
||||
|
||||
declare var APP: Object;
|
||||
|
@ -19,8 +22,11 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
switch (action.type) {
|
||||
case APP_STATE_CHANGED:
|
||||
case CONFERENCE_JOINED:
|
||||
case SCREEN_SHARE_PARTICIPANTS_UPDATED:
|
||||
case SELECT_LARGE_VIDEO_PARTICIPANT:
|
||||
case SET_AUDIO_ONLY:
|
||||
case SET_FILMSTRIP_ENABLED:
|
||||
case SET_TILE_VIEW:
|
||||
_updateLastN(store);
|
||||
break;
|
||||
}
|
||||
|
@ -52,12 +58,27 @@ function _updateLastN({ getState }) {
|
|||
const defaultLastN = typeof config.channelLastN === 'undefined' ? -1 : config.channelLastN;
|
||||
let lastN = defaultLastN;
|
||||
|
||||
if (audioOnly || appState !== 'active') {
|
||||
if (appState !== 'active') {
|
||||
lastN = 0;
|
||||
} else if (audioOnly) {
|
||||
const { screenShares, tileViewEnabled } = state['features/video-layout'];
|
||||
const largeVideoParticipantId = state['features/large-video'].participantId;
|
||||
const largeVideoParticipant
|
||||
= largeVideoParticipantId ? getParticipantById(state, largeVideoParticipantId) : undefined;
|
||||
|
||||
if (!tileViewEnabled && largeVideoParticipant && !largeVideoParticipant.local) {
|
||||
lastN = (screenShares || []).includes(largeVideoParticipantId) ? 1 : 0;
|
||||
} else {
|
||||
lastN = 0;
|
||||
}
|
||||
} else if (!filmStripEnabled) {
|
||||
lastN = 1;
|
||||
}
|
||||
|
||||
if (conference.getLastN() === lastN) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(`Setting last N to: ${lastN}`);
|
||||
|
||||
try {
|
||||
|
|
|
@ -185,8 +185,6 @@ class ParticipantView extends Component<Props> {
|
|||
tintStyle
|
||||
} = this.props;
|
||||
|
||||
const waitForVideoStarted = false;
|
||||
|
||||
// If the connection has problems, we will "tint" the video / avatar.
|
||||
const connectionProblem
|
||||
= connectionStatus !== JitsiParticipantConnectionStatus.ACTIVE;
|
||||
|
@ -216,7 +214,7 @@ class ParticipantView extends Component<Props> {
|
|||
&& <VideoTrack
|
||||
onPress = { onPress }
|
||||
videoTrack = { videoTrack }
|
||||
waitForVideoStarted = { waitForVideoStarted }
|
||||
waitForVideoStarted = { false }
|
||||
zOrder = { this.props.zOrder }
|
||||
zoomEnabled = { this.props.zoomEnabled } /> }
|
||||
|
||||
|
|
|
@ -299,14 +299,14 @@ export function isLocalParticipantModerator(
|
|||
|
||||
/**
|
||||
* Returns true if the video of the participant should be rendered.
|
||||
* NOTE: This is currently only used on mobile.
|
||||
*
|
||||
* @param {Object|Function} stateful - Object or function that can be resolved
|
||||
* to the Redux state.
|
||||
* @param {string} id - The ID of the participant.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function shouldRenderParticipantVideo(
|
||||
stateful: Object | Function, id: string) {
|
||||
export function shouldRenderParticipantVideo(stateful: Object | Function, id: string) {
|
||||
const state = toState(stateful);
|
||||
const participant = getParticipantById(state, id);
|
||||
|
||||
|
@ -314,29 +314,35 @@ export function shouldRenderParticipantVideo(
|
|||
return false;
|
||||
}
|
||||
|
||||
/* First check if we have an unmuted video track. */
|
||||
const videoTrack
|
||||
= getTrackByMediaTypeAndParticipant(state['features/base/tracks'], MEDIA_TYPE.VIDEO, id);
|
||||
|
||||
if (!shouldRenderVideoTrack(videoTrack, /* waitForVideoStarted */ false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Then check if the participant connection is active. */
|
||||
const connectionStatus = participant.connectionStatus || JitsiParticipantConnectionStatus.ACTIVE;
|
||||
|
||||
if (connectionStatus !== JitsiParticipantConnectionStatus.ACTIVE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Then check if audio-only mode is not active. */
|
||||
const audioOnly = state['features/base/audio-only'].enabled;
|
||||
const connectionStatus = participant.connectionStatus
|
||||
|| JitsiParticipantConnectionStatus.ACTIVE;
|
||||
const videoTrack = getTrackByMediaTypeAndParticipant(
|
||||
state['features/base/tracks'],
|
||||
MEDIA_TYPE.VIDEO,
|
||||
id);
|
||||
|
||||
// Is the video to be rendered?
|
||||
// FIXME It's currently impossible to have true as the value of
|
||||
// waitForVideoStarted because videoTrack's state videoStarted will be
|
||||
// updated only after videoTrack is rendered.
|
||||
// XXX Note that, unlike on web, we don't render video when the
|
||||
// connection status is interrupted, this is because the renderer
|
||||
// doesn't retain the last frame forever, so we would end up with a
|
||||
// black screen.
|
||||
const waitForVideoStarted = false;
|
||||
if (!audioOnly) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !audioOnly
|
||||
&& (connectionStatus
|
||||
=== JitsiParticipantConnectionStatus.ACTIVE)
|
||||
&& shouldRenderVideoTrack(videoTrack, waitForVideoStarted);
|
||||
/* Last, check if the participant is sharing their screen and they are on stage. */
|
||||
const screenShares = state['features/video-layout'].screenShares || [];
|
||||
const largeVideoParticipantId = state['features/large-video'].participantId;
|
||||
const participantIsInLargeVideoWithScreen
|
||||
= participant.id === largeVideoParticipantId && screenShares.includes(participant.id);
|
||||
|
||||
return participantIsInLargeVideoWithScreen;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue