fix(largeVideo): update don't depend on thumbnails

This commit is contained in:
Hristo Terezov 2020-04-14 17:41:30 -05:00
parent f972ebfe9e
commit 4fda428be1
11 changed files with 62 additions and 171 deletions

View File

@ -19,7 +19,6 @@ import {
createDeviceChangedEvent,
createStartSilentEvent,
createScreenSharingEvent,
createStreamSwitchDelayEvent,
createTrackMutedEvent,
sendAnalytics
} from './react/features/analytics';
@ -2263,18 +2262,6 @@ export default {
});
});
/* eslint-disable max-params */
APP.UI.addListener(
UIEvents.RESOLUTION_CHANGED,
(id, oldResolution, newResolution, delay) => {
sendAnalytics(createStreamSwitchDelayEvent(
{
'old_resolution': oldResolution,
'new_resolution': newResolution,
value: delay
}));
});
APP.UI.addListener(UIEvents.AUTH_CLICKED, () => {
AuthHandler.authenticate(room);
});

View File

@ -322,15 +322,6 @@ UI.inputDisplayNameHandler = function(newDisplayName) {
eventEmitter.emit(UIEvents.NICKNAME_CHANGED, newDisplayName);
};
/**
* Return the type of the remote video.
* @param jid the jid for the remote video
* @returns the video type video or screen.
*/
UI.getRemoteVideoType = function(jid) {
return VideoLayout.getRemoteVideoType(jid);
};
// FIXME check if someone user this
UI.showLoginPopup = function(callback) {
logger.log('password is required');

View File

@ -19,7 +19,6 @@ export default class SharedVideoThumb extends SmallVideo {
this.id = participant.id;
this.isLocal = false;
this.url = participant.id;
this.setVideoType(videoType);
this.videoSpanId = 'sharedVideoContainer';
this.container = this.createContainer(this.videoSpanId);
this.$container = $(this.container);

View File

@ -481,10 +481,6 @@ export default class RemoteVideo extends SmallVideo {
isVideo ? this.videoStream = stream : this.audioStream = stream;
if (isVideo) {
this.setVideoType(stream.videoType);
}
if (!stream.getOriginalStream()) {
logger.debug('Remote video stream has no original stream');

View File

@ -32,8 +32,6 @@ import {
const logger = require('jitsi-meet-logger').getLogger(__filename);
import UIEvents from '../../../service/UI/UIEvents';
/**
* Display mode constant used when video is being displayed on the small video.
* @type {number}
@ -158,28 +156,6 @@ export default class SmallVideo {
return this.$container.is(':visible');
}
/**
* Sets the type of the video displayed by this instance.
* Note that this is a string without clearly defined or checked values, and
* it is NOT one of the strings defined in service/RTC/VideoType in
* lib-jitsi-meet.
* @param videoType 'camera' or 'desktop', or 'sharedvideo'.
*/
setVideoType(videoType) {
this.videoType = videoType;
}
/**
* Returns the type of the video displayed by this instance.
* Note that this is a string without clearly defined or checked values, and
* it is NOT one of the strings defined in service/RTC/VideoType in
* lib-jitsi-meet.
* @returns {String} 'camera', 'screen', 'sharedvideo', or undefined.
*/
getVideoType() {
return this.videoType;
}
/**
* Creates an audio or video element for a particular MediaStream.
*/
@ -452,7 +428,7 @@ export default class SmallVideo {
* or <tt>false</tt> otherwise.
*/
isCurrentlyOnLargeVideo() {
return this.VideoLayout.isCurrentlyOnLarge(this.id);
return APP.store.getState()['features/large-video']?.participantId === this.id;
}
/**
@ -640,39 +616,6 @@ export default class SmallVideo {
this.updateIndicators();
}
/**
* Adds a listener for onresize events for this video, which will monitor for
* resolution changes, will calculate the delay since the moment the listened
* is added, and will fire a RESOLUTION_CHANGED event.
*/
waitForResolutionChange() {
const beforeChange = window.performance.now();
const videos = this.selectVideoElement();
if (!videos || !videos.length || videos.length <= 0) {
return;
}
const video = videos[0];
const oldWidth = video.videoWidth;
const oldHeight = video.videoHeight;
video.onresize = () => {
// eslint-disable-next-line eqeqeq
if (video.videoWidth != oldWidth || video.videoHeight != oldHeight) {
// Only run once.
video.onresize = null;
const delay = window.performance.now() - beforeChange;
const emitter = this.VideoLayout.getEventEmitter();
if (emitter) {
emitter.emit(UIEvents.RESOLUTION_CHANGED, this.getId(), `${oldWidth}x${oldHeight}`,
`${video.videoWidth}x${video.videoHeight}`, delay);
}
}
};
}
/**
* Initalizes any browser specific properties. Currently sets the overflow
* property for Qt browsers on Windows to hidden, thus fixing the following

View File

@ -1,12 +1,14 @@
/* global APP, $, interfaceConfig */
const logger = require('jitsi-meet-logger').getLogger(__filename);
import { VIDEO_TYPE } from '../../../react/features/base/media';
import { MEDIA_TYPE, VIDEO_TYPE } from '../../../react/features/base/media';
import {
getLocalParticipant as getLocalParticipantFromStore,
getPinnedParticipant,
getParticipantById,
pinParticipant
} from '../../../react/features/base/participants';
import { getTrackByMediaTypeAndParticipant } from '../../../react/features/base/tracks';
import { SHARED_VIDEO_CONTAINER_TYPE } from '../shared_video/SharedVideo';
import SharedVideoThumb from '../shared_video/SharedVideoThumb';
@ -73,9 +75,6 @@ const VideoLayout = {
emitter,
this._updateLargeVideoIfDisplayed.bind(this));
// sets default video type of local video
// FIXME container type is totally different thing from the video type
localVideoThumbnail.setVideoType(VIDEO_CONTAINER_TYPE);
this.registerListeners();
},
@ -221,10 +220,16 @@ const VideoLayout = {
* @returns {String} the video type video or screen.
*/
getRemoteVideoType(id) {
const smallVideo = VideoLayout.getSmallVideo(id);
const state = APP.store.getState();
const participant = getParticipantById(state, id);
if (participant?.isFakeParticipant) {
return SHARED_VIDEO_CONTAINER_TYPE;
}
return smallVideo ? smallVideo.getVideoType() : null;
const videoTrack = getTrackByMediaTypeAndParticipant(state['features/base/tracks'], MEDIA_TYPE.VIDEO, id);
return videoTrack?.videoType;
},
isPinned(id) {
@ -308,12 +313,6 @@ const VideoLayout = {
addRemoteVideoContainer(id, remoteVideo) {
remoteVideos[id] = remoteVideo;
if (!remoteVideo.getVideoType()) {
// make video type the default one (camera)
// FIXME container type is not a video type
remoteVideo.setVideoType(VIDEO_CONTAINER_TYPE);
}
// Initialize the view
remoteVideo.updateView();
},
@ -491,22 +490,6 @@ const VideoLayout = {
logger.info('Peer video type changed: ', id, newVideoType);
let smallVideo;
if (APP.conference.isLocalId(id)) {
if (!localVideoThumbnail) {
logger.warn('Local video not ready yet');
return;
}
smallVideo = localVideoThumbnail;
} else if (remoteVideos[id]) {
smallVideo = remoteVideos[id];
} else {
return;
}
smallVideo.setVideoType(newVideoType);
this._updateLargeVideoIfDisplayed(id, true);
},
@ -584,17 +567,16 @@ const VideoLayout = {
}
const currentContainer = largeVideo.getCurrentContainer();
const currentContainerType = largeVideo.getCurrentContainerType();
const currentId = largeVideo.id;
const isOnLarge = this.isCurrentlyOnLarge(id);
const smallVideo = this.getSmallVideo(id);
const state = APP.store.getState();
const videoTrack = getTrackByMediaTypeAndParticipant(state['features/base/tracks'], MEDIA_TYPE.VIDEO, id);
const videoStream = videoTrack?.jitsiTrack;
if (isOnLarge && !forceUpdate
&& LargeVideoManager.isVideoContainer(currentContainerType)
&& smallVideo) {
&& videoStream) {
const currentStreamId = currentContainer.getStreamID();
const newStreamId
= smallVideo.videoStream
? smallVideo.videoStream.getId() : null;
const newStreamId = videoStream?.getId() || null;
// FIXME it might be possible to get rid of 'forceUpdate' argument
if (currentStreamId !== newStreamId) {
@ -603,42 +585,17 @@ const VideoLayout = {
}
}
if ((!isOnLarge || forceUpdate) && smallVideo) {
if (!isOnLarge || forceUpdate) {
const videoType = this.getRemoteVideoType(id);
// FIXME video type is not the same thing as container type
if (id !== currentId && videoType === VIDEO_CONTAINER_TYPE) {
APP.API.notifyOnStageParticipantChanged(id);
}
let oldSmallVideo;
if (currentId) {
oldSmallVideo = this.getSmallVideo(currentId);
}
smallVideo.waitForResolutionChange();
if (oldSmallVideo) {
oldSmallVideo.waitForResolutionChange();
}
largeVideo.updateLargeVideo(
id,
smallVideo.videoStream,
videoStream,
videoType || VIDEO_TYPE.CAMERA
).then(() => {
// update current small video and the old one
smallVideo.updateView();
oldSmallVideo && oldSmallVideo.updateView();
}, () => {
// use clicked other video during update, nothing to do.
).catch(() => {
// do nothing
});
} else if (currentId) {
const currentSmallVideo = this.getSmallVideo(currentId);
currentSmallVideo && currentSmallVideo.updateView();
}
},
@ -723,10 +680,6 @@ const VideoLayout = {
this.localFlipX = val;
},
getEventEmitter() {
return eventEmitter;
},
/**
* Handles user's features changes.
*/

View File

@ -688,21 +688,6 @@ export function createStartMutedConfigurationEvent(
};
}
/**
* Creates an event which indicates the delay for switching between simulcast
* streams.
*
* @param {Object} attributes - Attributes to attach to the event.
* @returns {Object} The event in a format suitable for sending via
* sendAnalytics.
*/
export function createStreamSwitchDelayEvent(attributes) {
return {
action: 'stream.switch.delay',
attributes
};
}
/**
* Automatically changing the mute state of a media track in order to match
* the current stored state in redux.

View File

@ -129,6 +129,8 @@ MiddlewareRegistry.register(store => next => action => {
// TODO Remove the following calls to APP.UI once components interested
// in track mute changes are moved into React and/or redux.
if (typeof APP !== 'undefined') {
const result = next(action);
const { jitsiTrack } = action.track;
const muted = jitsiTrack.isMuted();
const participantID = jitsiTrack.getParticipantId();
@ -151,6 +153,8 @@ MiddlewareRegistry.register(store => next => action => {
} else {
APP.UI.setAudioMuted(participantID, muted);
}
return result;
}
}

View File

@ -1,7 +1,9 @@
// @flow
import { MEDIA_TYPE, VIDEO_TYPE } from '../base/media';
import { getLocalParticipant } from '../base/participants';
import { StateListenerRegistry } from '../base/redux';
import { getTrackByMediaTypeAndParticipant } from '../base/tracks';
import { appendSuffix } from '../display-name';
import { shouldDisplayTileView } from '../video-layout';
@ -37,3 +39,18 @@ StateListenerRegistry.register(
});
}
});
/**
* Updates the on stage participant value.
*/
StateListenerRegistry.register(
/* selector */ state => state['features/large-video'].participantId,
/* listener */ (participantId, store) => {
const videoTrack = getTrackByMediaTypeAndParticipant(
store.getState()['features/base/tracks'], MEDIA_TYPE.VIDEO, participantId);
if (videoTrack && videoTrack.videoType === VIDEO_TYPE.CAMERA) {
APP.API.notifyOnStageParticipantChanged(participantId);
}
}
);

View File

@ -2,6 +2,7 @@
import { StateListenerRegistry, equals } from '../base/redux';
import Filmstrip from '../../../modules/UI/videolayout/Filmstrip';
import VideoLayout from '../../../modules/UI/videolayout/VideoLayout';
import { getCurrentLayout, getTileViewGridDimensions, shouldDisplayTileView, LAYOUTS } from '../video-layout';
import { setHorizontalViewDimensions, setTileViewDimensions } from './actions';
@ -56,3 +57,22 @@ StateListenerRegistry.register(
break;
}
});
/**
* Handles on stage participant updates.
*/
StateListenerRegistry.register(
/* selector */ state => state['features/large-video'].participantId,
/* listener */ (participantId, store, oldParticipantId) => {
const newThumbnail = VideoLayout.getSmallVideo(participantId);
const oldThumbnail = VideoLayout.getSmallVideo(oldParticipantId);
if (newThumbnail) {
newThumbnail.updateView();
}
if (oldThumbnail) {
oldThumbnail.updateView();
}
}
);

View File

@ -53,10 +53,6 @@ export default {
*/
LOCAL_FLIPX_CHANGED: 'UI.local_flipx_changed',
// An event which indicates that the resolution of a remote video has
// changed.
RESOLUTION_CHANGED: 'UI.resolution_changed',
/**
* Notifies that the button "Cancel" is pressed on the dialog for
* external extension installation.