feat: Moves connectionquality to lib-jitsi-meet.

This commit is contained in:
Boris Grozev 2016-10-26 14:29:40 -05:00
parent 20e7c6d873
commit 051db50b3f
3 changed files with 11 additions and 233 deletions

View File

@ -4,18 +4,13 @@ import Invite from './modules/UI/invite/Invite';
import ContactList from './modules/UI/side_pannels/contactlist/ContactList';
import AuthHandler from './modules/UI/authentication/AuthHandler';
import ConnectionQuality from './modules/connectionquality/connectionquality';
import Recorder from './modules/recorder/Recorder';
import CQEvents from './service/connectionquality/CQEvents';
import UIEvents from './service/UI/UIEvents';
import mediaDeviceHelper from './modules/devices/mediaDeviceHelper';
import {reportError} from './modules/util/helpers';
import UIEvents from './service/UI/UIEvents';
import UIUtil from './modules/UI/util/UIUtil';
const ConnectionEvents = JitsiMeetJS.events.connection;
@ -27,6 +22,8 @@ const ConferenceErrors = JitsiMeetJS.errors.conference;
const TrackEvents = JitsiMeetJS.events.track;
const TrackErrors = JitsiMeetJS.errors.track;
const ConnectionQualityEvents = JitsiMeetJS.events.connectionQuality;
let room, connection, localAudio, localVideo;
/**
@ -769,7 +766,7 @@ export default {
* Returns the stats.
*/
getStats() {
return ConnectionQuality.getStats();
return room.connectionQuality.getStats();
},
// end used by torture
@ -1253,7 +1250,6 @@ export default {
room.on(ConferenceEvents.CONNECTION_INTERRUPTED, () => {
connectionIsInterrupted = true;
ConnectionQuality.updateLocalConnectionQuality(0);
APP.UI.showLocalConnectionInterrupted(true);
});
@ -1310,10 +1306,11 @@ export default {
});
}
// TODO: Move this to the library.
room.on(ConferenceEvents.CONNECTION_STATS, function (stats) {
// if we say video muted we will use old method of calculating
// quality and will not depend on localVideo if it is missing
ConnectionQuality.updateLocalStats(
room.connectionQuality.updateLocalStats(
stats,
connectionIsInterrupted,
localVideo ? localVideo.videoType : undefined,
@ -1321,9 +1318,11 @@ export default {
localVideo ? localVideo.resolution : null);
});
ConnectionQuality.addListener(CQEvents.LOCALSTATS_UPDATED,
room.on(ConnectionQualityEvents.LOCAL_STATS_UPDATED,
(percent, stats) => {
APP.UI.updateLocalStats(percent, stats);
// TODO: Move this to the library.
// Send only the data that remote participants care about.
let data = {
bitrate: stats.bitrate,
@ -1341,28 +1340,10 @@ export default {
}
});
room.on(ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
(participant, payload) => {
switch(payload.type) {
case this.commands.defaults.CONNECTION_QUALITY: {
let remoteVideo = participant.getTracks()
.find(tr => tr.isVideoTrack());
ConnectionQuality.updateRemoteStats(
participant.getId(),
payload.values,
remoteVideo ? remoteVideo.videoType : undefined,
remoteVideo ? remoteVideo.isMuted() : undefined);
break;
}
default:
console.warn("Unknown datachannel message", payload);
}
});
ConnectionQuality.addListener(CQEvents.REMOTESTATS_UPDATED,
room.on(ConnectionQualityEvents.REMOTE_STATS_UPDATED,
(id, percent, stats) => {
APP.UI.updateRemoteStats(id, percent, stats);
});
});
room.addCommandListener(this.commands.defaults.ETHERPAD, ({value}) => {
APP.UI.initEtherpad(value);

View File

@ -1,196 +0,0 @@
/* global config */
import EventEmitter from "events";
import CQEvents from "../../service/connectionquality/CQEvents";
const eventEmitter = new EventEmitter();
/**
* local stats
* @type {{}}
*/
var stats = {};
/**
* remote stats
* @type {{}}
*/
var remoteStats = {};
/**
* Quality percent( 100% - good, 0% - bad.) for the local user.
*/
var localConnectionQuality = 100;
/**
* Quality percent( 100% - good, 0% - bad.) stored per id.
*/
var remoteConnectionQuality = {};
/**
* Calculates the quality percent based on passed new and old value.
* @param newVal the new value
* @param oldVal the old value
*/
function calculateQuality(newVal, oldVal) {
return (newVal <= oldVal) ? newVal : (9*oldVal + newVal) / 10;
}
// webrtc table describing simulcast resolutions and used bandwidth
// https://chromium.googlesource.com/external/webrtc/+/master/webrtc/media/engine/simulcast.cc#42
const _bandwidthMap = [
{ width: 1920, height: 1080, layers:3, max: 5000, min: 800 },
{ width: 1280, height: 720, layers:3, max: 2500, min: 600 },
{ width: 960, height: 540, layers:3, max: 900, min: 450 },
{ width: 640, height: 360, layers:2, max: 700, min: 150 },
{ width: 480, height: 270, layers:2, max: 450, min: 150 },
{ width: 320, height: 180, layers:1, max: 200, min: 30 }
];
/**
* We disable quality calculations based on bandwidth if simulcast is disabled,
* or enable it in case of no simulcast and we force it.
* @type {boolean}
*/
const disableQualityBasedOnBandwidth =
config.forceQualityBasedOnBandwidth ? false : config.disableSimulcast;
/**
* Calculates the quality percentage based on the input resolution height and
* the upload reported by the client. The value is based on the interval from
* _bandwidthMap.
* @param inputHeight the resolution used to open the camera.
* @param upload the upload rate reported by client.
* @returns {int} the percent of upload based on _bandwidthMap and maximum value
* of 100, as values of the map are approximate and clients can stream above
* those values. Returns undefined if no result is found.
*/
function calculateQualityUsingUpload(inputHeight, upload) {
// found resolution from _bandwidthMap which height is equal or less than
// the inputHeight
let foundResolution = _bandwidthMap.find((r) => (r.height <= inputHeight));
if (!foundResolution)
return undefined;
if (upload <= foundResolution.min)
return 0;
return Math.min(
((upload - foundResolution.min)*100)
/ (foundResolution.max - foundResolution.min),
100);
}
export default {
/**
* Updates the local statistics
* @param data new statistics
* @param dontUpdateLocalConnectionQuality {boolean} if true -
* localConnectionQuality wont be recalculated.
* @param videoType the local video type
* @param isMuted current state of local video, whether it is muted
* @param resolution the current resolution used by local video
*/
updateLocalStats:
function (data, dontUpdateLocalConnectionQuality,
videoType, isMuted, resolution) {
stats = data;
if(!dontUpdateLocalConnectionQuality) {
let val = this._getNewQualityValue(
stats,
localConnectionQuality,
videoType,
isMuted,
resolution);
if (val !== undefined)
localConnectionQuality = val;
}
eventEmitter.emit(
CQEvents.LOCALSTATS_UPDATED, localConnectionQuality, stats);
},
/**
* Updates only the localConnectionQuality value
* @param values {int} the new value. should be from 0 - 100.
*/
updateLocalConnectionQuality: function (value) {
localConnectionQuality = value;
eventEmitter.emit(CQEvents.LOCALSTATS_UPDATED, localConnectionQuality,
stats);
},
/**
* Updates remote statistics
* @param id the id associated with the statistics
* @param data the statistics received
* @param remoteVideoType the video type of the remote video
* @param isRemoteVideoMuted whether remote video is muted
*/
updateRemoteStats:
function (id, data, remoteVideoType, isRemoteVideoMuted) {
if (!data ||
!("packetLoss" in data) ||
!("total" in data.packetLoss)) {
eventEmitter.emit(CQEvents.REMOTESTATS_UPDATED, id, null, null);
return;
}
let inputResolution = data.resolution;
// Use only the fields we need
data = {bitrate: data.bitrate, packetLoss: data.packetLoss};
remoteStats[id] = data;
let val = this._getNewQualityValue(
data,
remoteConnectionQuality[id],
remoteVideoType,
isRemoteVideoMuted,
inputResolution);
if (val !== undefined)
remoteConnectionQuality[id] = val;
eventEmitter.emit(
CQEvents.REMOTESTATS_UPDATED, id,
remoteConnectionQuality[id], remoteStats[id]);
},
/**
* Returns the new quality value based on the input parameters.
* Used to calculate remote and local values.
* @param data the data
* @param lastQualityValue the last value we calculated
* @param videoType need to check whether we are screen sharing
* @param isMuted is video muted
* @param resolution the input resolution used by the camera
* @returns {*} the newly calculated value or undefined if no result
* @private
*/
_getNewQualityValue:
function (data, lastQualityValue, videoType, isMuted, resolution) {
if (disableQualityBasedOnBandwidth
|| isMuted
|| videoType === 'desktop'
|| !resolution) {
return calculateQuality(
100 - data.packetLoss.total,
lastQualityValue || 100);
} else {
return calculateQualityUsingUpload(
resolution,
data.bitrate.upload);
}
},
/**
* Returns the local statistics.
*/
getStats: function () {
return stats;
},
addListener: function (type, listener) {
eventEmitter.on(type, listener);
}
};

View File

@ -1,7 +0,0 @@
var CQEvents = {
LOCALSTATS_UPDATED: "cq.localstats_updated",
REMOTESTATS_UPDATED: "cq.remotestats_updated",
STOP: "cq.stop"
};
module.exports = CQEvents;