@webex/plugin-meetings 3.3.1 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +7 -2
- package/dist/breakouts/index.js.map +1 -1
- package/dist/constants.js +11 -4
- package/dist/constants.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/selfUtils.js +0 -5
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/MediaConnectionAwaiter.js +70 -15
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/media/index.js +12 -0
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/connectionStateHandler.js +67 -0
- package/dist/meeting/connectionStateHandler.js.map +1 -0
- package/dist/meeting/index.js +552 -357
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +7 -0
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +6 -1
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/util.js +1 -0
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/index.js +4 -4
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +2 -2
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/util.js +17 -17
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +16 -16
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +1 -1
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +37 -33
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.js +8 -0
- package/dist/meetings/meetings.types.js.map +1 -1
- package/dist/meetings/util.js +3 -2
- package/dist/meetings/util.js.map +1 -1
- package/dist/metrics/constants.js +2 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +57 -0
- package/dist/metrics/index.js.map +1 -1
- package/dist/personal-meeting-room/index.js +1 -1
- package/dist/personal-meeting-room/index.js.map +1 -1
- package/dist/reachability/clusterReachability.js +108 -53
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +415 -56
- package/dist/reachability/index.js.map +1 -1
- package/dist/types/constants.d.ts +11 -3
- package/dist/types/media/MediaConnectionAwaiter.d.ts +24 -4
- package/dist/types/meeting/connectionStateHandler.d.ts +30 -0
- package/dist/types/meeting/index.d.ts +27 -7
- package/dist/types/meeting/locusMediaRequest.d.ts +2 -0
- package/dist/types/meeting-info/index.d.ts +3 -2
- package/dist/types/meeting-info/meeting-info-v2.d.ts +3 -2
- package/dist/types/meeting-info/util.d.ts +5 -4
- package/dist/types/meeting-info/utilv2.d.ts +3 -2
- package/dist/types/meetings/collection.d.ts +3 -2
- package/dist/types/meetings/index.d.ts +4 -3
- package/dist/types/meetings/meetings.types.d.ts +9 -0
- package/dist/types/metrics/constants.d.ts +1 -0
- package/dist/types/metrics/index.d.ts +15 -0
- package/dist/types/reachability/clusterReachability.d.ts +31 -3
- package/dist/types/reachability/index.d.ts +93 -2
- package/dist/webinar/index.js +1 -1
- package/package.json +23 -23
- package/src/breakouts/index.ts +7 -1
- package/src/constants.ts +13 -17
- package/src/locus-info/selfUtils.ts +0 -5
- package/src/media/MediaConnectionAwaiter.ts +89 -14
- package/src/media/index.ts +13 -0
- package/src/meeting/connectionStateHandler.ts +65 -0
- package/src/meeting/index.ts +526 -292
- package/src/meeting/locusMediaRequest.ts +5 -0
- package/src/meeting/muteState.ts +6 -1
- package/src/meeting/util.ts +1 -0
- package/src/meeting-info/index.ts +9 -6
- package/src/meeting-info/meeting-info-v2.ts +4 -4
- package/src/meeting-info/util.ts +23 -28
- package/src/meeting-info/utilv2.ts +18 -24
- package/src/meetings/collection.ts +3 -3
- package/src/meetings/index.ts +39 -40
- package/src/meetings/meetings.types.ts +11 -0
- package/src/meetings/util.ts +5 -4
- package/src/metrics/constants.ts +1 -0
- package/src/metrics/index.ts +44 -0
- package/src/personal-meeting-room/index.ts +2 -2
- package/src/reachability/clusterReachability.ts +86 -25
- package/src/reachability/index.ts +316 -27
- package/test/unit/spec/breakouts/index.ts +51 -32
- package/test/unit/spec/locus-info/selfUtils.js +25 -23
- package/test/unit/spec/media/MediaConnectionAwaiter.ts +131 -32
- package/test/unit/spec/media/index.ts +42 -27
- package/test/unit/spec/meeting/connectionStateHandler.ts +102 -0
- package/test/unit/spec/meeting/index.js +758 -179
- package/test/unit/spec/meeting/locusMediaRequest.ts +7 -0
- package/test/unit/spec/meeting/muteState.js +24 -0
- package/test/unit/spec/meeting-info/index.js +4 -4
- package/test/unit/spec/meeting-info/meetinginfov2.js +24 -28
- package/test/unit/spec/meeting-info/request.js +2 -2
- package/test/unit/spec/meeting-info/utilv2.js +41 -49
- package/test/unit/spec/meetings/index.js +14 -0
- package/test/unit/spec/metrics/index.js +126 -0
- package/test/unit/spec/multistream/mediaRequestManager.ts +2 -2
- package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -2
- package/test/unit/spec/reachability/clusterReachability.ts +116 -22
- package/test/unit/spec/reachability/index.ts +1153 -84
- package/test/unit/spec/rtcMetrics/index.ts +1 -0
- package/dist/mediaQualityMetrics/config.js +0 -321
- package/dist/mediaQualityMetrics/config.js.map +0 -1
- package/dist/statsAnalyzer/global.js +0 -44
- package/dist/statsAnalyzer/global.js.map +0 -1
- package/dist/statsAnalyzer/index.js +0 -1072
- package/dist/statsAnalyzer/index.js.map +0 -1
- package/dist/statsAnalyzer/mqaUtil.js +0 -368
- package/dist/statsAnalyzer/mqaUtil.js.map +0 -1
- package/dist/types/mediaQualityMetrics/config.d.ts +0 -247
- package/dist/types/statsAnalyzer/global.d.ts +0 -36
- package/dist/types/statsAnalyzer/index.d.ts +0 -217
- package/dist/types/statsAnalyzer/mqaUtil.d.ts +0 -48
- package/src/mediaQualityMetrics/config.ts +0 -255
- package/src/statsAnalyzer/global.ts +0 -37
- package/src/statsAnalyzer/index.ts +0 -1318
- package/src/statsAnalyzer/mqaUtil.ts +0 -463
- package/test/unit/spec/stats-analyzer/index.js +0 -1819
|
@@ -1,1072 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _Reflect$construct = require("@babel/runtime-corejs2/core-js/reflect/construct");
|
|
4
|
-
var _Object$keys2 = require("@babel/runtime-corejs2/core-js/object/keys");
|
|
5
|
-
var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs2/core-js/object/get-own-property-symbols");
|
|
6
|
-
var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor");
|
|
7
|
-
var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptors");
|
|
8
|
-
var _Object$defineProperties = require("@babel/runtime-corejs2/core-js/object/define-properties");
|
|
9
|
-
var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
|
|
10
|
-
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
|
|
11
|
-
_Object$defineProperty(exports, "__esModule", {
|
|
12
|
-
value: true
|
|
13
|
-
});
|
|
14
|
-
exports.StatsAnalyzer = exports.EVENTS = void 0;
|
|
15
|
-
var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
|
|
16
|
-
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
|
|
17
|
-
var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify"));
|
|
18
|
-
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
|
|
19
|
-
var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
|
|
20
|
-
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/assertThisInitialized"));
|
|
21
|
-
var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/inherits"));
|
|
22
|
-
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/possibleConstructorReturn"));
|
|
23
|
-
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/getPrototypeOf"));
|
|
24
|
-
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
|
|
25
|
-
var _lodash = require("lodash");
|
|
26
|
-
var _internalMediaCore = require("@webex/internal-media-core");
|
|
27
|
-
var _eventsScope = _interopRequireDefault(require("../common/events/events-scope"));
|
|
28
|
-
var _constants = require("../constants");
|
|
29
|
-
var _config = require("../mediaQualityMetrics/config");
|
|
30
|
-
var _loggerProxy = _interopRequireDefault(require("../common/logs/logger-proxy"));
|
|
31
|
-
var _global = _interopRequireDefault(require("./global"));
|
|
32
|
-
var _mqaUtil = require("./mqaUtil");
|
|
33
|
-
function ownKeys(e, r) { var t = _Object$keys2(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
34
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
35
|
-
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = _Reflect$construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
|
|
36
|
-
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } /* eslint-disable prefer-destructuring */
|
|
37
|
-
var EVENTS = exports.EVENTS = {
|
|
38
|
-
MEDIA_QUALITY: 'MEDIA_QUALITY',
|
|
39
|
-
LOCAL_MEDIA_STARTED: 'LOCAL_MEDIA_STARTED',
|
|
40
|
-
LOCAL_MEDIA_STOPPED: 'LOCAL_MEDIA_STOPPED',
|
|
41
|
-
REMOTE_MEDIA_STARTED: 'REMOTE_MEDIA_STARTED',
|
|
42
|
-
REMOTE_MEDIA_STOPPED: 'REMOTE_MEDIA_STOPPED'
|
|
43
|
-
};
|
|
44
|
-
var emptySender = {
|
|
45
|
-
trackLabel: '',
|
|
46
|
-
maxPacketLossRatio: 0,
|
|
47
|
-
availableBandwidth: 0,
|
|
48
|
-
bytesSent: 0,
|
|
49
|
-
meanRemoteJitter: [],
|
|
50
|
-
meanRoundTripTime: []
|
|
51
|
-
};
|
|
52
|
-
var emptyReceiver = {
|
|
53
|
-
availableBandwidth: 0,
|
|
54
|
-
bytesReceived: 0,
|
|
55
|
-
meanRtpJitter: [],
|
|
56
|
-
meanRoundTripTime: []
|
|
57
|
-
};
|
|
58
|
-
/**
|
|
59
|
-
* Stats Analyzer class that will emit events based on detected quality
|
|
60
|
-
*
|
|
61
|
-
* @export
|
|
62
|
-
* @class StatsAnalyzer
|
|
63
|
-
* @extends {EventsScope}
|
|
64
|
-
*/
|
|
65
|
-
var StatsAnalyzer = exports.StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
|
|
66
|
-
(0, _inherits2.default)(StatsAnalyzer, _EventsScope);
|
|
67
|
-
var _super = _createSuper(StatsAnalyzer);
|
|
68
|
-
/**
|
|
69
|
-
* Creates a new instance of StatsAnalyzer
|
|
70
|
-
* @constructor
|
|
71
|
-
* @public
|
|
72
|
-
* @param {Object} config SDK Configuration Object
|
|
73
|
-
* @param {Function} receiveSlotCallback Callback used to access receive slots.
|
|
74
|
-
* @param {Object} networkQualityMonitor class for assessing network characteristics (jitter, packetLoss, latency)
|
|
75
|
-
* @param {Object} statsResults Default properties for stats
|
|
76
|
-
*/
|
|
77
|
-
function StatsAnalyzer(config) {
|
|
78
|
-
var _this;
|
|
79
|
-
var receiveSlotCallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
|
|
80
|
-
return undefined;
|
|
81
|
-
};
|
|
82
|
-
var networkQualityMonitor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
83
|
-
var statsResults = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : _global.default;
|
|
84
|
-
(0, _classCallCheck2.default)(this, StatsAnalyzer);
|
|
85
|
-
_this = _super.call(this);
|
|
86
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "config", void 0);
|
|
87
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "correlationId", void 0);
|
|
88
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "lastEmittedStartStopEvent", void 0);
|
|
89
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "lastMqaDataSent", void 0);
|
|
90
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "lastStatsResults", void 0);
|
|
91
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "meetingMediaStatus", void 0);
|
|
92
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "mqaInterval", void 0);
|
|
93
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "mqaSentCount", void 0);
|
|
94
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "networkQualityMonitor", void 0);
|
|
95
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "mediaConnection", void 0);
|
|
96
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "statsInterval", void 0);
|
|
97
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "statsResults", void 0);
|
|
98
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "statsStarted", void 0);
|
|
99
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "successfulCandidatePair", void 0);
|
|
100
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "localIpAddress", void 0);
|
|
101
|
-
// Returns the local IP address for diagnostics. this is the local IP of the interface used for the current media connection a host can have many local Ip Addresses
|
|
102
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "receiveSlotCallback", void 0);
|
|
103
|
-
/**
|
|
104
|
-
* emits started/stopped events for local/remote media by checking
|
|
105
|
-
* if given values are increasing or not. The previousValue, currentValue
|
|
106
|
-
* params can be any numerical value like number of receive packets or
|
|
107
|
-
* decoded frames, etc.
|
|
108
|
-
*
|
|
109
|
-
* @private
|
|
110
|
-
* @param {string} mediaType
|
|
111
|
-
* @param {number} previousValue - value to compare
|
|
112
|
-
* @param {number} currentValue - value to compare (must be same type of value as previousValue)
|
|
113
|
-
* @param {boolean} isLocal - true if stats are for local media being sent out, false for remote media being received
|
|
114
|
-
* @memberof StatsAnalyzer
|
|
115
|
-
* @returns {void}
|
|
116
|
-
*/
|
|
117
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "emitStartStopEvents", function (mediaType, previousValue, currentValue, isLocal) {
|
|
118
|
-
if (mediaType !== 'audio' && mediaType !== 'video' && mediaType !== 'share') {
|
|
119
|
-
throw new Error("Unsupported mediaType: ".concat(mediaType));
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// eslint-disable-next-line no-param-reassign
|
|
123
|
-
if (previousValue === undefined) previousValue = 0;
|
|
124
|
-
// eslint-disable-next-line no-param-reassign
|
|
125
|
-
if (currentValue === undefined) currentValue = 0;
|
|
126
|
-
if (!_this.lastEmittedStartStopEvent[mediaType]) {
|
|
127
|
-
_this.lastEmittedStartStopEvent[mediaType] = {};
|
|
128
|
-
}
|
|
129
|
-
var lastEmittedEvent = isLocal ? _this.lastEmittedStartStopEvent[mediaType].local : _this.lastEmittedStartStopEvent[mediaType].remote;
|
|
130
|
-
var newEvent;
|
|
131
|
-
if (currentValue - previousValue > 0) {
|
|
132
|
-
newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STARTED : EVENTS.REMOTE_MEDIA_STARTED;
|
|
133
|
-
} else if (currentValue === previousValue && currentValue > 0) {
|
|
134
|
-
newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STOPPED : EVENTS.REMOTE_MEDIA_STOPPED;
|
|
135
|
-
}
|
|
136
|
-
if (newEvent && lastEmittedEvent !== newEvent) {
|
|
137
|
-
if (isLocal) {
|
|
138
|
-
_this.lastEmittedStartStopEvent[mediaType].local = newEvent;
|
|
139
|
-
} else {
|
|
140
|
-
_this.lastEmittedStartStopEvent[mediaType].remote = newEvent;
|
|
141
|
-
}
|
|
142
|
-
_this.emit({
|
|
143
|
-
file: 'statsAnalyzer/index',
|
|
144
|
-
function: 'compareLastStatsResult'
|
|
145
|
-
}, newEvent, {
|
|
146
|
-
type: mediaType
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
/**
|
|
151
|
-
* extracts the local Ip address from the statsResult object by looking at stats results candidates
|
|
152
|
-
* and matches that ID with the successful candidate pair. It looks at the type of local candidate it is
|
|
153
|
-
* and then extracts the IP address from the relatedAddress or address property based on conditions known in webrtc
|
|
154
|
-
* note, there are known incompatibilities and it is possible for this to set undefined, or for the IP address to be the public IP address
|
|
155
|
-
* for example, firefox does not set the relayProtocol, and if the user is behind a NAT it might be the public IP
|
|
156
|
-
* @private
|
|
157
|
-
* @param {string} successfulCandidatePairId - The ID of the successful candidate pair.
|
|
158
|
-
* @param {Object} candidates - the stats result candidates
|
|
159
|
-
* @returns {void}
|
|
160
|
-
*/
|
|
161
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "extractAndSetLocalIpAddressInfoForDiagnostics", function (successfulCandidatePairId, candidates) {
|
|
162
|
-
var newIpAddress = '';
|
|
163
|
-
if (successfulCandidatePairId && !(0, _lodash.isEmpty)(candidates)) {
|
|
164
|
-
var localCandidate = candidates[successfulCandidatePairId];
|
|
165
|
-
if (localCandidate) {
|
|
166
|
-
if (localCandidate.candidateType === 'host') {
|
|
167
|
-
// if it's a host candidate, use the address property - it will be the local IP
|
|
168
|
-
newIpAddress = "".concat(localCandidate.address);
|
|
169
|
-
} else if (localCandidate.candidateType === 'prflx') {
|
|
170
|
-
// if it's a peer reflexive candidate and we're not using a relay (there is no relayProtocol set)
|
|
171
|
-
// then look at the relatedAddress - it will be the local
|
|
172
|
-
//
|
|
173
|
-
// Firefox doesn't populate the relayProtocol property
|
|
174
|
-
if (!localCandidate.relayProtocol) {
|
|
175
|
-
newIpAddress = "".concat(localCandidate.relatedAddress);
|
|
176
|
-
} else {
|
|
177
|
-
// if it's a peer reflexive candidate and we are using a relay -
|
|
178
|
-
// in that case the relatedAddress will be the IP of the TURN server (Linus),
|
|
179
|
-
// so we can only look at the address, but it might be local IP or public IP,
|
|
180
|
-
// depending on if the user is behind a NAT or not
|
|
181
|
-
newIpAddress = "".concat(localCandidate.address);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
_this.localIpAddress = newIpAddress;
|
|
187
|
-
});
|
|
188
|
-
/**
|
|
189
|
-
* Processes remote and local candidate result and stores
|
|
190
|
-
* @private
|
|
191
|
-
* @param {*} result
|
|
192
|
-
* @param {*} type
|
|
193
|
-
* @param {boolean} isSender
|
|
194
|
-
* @param {boolean} isRemote
|
|
195
|
-
*
|
|
196
|
-
* @returns {void}
|
|
197
|
-
*/
|
|
198
|
-
(0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "parseCandidate", function (result, type, isSender, isRemote) {
|
|
199
|
-
var _this$successfulCandi;
|
|
200
|
-
if (!result || !result.id) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// We only care about the successful local candidate
|
|
205
|
-
if (((_this$successfulCandi = _this.successfulCandidatePair) === null || _this$successfulCandi === void 0 ? void 0 : _this$successfulCandi.localCandidateId) !== result.id) {
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
var transport;
|
|
209
|
-
if (result.relayProtocol) {
|
|
210
|
-
transport = result.relayProtocol.toUpperCase();
|
|
211
|
-
} else if (result.protocol) {
|
|
212
|
-
transport = result.protocol.toUpperCase();
|
|
213
|
-
}
|
|
214
|
-
var sendRecvType = isSender ? _constants.STATS.SEND_DIRECTION : _constants.STATS.RECEIVE_DIRECTION;
|
|
215
|
-
var ipType = isRemote ? _constants.STATS.REMOTE : _constants.STATS.LOCAL;
|
|
216
|
-
if (!_this.statsResults.candidates) {
|
|
217
|
-
_this.statsResults.candidates = {};
|
|
218
|
-
}
|
|
219
|
-
_this.statsResults.candidates[result.id] = {
|
|
220
|
-
candidateType: result.candidateType,
|
|
221
|
-
ipAddress: result.ip,
|
|
222
|
-
// TODO: add ports
|
|
223
|
-
relatedAddress: result.relatedAddress,
|
|
224
|
-
relatedPort: result.relatedPort,
|
|
225
|
-
relayProtocol: result.relayProtocol,
|
|
226
|
-
protocol: result.protocol,
|
|
227
|
-
address: result.address,
|
|
228
|
-
portNumber: result.port,
|
|
229
|
-
networkType: result.networkType,
|
|
230
|
-
priority: result.priority,
|
|
231
|
-
transport: transport,
|
|
232
|
-
timestamp: result.time,
|
|
233
|
-
id: result.id,
|
|
234
|
-
type: result.type
|
|
235
|
-
};
|
|
236
|
-
_this.statsResults.connectionType[ipType].candidateType = result.candidateType;
|
|
237
|
-
_this.statsResults.connectionType[ipType].ipAddress = result.ipAddress;
|
|
238
|
-
_this.statsResults.connectionType[ipType].networkType = result.networkType === _constants.NETWORK_TYPE.VPN ? _constants.NETWORK_TYPE.UNKNOWN : result.networkType;
|
|
239
|
-
_this.statsResults.connectionType[ipType].transport = transport;
|
|
240
|
-
_this.statsResults[type][sendRecvType].totalRoundTripTime = result.totalRoundTripTime;
|
|
241
|
-
});
|
|
242
|
-
_this.statsStarted = false;
|
|
243
|
-
_this.statsResults = statsResults;
|
|
244
|
-
_this.lastStatsResults = null;
|
|
245
|
-
_this.config = config;
|
|
246
|
-
_this.networkQualityMonitor = networkQualityMonitor;
|
|
247
|
-
_this.correlationId = config.correlationId;
|
|
248
|
-
_this.mqaSentCount = -1;
|
|
249
|
-
_this.lastMqaDataSent = {};
|
|
250
|
-
_this.lastEmittedStartStopEvent = {};
|
|
251
|
-
_this.receiveSlotCallback = receiveSlotCallback;
|
|
252
|
-
_this.successfulCandidatePair = {};
|
|
253
|
-
_this.localIpAddress = '';
|
|
254
|
-
return _this;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Resets cumulative stats arrays.
|
|
259
|
-
*
|
|
260
|
-
* @public
|
|
261
|
-
* @memberof StatsAnalyzer
|
|
262
|
-
* @returns {void}
|
|
263
|
-
*/
|
|
264
|
-
(0, _createClass2.default)(StatsAnalyzer, [{
|
|
265
|
-
key: "resetStatsResults",
|
|
266
|
-
value: function resetStatsResults() {
|
|
267
|
-
var _this2 = this;
|
|
268
|
-
(0, _keys.default)(this.statsResults).forEach(function (mediaType) {
|
|
269
|
-
if (mediaType.includes('recv')) {
|
|
270
|
-
_this2.statsResults[mediaType].recv.meanRtpJitter = [];
|
|
271
|
-
}
|
|
272
|
-
if (mediaType.includes('send')) {
|
|
273
|
-
_this2.statsResults[mediaType].send.meanRemoteJitter = [];
|
|
274
|
-
_this2.statsResults[mediaType].send.meanRoundTripTime = [];
|
|
275
|
-
}
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* sets mediaStatus status for analyzing metrics
|
|
281
|
-
*
|
|
282
|
-
* @public
|
|
283
|
-
* @param {Object} status for the audio and video
|
|
284
|
-
* @memberof StatsAnalyzer
|
|
285
|
-
* @returns {void}
|
|
286
|
-
*/
|
|
287
|
-
}, {
|
|
288
|
-
key: "updateMediaStatus",
|
|
289
|
-
value: function updateMediaStatus(status) {
|
|
290
|
-
var _this$meetingMediaSta, _this$meetingMediaSta2;
|
|
291
|
-
this.meetingMediaStatus = {
|
|
292
|
-
actual: _objectSpread(_objectSpread({}, (_this$meetingMediaSta = this.meetingMediaStatus) === null || _this$meetingMediaSta === void 0 ? void 0 : _this$meetingMediaSta.actual), status === null || status === void 0 ? void 0 : status.actual),
|
|
293
|
-
expected: _objectSpread(_objectSpread({}, (_this$meetingMediaSta2 = this.meetingMediaStatus) === null || _this$meetingMediaSta2 === void 0 ? void 0 : _this$meetingMediaSta2.expected), status === null || status === void 0 ? void 0 : status.expected)
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* captures MQA data from media connection
|
|
299
|
-
*
|
|
300
|
-
* @public
|
|
301
|
-
* @memberof StatsAnalyzer
|
|
302
|
-
* @returns {void}
|
|
303
|
-
*/
|
|
304
|
-
}, {
|
|
305
|
-
key: "sendMqaData",
|
|
306
|
-
value: function sendMqaData() {
|
|
307
|
-
var _this3 = this;
|
|
308
|
-
var newMqa = (0, _lodash.cloneDeep)(_config.emptyMqaInterval);
|
|
309
|
-
|
|
310
|
-
// Fill in empty stats items for lastMqaDataSent
|
|
311
|
-
(0, _keys.default)(this.statsResults).forEach(function (mediaType) {
|
|
312
|
-
if (!_this3.lastMqaDataSent[mediaType]) {
|
|
313
|
-
_this3.lastMqaDataSent[mediaType] = {};
|
|
314
|
-
}
|
|
315
|
-
if (!_this3.lastMqaDataSent[mediaType].send && mediaType.includes('-send')) {
|
|
316
|
-
_this3.lastMqaDataSent[mediaType].send = {};
|
|
317
|
-
}
|
|
318
|
-
if (!_this3.lastMqaDataSent[mediaType].recv && mediaType.includes('-recv')) {
|
|
319
|
-
_this3.lastMqaDataSent[mediaType].recv = {};
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
// Create stats the first level, totals for senders and receivers
|
|
324
|
-
var audioSender = (0, _lodash.cloneDeep)(_config.emptyAudioTransmit);
|
|
325
|
-
var audioShareSender = (0, _lodash.cloneDeep)(_config.emptyAudioTransmit);
|
|
326
|
-
var audioReceiver = (0, _lodash.cloneDeep)(_config.emptyAudioReceive);
|
|
327
|
-
var audioShareReceiver = (0, _lodash.cloneDeep)(_config.emptyAudioReceive);
|
|
328
|
-
var videoSender = (0, _lodash.cloneDeep)(_config.emptyVideoTransmit);
|
|
329
|
-
var videoShareSender = (0, _lodash.cloneDeep)(_config.emptyVideoTransmit);
|
|
330
|
-
var videoReceiver = (0, _lodash.cloneDeep)(_config.emptyVideoReceive);
|
|
331
|
-
var videoShareReceiver = (0, _lodash.cloneDeep)(_config.emptyVideoReceive);
|
|
332
|
-
(0, _mqaUtil.getAudioSenderMqa)({
|
|
333
|
-
audioSender: audioSender,
|
|
334
|
-
statsResults: this.statsResults,
|
|
335
|
-
lastMqaDataSent: this.lastMqaDataSent,
|
|
336
|
-
baseMediaType: 'audio-send'
|
|
337
|
-
});
|
|
338
|
-
newMqa.audioTransmit.push(audioSender);
|
|
339
|
-
(0, _mqaUtil.getAudioSenderMqa)({
|
|
340
|
-
audioSender: audioShareSender,
|
|
341
|
-
statsResults: this.statsResults,
|
|
342
|
-
lastMqaDataSent: this.lastMqaDataSent,
|
|
343
|
-
baseMediaType: 'audio-share-send'
|
|
344
|
-
});
|
|
345
|
-
newMqa.audioTransmit.push(audioShareSender);
|
|
346
|
-
(0, _mqaUtil.getAudioReceiverMqa)({
|
|
347
|
-
audioReceiver: audioReceiver,
|
|
348
|
-
statsResults: this.statsResults,
|
|
349
|
-
lastMqaDataSent: this.lastMqaDataSent,
|
|
350
|
-
baseMediaType: 'audio-recv'
|
|
351
|
-
});
|
|
352
|
-
newMqa.audioReceive.push(audioReceiver);
|
|
353
|
-
(0, _mqaUtil.getAudioReceiverMqa)({
|
|
354
|
-
audioReceiver: audioShareReceiver,
|
|
355
|
-
statsResults: this.statsResults,
|
|
356
|
-
lastMqaDataSent: this.lastMqaDataSent,
|
|
357
|
-
baseMediaType: 'audio-share-recv'
|
|
358
|
-
});
|
|
359
|
-
newMqa.audioReceive.push(audioShareReceiver);
|
|
360
|
-
(0, _mqaUtil.getVideoSenderMqa)({
|
|
361
|
-
videoSender: videoSender,
|
|
362
|
-
statsResults: this.statsResults,
|
|
363
|
-
lastMqaDataSent: this.lastMqaDataSent,
|
|
364
|
-
baseMediaType: 'video-send'
|
|
365
|
-
});
|
|
366
|
-
newMqa.videoTransmit.push(videoSender);
|
|
367
|
-
(0, _mqaUtil.getVideoSenderMqa)({
|
|
368
|
-
videoSender: videoShareSender,
|
|
369
|
-
statsResults: this.statsResults,
|
|
370
|
-
lastMqaDataSent: this.lastMqaDataSent,
|
|
371
|
-
baseMediaType: 'video-share-send'
|
|
372
|
-
});
|
|
373
|
-
newMqa.videoTransmit.push(videoShareSender);
|
|
374
|
-
(0, _mqaUtil.getVideoReceiverMqa)({
|
|
375
|
-
videoReceiver: videoReceiver,
|
|
376
|
-
statsResults: this.statsResults,
|
|
377
|
-
lastMqaDataSent: this.lastMqaDataSent,
|
|
378
|
-
baseMediaType: 'video-recv'
|
|
379
|
-
});
|
|
380
|
-
newMqa.videoReceive.push(videoReceiver);
|
|
381
|
-
(0, _mqaUtil.getVideoReceiverMqa)({
|
|
382
|
-
videoReceiver: videoShareReceiver,
|
|
383
|
-
statsResults: this.statsResults,
|
|
384
|
-
lastMqaDataSent: this.lastMqaDataSent,
|
|
385
|
-
baseMediaType: 'video-share-recv'
|
|
386
|
-
});
|
|
387
|
-
newMqa.videoReceive.push(videoShareReceiver);
|
|
388
|
-
|
|
389
|
-
// Add stats for individual streams
|
|
390
|
-
(0, _keys.default)(this.statsResults).forEach(function (mediaType) {
|
|
391
|
-
if (mediaType.startsWith('audio-send')) {
|
|
392
|
-
var audioSenderStream = (0, _lodash.cloneDeep)(_config.emptyAudioTransmitStream);
|
|
393
|
-
(0, _mqaUtil.getAudioSenderStreamMqa)({
|
|
394
|
-
audioSenderStream: audioSenderStream,
|
|
395
|
-
statsResults: _this3.statsResults,
|
|
396
|
-
lastMqaDataSent: _this3.lastMqaDataSent,
|
|
397
|
-
mediaType: mediaType
|
|
398
|
-
});
|
|
399
|
-
newMqa.audioTransmit[0].streams.push(audioSenderStream);
|
|
400
|
-
_this3.lastMqaDataSent[mediaType].send = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].send);
|
|
401
|
-
} else if (mediaType.startsWith('audio-share-send')) {
|
|
402
|
-
var _audioSenderStream = (0, _lodash.cloneDeep)(_config.emptyAudioTransmitStream);
|
|
403
|
-
(0, _mqaUtil.getAudioSenderStreamMqa)({
|
|
404
|
-
audioSenderStream: _audioSenderStream,
|
|
405
|
-
statsResults: _this3.statsResults,
|
|
406
|
-
lastMqaDataSent: _this3.lastMqaDataSent,
|
|
407
|
-
mediaType: mediaType
|
|
408
|
-
});
|
|
409
|
-
newMqa.audioTransmit[1].streams.push(_audioSenderStream);
|
|
410
|
-
_this3.lastMqaDataSent[mediaType].send = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].send);
|
|
411
|
-
} else if (mediaType.startsWith('audio-recv')) {
|
|
412
|
-
var audioReceiverStream = (0, _lodash.cloneDeep)(_config.emptyAudioReceiveStream);
|
|
413
|
-
(0, _mqaUtil.getAudioReceiverStreamMqa)({
|
|
414
|
-
audioReceiverStream: audioReceiverStream,
|
|
415
|
-
statsResults: _this3.statsResults,
|
|
416
|
-
lastMqaDataSent: _this3.lastMqaDataSent,
|
|
417
|
-
mediaType: mediaType
|
|
418
|
-
});
|
|
419
|
-
newMqa.audioReceive[0].streams.push(audioReceiverStream);
|
|
420
|
-
_this3.lastMqaDataSent[mediaType].recv = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].recv);
|
|
421
|
-
} else if (mediaType.startsWith('audio-share-recv')) {
|
|
422
|
-
var _audioReceiverStream = (0, _lodash.cloneDeep)(_config.emptyAudioReceiveStream);
|
|
423
|
-
(0, _mqaUtil.getAudioReceiverStreamMqa)({
|
|
424
|
-
audioReceiverStream: _audioReceiverStream,
|
|
425
|
-
statsResults: _this3.statsResults,
|
|
426
|
-
lastMqaDataSent: _this3.lastMqaDataSent,
|
|
427
|
-
mediaType: mediaType
|
|
428
|
-
});
|
|
429
|
-
newMqa.audioReceive[1].streams.push(_audioReceiverStream);
|
|
430
|
-
_this3.lastMqaDataSent[mediaType].recv = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].recv);
|
|
431
|
-
} else if (mediaType.startsWith('video-send-layer')) {
|
|
432
|
-
// We only want the stream-specific stats we get with video-send-layer-0, video-send-layer-1, etc.
|
|
433
|
-
var videoSenderStream = (0, _lodash.cloneDeep)(_config.emptyVideoTransmitStream);
|
|
434
|
-
(0, _mqaUtil.getVideoSenderStreamMqa)({
|
|
435
|
-
videoSenderStream: videoSenderStream,
|
|
436
|
-
statsResults: _this3.statsResults,
|
|
437
|
-
lastMqaDataSent: _this3.lastMqaDataSent,
|
|
438
|
-
mediaType: mediaType
|
|
439
|
-
});
|
|
440
|
-
newMqa.videoTransmit[0].streams.push(videoSenderStream);
|
|
441
|
-
_this3.lastMqaDataSent[mediaType].send = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].send);
|
|
442
|
-
} else if (mediaType.startsWith('video-share-send')) {
|
|
443
|
-
var _videoSenderStream = (0, _lodash.cloneDeep)(_config.emptyVideoTransmitStream);
|
|
444
|
-
(0, _mqaUtil.getVideoSenderStreamMqa)({
|
|
445
|
-
videoSenderStream: _videoSenderStream,
|
|
446
|
-
statsResults: _this3.statsResults,
|
|
447
|
-
lastMqaDataSent: _this3.lastMqaDataSent,
|
|
448
|
-
mediaType: mediaType
|
|
449
|
-
});
|
|
450
|
-
newMqa.videoTransmit[1].streams.push(_videoSenderStream);
|
|
451
|
-
_this3.lastMqaDataSent[mediaType].send = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].send);
|
|
452
|
-
} else if (mediaType.startsWith('video-recv')) {
|
|
453
|
-
var videoReceiverStream = (0, _lodash.cloneDeep)(_config.emptyVideoReceiveStream);
|
|
454
|
-
(0, _mqaUtil.getVideoReceiverStreamMqa)({
|
|
455
|
-
videoReceiverStream: videoReceiverStream,
|
|
456
|
-
statsResults: _this3.statsResults,
|
|
457
|
-
lastMqaDataSent: _this3.lastMqaDataSent,
|
|
458
|
-
mediaType: mediaType
|
|
459
|
-
});
|
|
460
|
-
newMqa.videoReceive[0].streams.push(videoReceiverStream);
|
|
461
|
-
_this3.lastMqaDataSent[mediaType].recv = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].recv);
|
|
462
|
-
} else if (mediaType.startsWith('video-share-recv')) {
|
|
463
|
-
var _videoReceiverStream = (0, _lodash.cloneDeep)(_config.emptyVideoReceiveStream);
|
|
464
|
-
(0, _mqaUtil.getVideoReceiverStreamMqa)({
|
|
465
|
-
videoReceiverStream: _videoReceiverStream,
|
|
466
|
-
statsResults: _this3.statsResults,
|
|
467
|
-
lastMqaDataSent: _this3.lastMqaDataSent,
|
|
468
|
-
mediaType: mediaType
|
|
469
|
-
});
|
|
470
|
-
newMqa.videoReceive[1].streams.push(_videoReceiverStream);
|
|
471
|
-
_this3.lastMqaDataSent[mediaType].recv = (0, _lodash.cloneDeep)(_this3.statsResults[mediaType].recv);
|
|
472
|
-
}
|
|
473
|
-
});
|
|
474
|
-
newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress;
|
|
475
|
-
|
|
476
|
-
// Adding peripheral information
|
|
477
|
-
newMqa.intervalMetadata.peripherals.push({
|
|
478
|
-
information: _constants._UNKNOWN_,
|
|
479
|
-
name: _constants.MEDIA_DEVICES.SPEAKER
|
|
480
|
-
});
|
|
481
|
-
if (this.statsResults['audio-send']) {
|
|
482
|
-
newMqa.intervalMetadata.peripherals.push({
|
|
483
|
-
information: this.statsResults['audio-send'].trackLabel || _constants._UNKNOWN_,
|
|
484
|
-
name: _constants.MEDIA_DEVICES.MICROPHONE
|
|
485
|
-
});
|
|
486
|
-
}
|
|
487
|
-
var existingVideoSender = (0, _keys.default)(this.statsResults).find(function (item) {
|
|
488
|
-
return item.includes('video-send');
|
|
489
|
-
});
|
|
490
|
-
if (existingVideoSender) {
|
|
491
|
-
newMqa.intervalMetadata.peripherals.push({
|
|
492
|
-
information: this.statsResults[existingVideoSender].trackLabel || _constants._UNKNOWN_,
|
|
493
|
-
name: _constants.MEDIA_DEVICES.CAMERA
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
newMqa.networkType = this.statsResults.connectionType.local.networkType;
|
|
497
|
-
this.mqaSentCount += 1;
|
|
498
|
-
newMqa.intervalNumber = this.mqaSentCount;
|
|
499
|
-
this.resetStatsResults();
|
|
500
|
-
this.emit({
|
|
501
|
-
file: 'statsAnalyzer',
|
|
502
|
-
function: 'sendMqaData'
|
|
503
|
-
}, EVENTS.MEDIA_QUALITY, {
|
|
504
|
-
data: newMqa,
|
|
505
|
-
// @ts-ignore
|
|
506
|
-
networkType: newMqa.networkType
|
|
507
|
-
});
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
/**
|
|
511
|
-
* updated the media connection when changed
|
|
512
|
-
*
|
|
513
|
-
* @private
|
|
514
|
-
* @memberof StatsAnalyzer
|
|
515
|
-
* @param {RoapMediaConnection} mediaConnection
|
|
516
|
-
* @returns {void}
|
|
517
|
-
*/
|
|
518
|
-
}, {
|
|
519
|
-
key: "updateMediaConnection",
|
|
520
|
-
value: function updateMediaConnection(mediaConnection) {
|
|
521
|
-
this.mediaConnection = mediaConnection;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
/**
|
|
525
|
-
* Returns the local IP address for diagnostics.
|
|
526
|
-
* this is the local IP of the interface used for the current media connection
|
|
527
|
-
* a host can have many local Ip Addresses
|
|
528
|
-
* @returns {string | undefined} The local IP address.
|
|
529
|
-
*/
|
|
530
|
-
}, {
|
|
531
|
-
key: "getLocalIpAddress",
|
|
532
|
-
value: function getLocalIpAddress() {
|
|
533
|
-
return this.localIpAddress;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
/**
|
|
537
|
-
* Starts the stats analyzer on interval
|
|
538
|
-
*
|
|
539
|
-
* @public
|
|
540
|
-
* @memberof StatsAnalyzer
|
|
541
|
-
* @param {RoapMediaConnection} mediaConnection
|
|
542
|
-
* @returns {Promise}
|
|
543
|
-
*/
|
|
544
|
-
}, {
|
|
545
|
-
key: "startAnalyzer",
|
|
546
|
-
value: function startAnalyzer(mediaConnection) {
|
|
547
|
-
var _this4 = this;
|
|
548
|
-
if (!this.statsStarted) {
|
|
549
|
-
this.statsStarted = true;
|
|
550
|
-
this.mediaConnection = mediaConnection;
|
|
551
|
-
return this.getStatsAndParse().then(function () {
|
|
552
|
-
_this4.statsInterval = setInterval(function () {
|
|
553
|
-
_this4.getStatsAndParse();
|
|
554
|
-
}, _this4.config.analyzerInterval);
|
|
555
|
-
// Trigger initial fetch
|
|
556
|
-
_this4.sendMqaData();
|
|
557
|
-
_this4.mqaInterval = setInterval(function () {
|
|
558
|
-
_this4.sendMqaData();
|
|
559
|
-
}, _constants.MQA_INTERVAL);
|
|
560
|
-
});
|
|
561
|
-
}
|
|
562
|
-
return _promise.default.resolve();
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
/**
|
|
566
|
-
* Cleans up the analyzer when done
|
|
567
|
-
*
|
|
568
|
-
* @public
|
|
569
|
-
* @memberof StatsAnalyzer
|
|
570
|
-
* @returns {void}
|
|
571
|
-
*/
|
|
572
|
-
}, {
|
|
573
|
-
key: "stopAnalyzer",
|
|
574
|
-
value: function stopAnalyzer() {
|
|
575
|
-
var _this5 = this;
|
|
576
|
-
var sendOneLastMqa = this.mqaInterval && this.statsInterval;
|
|
577
|
-
if (this.statsInterval) {
|
|
578
|
-
clearInterval(this.statsInterval);
|
|
579
|
-
this.statsInterval = undefined;
|
|
580
|
-
}
|
|
581
|
-
if (this.mqaInterval) {
|
|
582
|
-
clearInterval(this.mqaInterval);
|
|
583
|
-
this.mqaInterval = undefined;
|
|
584
|
-
}
|
|
585
|
-
if (sendOneLastMqa) {
|
|
586
|
-
return this.getStatsAndParse().then(function () {
|
|
587
|
-
_this5.sendMqaData();
|
|
588
|
-
_this5.mediaConnection = null;
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
return _promise.default.resolve();
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
/**
|
|
595
|
-
* Parse a single result of get stats
|
|
596
|
-
*
|
|
597
|
-
* @private
|
|
598
|
-
* @param {*} getStatsResult
|
|
599
|
-
* @param {String} type
|
|
600
|
-
* @param {boolean} isSender
|
|
601
|
-
* @returns {void}
|
|
602
|
-
* @memberof StatsAnalyzer
|
|
603
|
-
*/
|
|
604
|
-
}, {
|
|
605
|
-
key: "parseGetStatsResult",
|
|
606
|
-
value: function parseGetStatsResult(getStatsResult, type, isSender) {
|
|
607
|
-
if (!getStatsResult) {
|
|
608
|
-
return;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// Generate empty stats results
|
|
612
|
-
if (!this.statsResults[type]) {
|
|
613
|
-
this.statsResults[type] = {};
|
|
614
|
-
}
|
|
615
|
-
if (isSender && !this.statsResults[type].send) {
|
|
616
|
-
this.statsResults[type].send = (0, _lodash.cloneDeep)(emptySender);
|
|
617
|
-
} else if (!isSender && !this.statsResults[type].recv) {
|
|
618
|
-
this.statsResults[type].recv = (0, _lodash.cloneDeep)(emptyReceiver);
|
|
619
|
-
}
|
|
620
|
-
switch (getStatsResult.type) {
|
|
621
|
-
case 'outbound-rtp':
|
|
622
|
-
this.processOutboundRTPResult(getStatsResult, type);
|
|
623
|
-
break;
|
|
624
|
-
case 'inbound-rtp':
|
|
625
|
-
this.processInboundRTPResult(getStatsResult, type);
|
|
626
|
-
break;
|
|
627
|
-
case 'remote-inbound-rtp':
|
|
628
|
-
case 'remote-outbound-rtp':
|
|
629
|
-
this.compareSentAndReceived(getStatsResult, type);
|
|
630
|
-
break;
|
|
631
|
-
case 'remotecandidate':
|
|
632
|
-
case 'remote-candidate':
|
|
633
|
-
this.parseCandidate(getStatsResult, type, isSender, true);
|
|
634
|
-
break;
|
|
635
|
-
case 'local-candidate':
|
|
636
|
-
this.parseCandidate(getStatsResult, type, isSender, false);
|
|
637
|
-
break;
|
|
638
|
-
case 'media-source':
|
|
639
|
-
this.parseAudioSource(getStatsResult, type);
|
|
640
|
-
break;
|
|
641
|
-
default:
|
|
642
|
-
break;
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
/**
|
|
647
|
-
* Filters the get stats results for types
|
|
648
|
-
* @private
|
|
649
|
-
* @param {Array} statsItem
|
|
650
|
-
* @param {String} type
|
|
651
|
-
* @param {boolean} isSender
|
|
652
|
-
* @returns {void}
|
|
653
|
-
*/
|
|
654
|
-
}, {
|
|
655
|
-
key: "filterAndParseGetStatsResults",
|
|
656
|
-
value: function filterAndParseGetStatsResults(statsItem, type, isSender) {
|
|
657
|
-
var _this6 = this;
|
|
658
|
-
var types = _constants.DEFAULT_GET_STATS_FILTER.types;
|
|
659
|
-
|
|
660
|
-
// get the successful candidate pair before parsing stats.
|
|
661
|
-
statsItem.report.forEach(function (report) {
|
|
662
|
-
if (report.type === 'candidate-pair' && report.state === 'succeeded') {
|
|
663
|
-
_this6.successfulCandidatePair = report;
|
|
664
|
-
}
|
|
665
|
-
});
|
|
666
|
-
var videoSenderIndex = 0;
|
|
667
|
-
statsItem.report.forEach(function (result) {
|
|
668
|
-
if (types.includes(result.type)) {
|
|
669
|
-
// if the video sender has multiple streams in the report, it is a new stream object.
|
|
670
|
-
if (type === 'video-send' && result.type === 'outbound-rtp') {
|
|
671
|
-
var newType = "video-send-layer-".concat(videoSenderIndex);
|
|
672
|
-
_this6.parseGetStatsResult(result, newType, isSender);
|
|
673
|
-
videoSenderIndex += 1;
|
|
674
|
-
_this6.statsResults[newType].direction = statsItem.currentDirection;
|
|
675
|
-
_this6.statsResults[newType].trackLabel = statsItem.localTrackLabel;
|
|
676
|
-
_this6.statsResults[newType].csi = statsItem.csi;
|
|
677
|
-
} else {
|
|
678
|
-
_this6.parseGetStatsResult(result, type, isSender);
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
});
|
|
682
|
-
if (this.statsResults[type]) {
|
|
683
|
-
var _this$successfulCandi2, _this$statsResults;
|
|
684
|
-
this.statsResults[type].direction = statsItem.currentDirection;
|
|
685
|
-
this.statsResults[type].trackLabel = statsItem.localTrackLabel;
|
|
686
|
-
this.statsResults[type].csi = statsItem.csi;
|
|
687
|
-
this.extractAndSetLocalIpAddressInfoForDiagnostics((_this$successfulCandi2 = this.successfulCandidatePair) === null || _this$successfulCandi2 === void 0 ? void 0 : _this$successfulCandi2.localCandidateId, (_this$statsResults = this.statsResults) === null || _this$statsResults === void 0 ? void 0 : _this$statsResults.candidates);
|
|
688
|
-
// reset the successful candidate pair.
|
|
689
|
-
this.successfulCandidatePair = {};
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
/**
|
|
694
|
-
* parse the audio
|
|
695
|
-
* @param {String} result
|
|
696
|
-
* @param {boolean} type
|
|
697
|
-
* @returns {void}
|
|
698
|
-
*/
|
|
699
|
-
}, {
|
|
700
|
-
key: "parseAudioSource",
|
|
701
|
-
value: function parseAudioSource(result, type) {
|
|
702
|
-
if (!result) {
|
|
703
|
-
return;
|
|
704
|
-
}
|
|
705
|
-
if (type.includes('audio-send')) {
|
|
706
|
-
this.statsResults[type].send.audioLevel = result.audioLevel;
|
|
707
|
-
this.statsResults[type].send.totalAudioEnergy = result.totalAudioEnergy;
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
}, {
|
|
711
|
-
key: "compareLastStatsResult",
|
|
712
|
-
value:
|
|
713
|
-
/**
|
|
714
|
-
* compares current and previous stats to check if packets are not sent
|
|
715
|
-
*
|
|
716
|
-
* @private
|
|
717
|
-
* @memberof StatsAnalyzer
|
|
718
|
-
* @returns {void}
|
|
719
|
-
*/
|
|
720
|
-
function compareLastStatsResult() {
|
|
721
|
-
var _this7 = this;
|
|
722
|
-
if (this.lastStatsResults !== null && this.meetingMediaStatus) {
|
|
723
|
-
var getCurrentStatsTotals = function getCurrentStatsTotals(keyPrefix, value) {
|
|
724
|
-
return (0, _keys.default)(_this7.statsResults).filter(function (key) {
|
|
725
|
-
return key.startsWith(keyPrefix);
|
|
726
|
-
}).reduce(function (prev, cur) {
|
|
727
|
-
var _this7$statsResults$c;
|
|
728
|
-
return prev + (((_this7$statsResults$c = _this7.statsResults[cur]) === null || _this7$statsResults$c === void 0 ? void 0 : _this7$statsResults$c[keyPrefix.includes('send') ? 'send' : 'recv'][value]) || 0);
|
|
729
|
-
}, 0);
|
|
730
|
-
};
|
|
731
|
-
var getPreviousStatsTotals = function getPreviousStatsTotals(keyPrefix, value) {
|
|
732
|
-
return (0, _keys.default)(_this7.statsResults).filter(function (key) {
|
|
733
|
-
return key.startsWith(keyPrefix);
|
|
734
|
-
}).reduce(function (prev, cur) {
|
|
735
|
-
var _this7$lastStatsResul;
|
|
736
|
-
return prev + (((_this7$lastStatsResul = _this7.lastStatsResults[cur]) === null || _this7$lastStatsResul === void 0 ? void 0 : _this7$lastStatsResul[keyPrefix.includes('send') ? 'send' : 'recv'][value]) || 0);
|
|
737
|
-
}, 0);
|
|
738
|
-
};
|
|
739
|
-
|
|
740
|
-
// Audio Transmit
|
|
741
|
-
if (this.lastStatsResults['audio-send']) {
|
|
742
|
-
// compare audio stats sent
|
|
743
|
-
// NOTE: relies on there being only one sender.
|
|
744
|
-
var currentStats = this.statsResults['audio-send'].send;
|
|
745
|
-
var previousStats = this.lastStatsResults['audio-send'].send;
|
|
746
|
-
if (this.meetingMediaStatus.expected.sendAudio && currentStats.totalPacketsSent === previousStats.totalPacketsSent || currentStats.totalPacketsSent === 0) {
|
|
747
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent", currentStats.totalPacketsSent);
|
|
748
|
-
} else {
|
|
749
|
-
if (this.meetingMediaStatus.expected.sendAudio && currentStats.totalAudioEnergy === previousStats.totalAudioEnergy || currentStats.totalAudioEnergy === 0) {
|
|
750
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present", currentStats.totalAudioEnergy);
|
|
751
|
-
}
|
|
752
|
-
if (this.meetingMediaStatus.expected.sendAudio && currentStats.audioLevel === 0) {
|
|
753
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> audio level is 0 for the user");
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
this.emitStartStopEvents('audio', previousStats.totalPacketsSent, currentStats.totalPacketsSent, true);
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
// Audio Receive
|
|
760
|
-
var currentAudioPacketsReceived = getCurrentStatsTotals('audio-recv', 'totalPacketsReceived');
|
|
761
|
-
var previousAudioPacketsReceived = getPreviousStatsTotals('audio-recv', 'totalPacketsReceived');
|
|
762
|
-
this.emitStartStopEvents('audio', previousAudioPacketsReceived, currentAudioPacketsReceived, false);
|
|
763
|
-
var currentTotalPacketsSent = getCurrentStatsTotals('video-send', 'totalPacketsSent');
|
|
764
|
-
var previousTotalPacketsSent = getPreviousStatsTotals('video-send', 'totalPacketsSent');
|
|
765
|
-
var currentFramesEncoded = getCurrentStatsTotals('video-send', 'framesEncoded');
|
|
766
|
-
var previousFramesEncoded = getPreviousStatsTotals('video-send', 'framesEncoded');
|
|
767
|
-
var currentFramesSent = getCurrentStatsTotals('video-send', 'framesSent');
|
|
768
|
-
var previousFramesSent = getPreviousStatsTotals('video-send', 'framesSent');
|
|
769
|
-
var doesVideoSendExist = (0, _keys.default)(this.lastStatsResults).some(function (item) {
|
|
770
|
-
return item.includes('video-send');
|
|
771
|
-
});
|
|
772
|
-
|
|
773
|
-
// Video Transmit
|
|
774
|
-
if (doesVideoSendExist) {
|
|
775
|
-
// compare video stats sent
|
|
776
|
-
|
|
777
|
-
if (this.meetingMediaStatus.expected.sendVideo && (currentTotalPacketsSent === previousTotalPacketsSent || currentTotalPacketsSent === 0)) {
|
|
778
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent", currentTotalPacketsSent);
|
|
779
|
-
} else {
|
|
780
|
-
if (this.meetingMediaStatus.expected.sendVideo && (currentFramesEncoded === previousFramesEncoded || currentFramesEncoded === 0)) {
|
|
781
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded", currentFramesEncoded);
|
|
782
|
-
}
|
|
783
|
-
if (this.meetingMediaStatus.expected.sendVideo && (currentFramesSent === previousFramesSent || currentFramesSent === 0)) {
|
|
784
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent", currentFramesSent);
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
this.emitStartStopEvents('video', previousFramesSent, currentFramesSent, true);
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
// Video Receive
|
|
791
|
-
var currentVideoFramesDecoded = getCurrentStatsTotals('video-recv', 'framesDecoded');
|
|
792
|
-
var previousVideoFramesDecoded = getPreviousStatsTotals('video-recv', 'framesDecoded');
|
|
793
|
-
this.emitStartStopEvents('video', previousVideoFramesDecoded, currentVideoFramesDecoded, false);
|
|
794
|
-
|
|
795
|
-
// Share Transmit
|
|
796
|
-
if (this.lastStatsResults['video-share-send']) {
|
|
797
|
-
// compare share stats sent
|
|
798
|
-
|
|
799
|
-
var _currentStats = this.statsResults['video-share-send'].send;
|
|
800
|
-
var _previousStats = this.lastStatsResults['video-share-send'].send;
|
|
801
|
-
if (this.meetingMediaStatus.expected.sendShare && (_currentStats.totalPacketsSent === _previousStats.totalPacketsSent || _currentStats.totalPacketsSent === 0)) {
|
|
802
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent", _currentStats.totalPacketsSent);
|
|
803
|
-
} else {
|
|
804
|
-
if (this.meetingMediaStatus.expected.sendShare && (_currentStats.framesEncoded === _previousStats.framesEncoded || _currentStats.framesEncoded === 0)) {
|
|
805
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded", _currentStats.framesEncoded);
|
|
806
|
-
}
|
|
807
|
-
if (this.meetingMediaStatus.expected.sendShare && (this.statsResults['video-share-send'].send.framesSent === this.lastStatsResults['video-share-send'].send.framesSent || this.statsResults['video-share-send'].send.framesSent === 0)) {
|
|
808
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#compareLastStatsResult --> No share frames sent", this.statsResults['video-share-send'].send.framesSent);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
this.emitStartStopEvents('share', _previousStats.framesSent, _currentStats.framesSent, true);
|
|
812
|
-
}
|
|
813
|
-
|
|
814
|
-
// Share receive
|
|
815
|
-
var currentShareFramesDecoded = getCurrentStatsTotals('video-share-recv', 'framesDecoded');
|
|
816
|
-
var previousShareFramesDecoded = getPreviousStatsTotals('video-share-recv', 'framesDecoded');
|
|
817
|
-
this.emitStartStopEvents('share', previousShareFramesDecoded, currentShareFramesDecoded, false);
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
/**
|
|
822
|
-
* Does a `getStats` on all the transceivers and parses the results
|
|
823
|
-
*
|
|
824
|
-
* @private
|
|
825
|
-
* @memberof StatsAnalyzer
|
|
826
|
-
* @returns {Promise}
|
|
827
|
-
*/
|
|
828
|
-
}, {
|
|
829
|
-
key: "getStatsAndParse",
|
|
830
|
-
value: function getStatsAndParse() {
|
|
831
|
-
var _this8 = this;
|
|
832
|
-
if (!this.mediaConnection) {
|
|
833
|
-
return _promise.default.resolve();
|
|
834
|
-
}
|
|
835
|
-
if (this.mediaConnection && this.mediaConnection.getConnectionState() === _internalMediaCore.ConnectionState.Failed) {
|
|
836
|
-
_loggerProxy.default.logger.trace('StatsAnalyzer:index#getStatsAndParse --> media connection is in failed state');
|
|
837
|
-
return _promise.default.resolve();
|
|
838
|
-
}
|
|
839
|
-
_loggerProxy.default.logger.trace('StatsAnalyzer:index#getStatsAndParse --> Collecting Stats');
|
|
840
|
-
return this.mediaConnection.getTransceiverStats().then(function (transceiverStats) {
|
|
841
|
-
transceiverStats.video.receivers.forEach(function (receiver, i) {
|
|
842
|
-
return _this8.filterAndParseGetStatsResults(receiver, "video-recv-".concat(i), false);
|
|
843
|
-
});
|
|
844
|
-
transceiverStats.audio.receivers.forEach(function (receiver, i) {
|
|
845
|
-
return _this8.filterAndParseGetStatsResults(receiver, "audio-recv-".concat(i), false);
|
|
846
|
-
});
|
|
847
|
-
transceiverStats.screenShareVideo.receivers.forEach(function (receiver, i) {
|
|
848
|
-
return _this8.filterAndParseGetStatsResults(receiver, "video-share-recv-".concat(i), false);
|
|
849
|
-
});
|
|
850
|
-
transceiverStats.screenShareAudio.receivers.forEach(function (receiver, i) {
|
|
851
|
-
return _this8.filterAndParseGetStatsResults(receiver, "audio-share-recv-".concat(i), false);
|
|
852
|
-
});
|
|
853
|
-
transceiverStats.video.senders.forEach(function (sender, i) {
|
|
854
|
-
if (i > 0) {
|
|
855
|
-
throw new Error('Stats Analyzer does not support multiple senders.');
|
|
856
|
-
}
|
|
857
|
-
_this8.filterAndParseGetStatsResults(sender, 'video-send', true);
|
|
858
|
-
});
|
|
859
|
-
transceiverStats.audio.senders.forEach(function (sender, i) {
|
|
860
|
-
if (i > 0) {
|
|
861
|
-
throw new Error('Stats Analyzer does not support multiple senders.');
|
|
862
|
-
}
|
|
863
|
-
_this8.filterAndParseGetStatsResults(sender, 'audio-send', true);
|
|
864
|
-
});
|
|
865
|
-
transceiverStats.screenShareVideo.senders.forEach(function (sender, i) {
|
|
866
|
-
if (i > 0) {
|
|
867
|
-
throw new Error('Stats Analyzer does not support multiple senders.');
|
|
868
|
-
}
|
|
869
|
-
_this8.filterAndParseGetStatsResults(sender, 'video-share-send', true);
|
|
870
|
-
});
|
|
871
|
-
transceiverStats.screenShareAudio.senders.forEach(function (sender, i) {
|
|
872
|
-
if (i > 0) {
|
|
873
|
-
throw new Error('Stats Analyzer does not support multiple senders.');
|
|
874
|
-
}
|
|
875
|
-
_this8.filterAndParseGetStatsResults(sender, 'audio-share-send', true);
|
|
876
|
-
});
|
|
877
|
-
_this8.compareLastStatsResult();
|
|
878
|
-
|
|
879
|
-
// Save the last results to compare with the current
|
|
880
|
-
// DO Deep copy, for some reason it takes the reference all the time rather then old value set
|
|
881
|
-
_this8.lastStatsResults = JSON.parse((0, _stringify.default)(_this8.statsResults));
|
|
882
|
-
_loggerProxy.default.logger.trace('StatsAnalyzer:index#getStatsAndParse --> Finished Collecting Stats');
|
|
883
|
-
});
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
/**
|
|
887
|
-
* Processes OutboundRTP stats result and stores
|
|
888
|
-
* @private
|
|
889
|
-
* @param {*} result
|
|
890
|
-
* @param {*} mediaType
|
|
891
|
-
* @returns {void}
|
|
892
|
-
*/
|
|
893
|
-
}, {
|
|
894
|
-
key: "processOutboundRTPResult",
|
|
895
|
-
value: function processOutboundRTPResult(result, mediaType) {
|
|
896
|
-
var sendrecvType = _constants.STATS.SEND_DIRECTION;
|
|
897
|
-
if (result.bytesSent) {
|
|
898
|
-
var kilobytes = 0;
|
|
899
|
-
if (result.frameWidth && result.frameHeight) {
|
|
900
|
-
this.statsResults[mediaType][sendrecvType].width = result.frameWidth;
|
|
901
|
-
this.statsResults[mediaType][sendrecvType].height = result.frameHeight;
|
|
902
|
-
this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;
|
|
903
|
-
this.statsResults[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;
|
|
904
|
-
}
|
|
905
|
-
this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
|
|
906
|
-
this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;
|
|
907
|
-
this.statsResults[mediaType][sendrecvType].keyFramesEncoded = result.keyFramesEncoded;
|
|
908
|
-
this.statsResults[mediaType][sendrecvType].packetsSent = result.packetsSent;
|
|
909
|
-
|
|
910
|
-
// Data saved to send MQA metrics
|
|
911
|
-
|
|
912
|
-
this.statsResults[mediaType][sendrecvType].totalKeyFramesEncoded = result.keyFramesEncoded;
|
|
913
|
-
this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;
|
|
914
|
-
this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;
|
|
915
|
-
this.statsResults[mediaType][sendrecvType].totalPacketsSent = result.packetsSent;
|
|
916
|
-
this.statsResults[mediaType][sendrecvType].totalFirCount = result.firCount;
|
|
917
|
-
this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;
|
|
918
|
-
this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;
|
|
919
|
-
this.statsResults[mediaType][sendrecvType].encoderImplementation = result.encoderImplementation;
|
|
920
|
-
this.statsResults[mediaType][sendrecvType].qualityLimitationReason = result.qualityLimitationReason;
|
|
921
|
-
this.statsResults[mediaType][sendrecvType].qualityLimitationResolutionChanges = result.qualityLimitationResolutionChanges;
|
|
922
|
-
this.statsResults[mediaType][sendrecvType].totalRtxPacketsSent = result.retransmittedPacketsSent;
|
|
923
|
-
this.statsResults[mediaType][sendrecvType].totalRtxBytesSent = result.retransmittedBytesSent;
|
|
924
|
-
this.statsResults[mediaType][sendrecvType].totalBytesSent = result.bytesSent;
|
|
925
|
-
this.statsResults[mediaType][sendrecvType].headerBytesSent = result.headerBytesSent;
|
|
926
|
-
this.statsResults[mediaType][sendrecvType].requestedBitrate = result.requestedBitrate;
|
|
927
|
-
this.statsResults[mediaType][sendrecvType].requestedFrameSize = result.requestedFrameSize;
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
/**
|
|
932
|
-
* Processes InboundRTP stats result and stores
|
|
933
|
-
* @private
|
|
934
|
-
* @param {*} result
|
|
935
|
-
* @param {*} mediaType
|
|
936
|
-
* @returns {void}
|
|
937
|
-
*/
|
|
938
|
-
}, {
|
|
939
|
-
key: "processInboundRTPResult",
|
|
940
|
-
value: function processInboundRTPResult(result, mediaType) {
|
|
941
|
-
var sendrecvType = _constants.STATS.RECEIVE_DIRECTION;
|
|
942
|
-
if (result.bytesReceived) {
|
|
943
|
-
var kilobytes = 0;
|
|
944
|
-
var receiveSlot = this.receiveSlotCallback(result.ssrc);
|
|
945
|
-
var sourceState = receiveSlot === null || receiveSlot === void 0 ? void 0 : receiveSlot.sourceState;
|
|
946
|
-
var idAndCsi = receiveSlot ? "id: \"".concat(receiveSlot.id || '', "\"").concat(receiveSlot.csi ? " and csi: ".concat(receiveSlot.csi) : '') : '';
|
|
947
|
-
var bytes = result.bytesReceived - this.statsResults[mediaType][sendrecvType].totalBytesReceived;
|
|
948
|
-
kilobytes = bytes / 1024;
|
|
949
|
-
this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
|
|
950
|
-
var currentPacketsLost = result.packetsLost - this.statsResults[mediaType][sendrecvType].totalPacketsLost;
|
|
951
|
-
if (currentPacketsLost < 0) {
|
|
952
|
-
currentPacketsLost = 0;
|
|
953
|
-
}
|
|
954
|
-
var packetsReceivedDiff = result.packetsReceived - this.statsResults[mediaType][sendrecvType].totalPacketsReceived;
|
|
955
|
-
this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;
|
|
956
|
-
if (packetsReceivedDiff === 0) {
|
|
957
|
-
if (receiveSlot && sourceState === 'live') {
|
|
958
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#processInboundRTPResult --> No packets received for mediaType: ".concat(mediaType, ", receive slot ").concat(idAndCsi, ". Total packets received on slot: "), result.packetsReceived);
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
if (mediaType.startsWith('video') || mediaType.startsWith('share')) {
|
|
962
|
-
var videoFramesReceivedDiff = result.framesReceived - this.statsResults[mediaType][sendrecvType].framesReceived;
|
|
963
|
-
if (videoFramesReceivedDiff === 0) {
|
|
964
|
-
if (receiveSlot && sourceState === 'live') {
|
|
965
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#processInboundRTPResult --> No frames received for mediaType: ".concat(mediaType, ", receive slot ").concat(idAndCsi, ". Total frames received on slot: "), result.framesReceived);
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
var videoFramesDecodedDiff = result.framesDecoded - this.statsResults[mediaType][sendrecvType].framesDecoded;
|
|
969
|
-
if (videoFramesDecodedDiff === 0) {
|
|
970
|
-
if (receiveSlot && sourceState === 'live') {
|
|
971
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#processInboundRTPResult --> No frames decoded for mediaType: ".concat(mediaType, ", receive slot ").concat(idAndCsi, ". Total frames decoded on slot: "), result.framesDecoded);
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
var videoFramesDroppedDiff = result.framesDropped - this.statsResults[mediaType][sendrecvType].framesDropped;
|
|
975
|
-
if (videoFramesDroppedDiff > 10) {
|
|
976
|
-
if (receiveSlot && sourceState === 'live') {
|
|
977
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#processInboundRTPResult --> Frames dropped for mediaType: ".concat(mediaType, ", receive slot ").concat(idAndCsi, ". Total frames dropped on slot: "), result.framesDropped);
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
// Check the over all packet Lost ratio
|
|
983
|
-
this.statsResults[mediaType][sendrecvType].currentPacketLossRatio = currentPacketsLost > 0 ? currentPacketsLost / (packetsReceivedDiff + currentPacketsLost) : 0;
|
|
984
|
-
if (this.statsResults[mediaType][sendrecvType].currentPacketLossRatio > 3) {
|
|
985
|
-
_loggerProxy.default.logger.info("StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver with slot ".concat(idAndCsi), this.statsResults[mediaType][sendrecvType].currentPacketLossRatio);
|
|
986
|
-
}
|
|
987
|
-
if (result.frameWidth && result.frameHeight) {
|
|
988
|
-
this.statsResults[mediaType][sendrecvType].width = result.frameWidth;
|
|
989
|
-
this.statsResults[mediaType][sendrecvType].height = result.frameHeight;
|
|
990
|
-
this.statsResults[mediaType][sendrecvType].framesReceived = result.framesReceived;
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
// TODO: check the packet loss value is negative values here
|
|
994
|
-
|
|
995
|
-
if (result.packetsLost) {
|
|
996
|
-
this.statsResults[mediaType][sendrecvType].totalPacketsLost = result.packetsLost > 0 ? result.packetsLost : -result.packetsLost;
|
|
997
|
-
} else {
|
|
998
|
-
this.statsResults[mediaType][sendrecvType].totalPacketsLost = 0;
|
|
999
|
-
}
|
|
1000
|
-
this.statsResults[mediaType][sendrecvType].lastPacketReceivedTimestamp = result.lastPacketReceivedTimestamp;
|
|
1001
|
-
this.statsResults[mediaType][sendrecvType].requestedBitrate = result.requestedBitrate;
|
|
1002
|
-
this.statsResults[mediaType][sendrecvType].requestedFrameSize = result.requestedFrameSize;
|
|
1003
|
-
|
|
1004
|
-
// From Thin
|
|
1005
|
-
this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;
|
|
1006
|
-
this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;
|
|
1007
|
-
this.statsResults[mediaType][sendrecvType].framesDecoded = result.framesDecoded;
|
|
1008
|
-
this.statsResults[mediaType][sendrecvType].keyFramesDecoded = result.keyFramesDecoded;
|
|
1009
|
-
this.statsResults[mediaType][sendrecvType].framesDropped = result.framesDropped;
|
|
1010
|
-
this.statsResults[mediaType][sendrecvType].decoderImplementation = result.decoderImplementation;
|
|
1011
|
-
this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;
|
|
1012
|
-
this.statsResults[mediaType][sendrecvType].fecPacketsDiscarded = result.fecPacketsDiscarded;
|
|
1013
|
-
this.statsResults[mediaType][sendrecvType].fecPacketsReceived = result.fecPacketsReceived;
|
|
1014
|
-
this.statsResults[mediaType][sendrecvType].totalBytesReceived = result.bytesReceived;
|
|
1015
|
-
this.statsResults[mediaType][sendrecvType].headerBytesReceived = result.headerBytesReceived;
|
|
1016
|
-
this.statsResults[mediaType][sendrecvType].totalRtxPacketsReceived = result.retransmittedPacketsReceived;
|
|
1017
|
-
this.statsResults[mediaType][sendrecvType].totalRtxBytesReceived = result.retransmittedBytesReceived;
|
|
1018
|
-
this.statsResults[mediaType][sendrecvType].meanRtpJitter.push(result.jitter);
|
|
1019
|
-
|
|
1020
|
-
// Audio stats
|
|
1021
|
-
|
|
1022
|
-
this.statsResults[mediaType][sendrecvType].audioLevel = result.audioLevel;
|
|
1023
|
-
this.statsResults[mediaType][sendrecvType].totalAudioEnergy = result.totalAudioEnergy;
|
|
1024
|
-
this.statsResults[mediaType][sendrecvType].totalSamplesReceived = result.totalSamplesReceived || 0;
|
|
1025
|
-
this.statsResults[mediaType][sendrecvType].totalSamplesDecoded = result.totalSamplesDecoded || 0;
|
|
1026
|
-
this.statsResults[mediaType][sendrecvType].concealedSamples = result.concealedSamples || 0;
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
}, {
|
|
1030
|
-
key: "compareSentAndReceived",
|
|
1031
|
-
value:
|
|
1032
|
-
/**
|
|
1033
|
-
*
|
|
1034
|
-
* @private
|
|
1035
|
-
* @param {*} result
|
|
1036
|
-
* @param {*} type
|
|
1037
|
-
* @returns {void}
|
|
1038
|
-
* @memberof StatsAnalyzer
|
|
1039
|
-
*/
|
|
1040
|
-
function compareSentAndReceived(result, type) {
|
|
1041
|
-
// Don't compare on transceivers without a sender.
|
|
1042
|
-
if (!type || !this.statsResults[type].send) {
|
|
1043
|
-
return;
|
|
1044
|
-
}
|
|
1045
|
-
var mediaType = type;
|
|
1046
|
-
var currentPacketLoss = result.packetsLost - this.statsResults[mediaType].send.totalPacketsLostOnReceiver;
|
|
1047
|
-
this.statsResults[mediaType].send.packetsLostOnReceiver = currentPacketLoss;
|
|
1048
|
-
this.statsResults[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
|
|
1049
|
-
this.statsResults[mediaType].send.meanRemoteJitter.push(result.jitter);
|
|
1050
|
-
this.statsResults[mediaType].send.meanRoundTripTime.push(result.roundTripTime);
|
|
1051
|
-
this.statsResults[mediaType].send.timestamp = result.timestamp;
|
|
1052
|
-
this.statsResults[mediaType].send.ssrc = result.ssrc;
|
|
1053
|
-
this.statsResults[mediaType].send.reportsReceived = result.reportsReceived;
|
|
1054
|
-
|
|
1055
|
-
// Total packloss ratio on this video section of the call
|
|
1056
|
-
this.statsResults[mediaType].send.overAllPacketLossRatio = this.statsResults[mediaType].send.totalPacketsLostOnReceiver > 0 ? this.statsResults[mediaType].send.totalPacketsLostOnReceiver / this.statsResults[mediaType].send.totalPacketsSent : 0;
|
|
1057
|
-
this.statsResults[mediaType].send.currentPacketLossRatio = this.statsResults[mediaType].send.packetsLostOnReceiver > 0 ? this.statsResults[mediaType].send.packetsLostOnReceiver * 100 / (this.statsResults[mediaType].send.packetsSent + this.statsResults[mediaType].send.packetsLostOnReceiver) : 0;
|
|
1058
|
-
if (this.statsResults[mediaType].send.maxPacketLossRatio < this.statsResults[mediaType].send.currentPacketLossRatio) {
|
|
1059
|
-
this.statsResults[mediaType].send.maxPacketLossRatio = this.statsResults[mediaType].send.currentPacketLossRatio;
|
|
1060
|
-
}
|
|
1061
|
-
if (result.type === 'remote-inbound-rtp') {
|
|
1062
|
-
this.networkQualityMonitor.determineUplinkNetworkQuality({
|
|
1063
|
-
mediaType: mediaType,
|
|
1064
|
-
remoteRtpResults: result,
|
|
1065
|
-
statsAnalyzerCurrentStats: this.statsResults
|
|
1066
|
-
});
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
}]);
|
|
1070
|
-
return StatsAnalyzer;
|
|
1071
|
-
}(_eventsScope.default);
|
|
1072
|
-
//# sourceMappingURL=index.js.map
|