@webex/plugin-meetings 3.0.0-beta.36 → 3.0.0-beta.38
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 +1 -1
- package/dist/multistream/mediaRequestManager.js +1 -31
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +0 -15
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/statsAnalyzer/index.js +8 -4
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/types/multistream/mediaRequestManager.d.ts +0 -2
- package/dist/types/multistream/receiveSlot.d.ts +0 -8
- package/package.json +19 -19
- package/src/multistream/mediaRequestManager.ts +0 -31
- package/src/multistream/receiveSlot.ts +0 -13
- package/src/statsAnalyzer/index.ts +4 -4
- package/test/unit/spec/multistream/mediaRequestManager.ts +0 -73
- package/test/unit/spec/multistream/receiveSlot.ts +0 -19
package/dist/breakouts/index.js
CHANGED
|
@@ -6,8 +6,8 @@ _Object$defineProperty(exports, "__esModule", {
|
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
8
|
exports.MediaRequestManager = void 0;
|
|
9
|
-
var _values = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/values"));
|
|
10
9
|
var _entries = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/entries"));
|
|
10
|
+
var _values = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/values"));
|
|
11
11
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
|
|
12
12
|
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/classCallCheck"));
|
|
13
13
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
|
|
@@ -32,43 +32,15 @@ var MediaRequestManager = /*#__PURE__*/function () {
|
|
|
32
32
|
(0, _defineProperty2.default)(this, "sendMediaRequestsCallback", void 0);
|
|
33
33
|
(0, _defineProperty2.default)(this, "counter", void 0);
|
|
34
34
|
(0, _defineProperty2.default)(this, "clientRequests", void 0);
|
|
35
|
-
(0, _defineProperty2.default)(this, "slotsActiveInLastMediaRequest", void 0);
|
|
36
35
|
(0, _defineProperty2.default)(this, "degradationPreferences", void 0);
|
|
37
36
|
(0, _defineProperty2.default)(this, "sourceUpdateListener", void 0);
|
|
38
37
|
this.sendMediaRequestsCallback = sendMediaRequestsCallback;
|
|
39
38
|
this.counter = 0;
|
|
40
39
|
this.clientRequests = {};
|
|
41
|
-
this.slotsActiveInLastMediaRequest = {};
|
|
42
40
|
this.degradationPreferences = degradationPreferences;
|
|
43
41
|
this.sourceUpdateListener = this.commit.bind(this);
|
|
44
42
|
}
|
|
45
43
|
(0, _createClass2.default)(MediaRequestManager, [{
|
|
46
|
-
key: "resetInactiveReceiveSlots",
|
|
47
|
-
value: function resetInactiveReceiveSlots() {
|
|
48
|
-
var activeSlots = {};
|
|
49
|
-
|
|
50
|
-
// create a map of all currently used slot ids
|
|
51
|
-
(0, _values.default)(this.clientRequests).forEach(function (request) {
|
|
52
|
-
return request.receiveSlots.forEach(function (slot) {
|
|
53
|
-
activeSlots[slot.id] = slot;
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// when we stop using some receive slots and they are not included in the new media request,
|
|
58
|
-
// we will never get a 'no source' notification for them, so we reset their state,
|
|
59
|
-
// so that the client doesn't try to display their video anymore
|
|
60
|
-
for (var _i = 0, _Object$entries = (0, _entries.default)(this.slotsActiveInLastMediaRequest); _i < _Object$entries.length; _i++) {
|
|
61
|
-
var _Object$entries$_i = (0, _slicedToArray2.default)(_Object$entries[_i], 2),
|
|
62
|
-
slotId = _Object$entries$_i[0],
|
|
63
|
-
slot = _Object$entries$_i[1];
|
|
64
|
-
if (!(slotId in activeSlots)) {
|
|
65
|
-
_loggerProxy.default.logger.info("multistream:mediaRequestManager --> resetting sourceState to \"no source\" for slot ".concat(slot.id));
|
|
66
|
-
slot.resetSourceState();
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
this.slotsActiveInLastMediaRequest = activeSlots;
|
|
70
|
-
}
|
|
71
|
-
}, {
|
|
72
44
|
key: "setDegradationPreferences",
|
|
73
45
|
value: function setDegradationPreferences(degradationPreferences) {
|
|
74
46
|
this.degradationPreferences = degradationPreferences;
|
|
@@ -126,7 +98,6 @@ var MediaRequestManager = /*#__PURE__*/function () {
|
|
|
126
98
|
}), maxPayloadBitsPerSecond, mr.codecInfo && [new _internalMediaCore.CodecInfo(0x80, new _internalMediaCore.H264Codec(mr.codecInfo.maxFs, mr.codecInfo.maxFps || CODEC_DEFAULTS.h264.maxFps, mr.codecInfo.maxMbps || CODEC_DEFAULTS.h264.maxMbps, mr.codecInfo.maxWidth, mr.codecInfo.maxHeight))]));
|
|
127
99
|
});
|
|
128
100
|
this.sendMediaRequestsCallback(wcmeMediaRequests);
|
|
129
|
-
this.resetInactiveReceiveSlots();
|
|
130
101
|
}
|
|
131
102
|
}, {
|
|
132
103
|
key: "addRequest",
|
|
@@ -167,7 +138,6 @@ var MediaRequestManager = /*#__PURE__*/function () {
|
|
|
167
138
|
key: "reset",
|
|
168
139
|
value: function reset() {
|
|
169
140
|
this.clientRequests = {};
|
|
170
|
-
this.slotsActiveInLastMediaRequest = {};
|
|
171
141
|
}
|
|
172
142
|
}]);
|
|
173
143
|
return MediaRequestManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["CODEC_DEFAULTS","h264","maxFs","maxFps","maxMbps","MediaRequestManager","degradationPreferences","sendMediaRequestsCallback","counter","clientRequests","slotsActiveInLastMediaRequest","sourceUpdateListener","commit","bind","activeSlots","forEach","request","receiveSlots","slot","id","slotId","LoggerProxy","logger","info","resetSourceState","sendRequests","maxFsLimits","getMaxFs","totalMacroblocksRequested","mr","codecInfo","Math","min","i","slotsWithLiveSource","filter","rs","sourceState","length","maxMacroblocksLimit","warn","wcmeMediaRequests","getDegradedClientRequests","maxPayloadBitsPerSecond","push","WcmeMediaRequest","policyInfo","policy","Policy","ActiveSpeaker","ReceiverSelected","ActiveSpeakerInfo","priority","crossPriorityDuplication","crossPolicyDuplication","preferLiveVideo","ReceiverSelectedInfo","csi","map","receiveSlot","wcmeReceiveSlot","WcmeCodecInfo","H264Codec","maxWidth","maxHeight","resetInactiveReceiveSlots","mediaRequest","newId","on","ReceiveSlotEvents","SourceUpdate","requestId","off"],"sources":["mediaRequestManager.ts"],"sourcesContent":["/* eslint-disable require-jsdoc */\nimport {\n MediaRequest as WcmeMediaRequest,\n Policy,\n ActiveSpeakerInfo,\n ReceiverSelectedInfo,\n CodecInfo as WcmeCodecInfo,\n H264Codec,\n} from '@webex/internal-media-core';\nimport {cloneDeep} from 'lodash';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport {ReceiveSlot, ReceiveSlotEvents, ReceiveSlotId} from './receiveSlot';\nimport {getMaxFs} from './remoteMedia';\n\nexport interface ActiveSpeakerPolicyInfo {\n policy: 'active-speaker';\n priority: number;\n crossPriorityDuplication: boolean;\n crossPolicyDuplication: boolean;\n preferLiveVideo: boolean;\n}\n\nexport interface ReceiverSelectedPolicyInfo {\n policy: 'receiver-selected';\n csi: number;\n}\n\nexport type PolicyInfo = ActiveSpeakerPolicyInfo | ReceiverSelectedPolicyInfo;\n\nexport interface H264CodecInfo {\n codec: 'h264';\n maxFs?: number;\n maxFps?: number;\n maxMbps?: number;\n maxWidth?: number;\n maxHeight?: number;\n}\n\nexport type CodecInfo = H264CodecInfo; // we'll add AV1 here in the future when it's available\n\nexport interface MediaRequest {\n policyInfo: PolicyInfo;\n receiveSlots: Array<ReceiveSlot>;\n codecInfo?: CodecInfo;\n}\n\nexport type MediaRequestId = string;\n\nconst CODEC_DEFAULTS = {\n h264: {\n maxFs: 8192,\n maxFps: 3000,\n maxMbps: 245760,\n },\n};\n\ntype DegradationPreferences = {\n maxMacroblocksLimit: number;\n};\n\ntype SendMediaRequestsCallback = (mediaRequests: WcmeMediaRequest[]) => void;\n\nexport class MediaRequestManager {\n private sendMediaRequestsCallback: SendMediaRequestsCallback;\n\n private counter: number;\n\n private clientRequests: {[key: MediaRequestId]: MediaRequest};\n\n private slotsActiveInLastMediaRequest: {[key: ReceiveSlotId]: ReceiveSlot};\n\n private degradationPreferences: DegradationPreferences;\n\n private sourceUpdateListener: () => void;\n\n constructor(\n degradationPreferences: DegradationPreferences,\n sendMediaRequestsCallback: SendMediaRequestsCallback\n ) {\n this.sendMediaRequestsCallback = sendMediaRequestsCallback;\n this.counter = 0;\n this.clientRequests = {};\n this.slotsActiveInLastMediaRequest = {};\n this.degradationPreferences = degradationPreferences;\n this.sourceUpdateListener = this.commit.bind(this);\n }\n\n private resetInactiveReceiveSlots() {\n const activeSlots: {[key: ReceiveSlotId]: ReceiveSlot} = {};\n\n // create a map of all currently used slot ids\n Object.values(this.clientRequests).forEach((request) =>\n request.receiveSlots.forEach((slot) => {\n activeSlots[slot.id] = slot;\n })\n );\n\n // when we stop using some receive slots and they are not included in the new media request,\n // we will never get a 'no source' notification for them, so we reset their state,\n // so that the client doesn't try to display their video anymore\n for (const [slotId, slot] of Object.entries(this.slotsActiveInLastMediaRequest)) {\n if (!(slotId in activeSlots)) {\n LoggerProxy.logger.info(\n `multistream:mediaRequestManager --> resetting sourceState to \"no source\" for slot ${slot.id}`\n );\n slot.resetSourceState();\n }\n }\n\n this.slotsActiveInLastMediaRequest = activeSlots;\n }\n\n public setDegradationPreferences(degradationPreferences: DegradationPreferences) {\n this.degradationPreferences = degradationPreferences;\n this.sendRequests(); // re-send requests after preferences are set\n }\n\n private getDegradedClientRequests() {\n const clientRequests = cloneDeep(this.clientRequests);\n const maxFsLimits = [\n getMaxFs('best'),\n getMaxFs('large'),\n getMaxFs('medium'),\n getMaxFs('small'),\n getMaxFs('very small'),\n getMaxFs('thumbnail'),\n ];\n\n // reduce max-fs until total macroblocks is below limit\n for (let i = 0; i < maxFsLimits.length; i += 1) {\n let totalMacroblocksRequested = 0;\n Object.entries(clientRequests).forEach(([id, mr]) => {\n if (mr.codecInfo) {\n mr.codecInfo.maxFs = Math.min(\n mr.codecInfo.maxFs || CODEC_DEFAULTS.h264.maxFs,\n maxFsLimits[i]\n );\n // we only consider sources with \"live\" state\n const slotsWithLiveSource = this.clientRequests[id].receiveSlots.filter(\n (rs) => rs.sourceState === 'live'\n );\n totalMacroblocksRequested += mr.codecInfo.maxFs * slotsWithLiveSource.length;\n }\n });\n if (totalMacroblocksRequested <= this.degradationPreferences.maxMacroblocksLimit) {\n if (i !== 0) {\n LoggerProxy.logger.warn(\n `multistream:mediaRequestManager --> too many streams with high max-fs, frame size will be limited to ${maxFsLimits[i]}`\n );\n }\n break;\n } else if (i === maxFsLimits.length - 1) {\n LoggerProxy.logger.warn(\n `multistream:mediaRequestManager --> even with frame size limited to ${maxFsLimits[i]} you are still requesting too many streams, consider reducing the number of requests`\n );\n }\n }\n\n return clientRequests;\n }\n\n private sendRequests() {\n const wcmeMediaRequests: WcmeMediaRequest[] = [];\n\n const clientRequests = this.getDegradedClientRequests();\n const maxPayloadBitsPerSecond = 10 * 1000 * 1000;\n\n // map all the client media requests to wcme media requests\n Object.values(clientRequests).forEach((mr) => {\n wcmeMediaRequests.push(\n new WcmeMediaRequest(\n mr.policyInfo.policy === 'active-speaker'\n ? Policy.ActiveSpeaker\n : Policy.ReceiverSelected,\n mr.policyInfo.policy === 'active-speaker'\n ? new ActiveSpeakerInfo(\n mr.policyInfo.priority,\n mr.policyInfo.crossPriorityDuplication,\n mr.policyInfo.crossPolicyDuplication,\n mr.policyInfo.preferLiveVideo\n )\n : new ReceiverSelectedInfo(mr.policyInfo.csi),\n mr.receiveSlots.map((receiveSlot) => receiveSlot.wcmeReceiveSlot),\n maxPayloadBitsPerSecond,\n mr.codecInfo && [\n new WcmeCodecInfo(\n 0x80,\n new H264Codec(\n mr.codecInfo.maxFs,\n mr.codecInfo.maxFps || CODEC_DEFAULTS.h264.maxFps,\n mr.codecInfo.maxMbps || CODEC_DEFAULTS.h264.maxMbps,\n mr.codecInfo.maxWidth,\n mr.codecInfo.maxHeight\n )\n ),\n ]\n )\n );\n });\n\n this.sendMediaRequestsCallback(wcmeMediaRequests);\n\n this.resetInactiveReceiveSlots();\n }\n\n public addRequest(mediaRequest: MediaRequest, commit = true): MediaRequestId {\n // eslint-disable-next-line no-plusplus\n const newId = `${this.counter++}`;\n\n this.clientRequests[newId] = mediaRequest;\n\n mediaRequest.receiveSlots.forEach((rs) => {\n rs.on(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);\n });\n\n if (commit) {\n this.commit();\n }\n\n return newId;\n }\n\n public cancelRequest(requestId: MediaRequestId, commit = true) {\n this.clientRequests[requestId]?.receiveSlots.forEach((rs) => {\n rs.off(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);\n });\n\n delete this.clientRequests[requestId];\n\n if (commit) {\n this.commit();\n }\n }\n\n public commit() {\n return this.sendRequests();\n }\n\n public reset() {\n this.clientRequests = {};\n this.slotsActiveInLastMediaRequest = {};\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AACA;AAUA;AAEA;AACA;AAdA;;AAkDA,IAAMA,cAAc,GAAG;EACrBC,IAAI,EAAE;IACJC,KAAK,EAAE,IAAI;IACXC,MAAM,EAAE,IAAI;IACZC,OAAO,EAAE;EACX;AACF,CAAC;AAAC,IAQWC,mBAAmB;EAa9B,6BACEC,sBAA8C,EAC9CC,yBAAoD,EACpD;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IACA,IAAI,CAACA,yBAAyB,GAAGA,yBAAyB;IAC1D,IAAI,CAACC,OAAO,GAAG,CAAC;IAChB,IAAI,CAACC,cAAc,GAAG,CAAC,CAAC;IACxB,IAAI,CAACC,6BAA6B,GAAG,CAAC,CAAC;IACvC,IAAI,CAACJ,sBAAsB,GAAGA,sBAAsB;IACpD,IAAI,CAACK,oBAAoB,GAAG,IAAI,CAACC,MAAM,CAACC,IAAI,CAAC,IAAI,CAAC;EACpD;EAAC;IAAA;IAAA,OAED,qCAAoC;MAClC,IAAMC,WAAgD,GAAG,CAAC,CAAC;;MAE3D;MACA,qBAAc,IAAI,CAACL,cAAc,CAAC,CAACM,OAAO,CAAC,UAACC,OAAO;QAAA,OACjDA,OAAO,CAACC,YAAY,CAACF,OAAO,CAAC,UAACG,IAAI,EAAK;UACrCJ,WAAW,CAACI,IAAI,CAACC,EAAE,CAAC,GAAGD,IAAI;QAC7B,CAAC,CAAC;MAAA,EACH;;MAED;MACA;MACA;MACA,mCAA6B,sBAAe,IAAI,CAACR,6BAA6B,CAAC,qCAAE;QAA5E;UAAOU,MAAM;UAAEF,IAAI;QACtB,IAAI,EAAEE,MAAM,IAAIN,WAAW,CAAC,EAAE;UAC5BO,oBAAW,CAACC,MAAM,CAACC,IAAI,+FACgEL,IAAI,CAACC,EAAE,EAC7F;UACDD,IAAI,CAACM,gBAAgB,EAAE;QACzB;MACF;MAEA,IAAI,CAACd,6BAA6B,GAAGI,WAAW;IAClD;EAAC;IAAA;IAAA,OAED,mCAAiCR,sBAA8C,EAAE;MAC/E,IAAI,CAACA,sBAAsB,GAAGA,sBAAsB;MACpD,IAAI,CAACmB,YAAY,EAAE,CAAC,CAAC;IACvB;EAAC;IAAA;IAAA,OAED,qCAAoC;MAAA;MAClC,IAAMhB,cAAc,GAAG,yBAAU,IAAI,CAACA,cAAc,CAAC;MACrD,IAAMiB,WAAW,GAAG,CAClB,IAAAC,qBAAQ,EAAC,MAAM,CAAC,EAChB,IAAAA,qBAAQ,EAAC,OAAO,CAAC,EACjB,IAAAA,qBAAQ,EAAC,QAAQ,CAAC,EAClB,IAAAA,qBAAQ,EAAC,OAAO,CAAC,EACjB,IAAAA,qBAAQ,EAAC,YAAY,CAAC,EACtB,IAAAA,qBAAQ,EAAC,WAAW,CAAC,CACtB;;MAED;MAAA,8BACgD;QAC9C,IAAIC,yBAAyB,GAAG,CAAC;QACjC,sBAAenB,cAAc,CAAC,CAACM,OAAO,CAAC,gBAAc;UAAA;YAAZI,EAAE;YAAEU,EAAE;UAC7C,IAAIA,EAAE,CAACC,SAAS,EAAE;YAChBD,EAAE,CAACC,SAAS,CAAC5B,KAAK,GAAG6B,IAAI,CAACC,GAAG,CAC3BH,EAAE,CAACC,SAAS,CAAC5B,KAAK,IAAIF,cAAc,CAACC,IAAI,CAACC,KAAK,EAC/CwB,WAAW,CAACO,CAAC,CAAC,CACf;YACD;YACA,IAAMC,mBAAmB,GAAG,KAAI,CAACzB,cAAc,CAACU,EAAE,CAAC,CAACF,YAAY,CAACkB,MAAM,CACrE,UAACC,EAAE;cAAA,OAAKA,EAAE,CAACC,WAAW,KAAK,MAAM;YAAA,EAClC;YACDT,yBAAyB,IAAIC,EAAE,CAACC,SAAS,CAAC5B,KAAK,GAAGgC,mBAAmB,CAACI,MAAM;UAC9E;QACF,CAAC,CAAC;QACF,IAAIV,yBAAyB,IAAI,KAAI,CAACtB,sBAAsB,CAACiC,mBAAmB,EAAE;UAChF,IAAIN,CAAC,KAAK,CAAC,EAAE;YACXZ,oBAAW,CAACC,MAAM,CAACkB,IAAI,gHACmFd,WAAW,CAACO,CAAC,CAAC,EACvH;UACH;UAAC;QAEH,CAAC,MAAM,IAAIA,CAAC,KAAKP,WAAW,CAACY,MAAM,GAAG,CAAC,EAAE;UACvCjB,oBAAW,CAACC,MAAM,CAACkB,IAAI,+EACkDd,WAAW,CAACO,CAAC,CAAC,0FACtF;QACH;MACF,CAAC;MA3BD,KAAK,IAAIA,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGP,WAAW,CAACY,MAAM,EAAEL,CAAC,IAAI,CAAC;QAAA;QAAA,sBAqB1C;MAAM;MAQV,OAAOxB,cAAc;IACvB;EAAC;IAAA;IAAA,OAED,wBAAuB;MACrB,IAAMgC,iBAAqC,GAAG,EAAE;MAEhD,IAAMhC,cAAc,GAAG,IAAI,CAACiC,yBAAyB,EAAE;MACvD,IAAMC,uBAAuB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI;;MAEhD;MACA,qBAAclC,cAAc,CAAC,CAACM,OAAO,CAAC,UAACc,EAAE,EAAK;QAC5CY,iBAAiB,CAACG,IAAI,CACpB,IAAIC,+BAAgB,CAClBhB,EAAE,CAACiB,UAAU,CAACC,MAAM,KAAK,gBAAgB,GACrCC,yBAAM,CAACC,aAAa,GACpBD,yBAAM,CAACE,gBAAgB,EAC3BrB,EAAE,CAACiB,UAAU,CAACC,MAAM,KAAK,gBAAgB,GACrC,IAAII,oCAAiB,CACnBtB,EAAE,CAACiB,UAAU,CAACM,QAAQ,EACtBvB,EAAE,CAACiB,UAAU,CAACO,wBAAwB,EACtCxB,EAAE,CAACiB,UAAU,CAACQ,sBAAsB,EACpCzB,EAAE,CAACiB,UAAU,CAACS,eAAe,CAC9B,GACD,IAAIC,uCAAoB,CAAC3B,EAAE,CAACiB,UAAU,CAACW,GAAG,CAAC,EAC/C5B,EAAE,CAACZ,YAAY,CAACyC,GAAG,CAAC,UAACC,WAAW;UAAA,OAAKA,WAAW,CAACC,eAAe;QAAA,EAAC,EACjEjB,uBAAuB,EACvBd,EAAE,CAACC,SAAS,IAAI,CACd,IAAI+B,4BAAa,CACf,IAAI,EACJ,IAAIC,4BAAS,CACXjC,EAAE,CAACC,SAAS,CAAC5B,KAAK,EAClB2B,EAAE,CAACC,SAAS,CAAC3B,MAAM,IAAIH,cAAc,CAACC,IAAI,CAACE,MAAM,EACjD0B,EAAE,CAACC,SAAS,CAAC1B,OAAO,IAAIJ,cAAc,CAACC,IAAI,CAACG,OAAO,EACnDyB,EAAE,CAACC,SAAS,CAACiC,QAAQ,EACrBlC,EAAE,CAACC,SAAS,CAACkC,SAAS,CACvB,CACF,CACF,CACF,CACF;MACH,CAAC,CAAC;MAEF,IAAI,CAACzD,yBAAyB,CAACkC,iBAAiB,CAAC;MAEjD,IAAI,CAACwB,yBAAyB,EAAE;IAClC;EAAC;IAAA;IAAA,OAED,oBAAkBC,YAA0B,EAAiC;MAAA;MAAA,IAA/BtD,MAAM,uEAAG,IAAI;MACzD;MACA,IAAMuD,KAAK,aAAM,IAAI,CAAC3D,OAAO,EAAE,CAAE;MAEjC,IAAI,CAACC,cAAc,CAAC0D,KAAK,CAAC,GAAGD,YAAY;MAEzCA,YAAY,CAACjD,YAAY,CAACF,OAAO,CAAC,UAACqB,EAAE,EAAK;QACxCA,EAAE,CAACgC,EAAE,CAACC,8BAAiB,CAACC,YAAY,EAAE,MAAI,CAAC3D,oBAAoB,CAAC;MAClE,CAAC,CAAC;MAEF,IAAIC,MAAM,EAAE;QACV,IAAI,CAACA,MAAM,EAAE;MACf;MAEA,OAAOuD,KAAK;IACd;EAAC;IAAA;IAAA,OAED,uBAAqBI,SAAyB,EAAiB;MAAA;QAAA;MAAA,IAAf3D,MAAM,uEAAG,IAAI;MAC3D,6BAAI,CAACH,cAAc,CAAC8D,SAAS,CAAC,0DAA9B,sBAAgCtD,YAAY,CAACF,OAAO,CAAC,UAACqB,EAAE,EAAK;QAC3DA,EAAE,CAACoC,GAAG,CAACH,8BAAiB,CAACC,YAAY,EAAE,MAAI,CAAC3D,oBAAoB,CAAC;MACnE,CAAC,CAAC;MAEF,OAAO,IAAI,CAACF,cAAc,CAAC8D,SAAS,CAAC;MAErC,IAAI3D,MAAM,EAAE;QACV,IAAI,CAACA,MAAM,EAAE;MACf;IACF;EAAC;IAAA;IAAA,OAED,kBAAgB;MACd,OAAO,IAAI,CAACa,YAAY,EAAE;IAC5B;EAAC;IAAA;IAAA,OAED,iBAAe;MACb,IAAI,CAAChB,cAAc,GAAG,CAAC,CAAC;MACxB,IAAI,CAACC,6BAA6B,GAAG,CAAC,CAAC;IACzC;EAAC;EAAA;AAAA;AAAA"}
|
|
1
|
+
{"version":3,"names":["CODEC_DEFAULTS","h264","maxFs","maxFps","maxMbps","MediaRequestManager","degradationPreferences","sendMediaRequestsCallback","counter","clientRequests","sourceUpdateListener","commit","bind","sendRequests","maxFsLimits","getMaxFs","totalMacroblocksRequested","forEach","id","mr","codecInfo","Math","min","i","slotsWithLiveSource","receiveSlots","filter","rs","sourceState","length","maxMacroblocksLimit","LoggerProxy","logger","warn","wcmeMediaRequests","getDegradedClientRequests","maxPayloadBitsPerSecond","push","WcmeMediaRequest","policyInfo","policy","Policy","ActiveSpeaker","ReceiverSelected","ActiveSpeakerInfo","priority","crossPriorityDuplication","crossPolicyDuplication","preferLiveVideo","ReceiverSelectedInfo","csi","map","receiveSlot","wcmeReceiveSlot","WcmeCodecInfo","H264Codec","maxWidth","maxHeight","mediaRequest","newId","on","ReceiveSlotEvents","SourceUpdate","requestId","off"],"sources":["mediaRequestManager.ts"],"sourcesContent":["/* eslint-disable require-jsdoc */\nimport {\n MediaRequest as WcmeMediaRequest,\n Policy,\n ActiveSpeakerInfo,\n ReceiverSelectedInfo,\n CodecInfo as WcmeCodecInfo,\n H264Codec,\n} from '@webex/internal-media-core';\nimport {cloneDeep} from 'lodash';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport {ReceiveSlot, ReceiveSlotEvents, ReceiveSlotId} from './receiveSlot';\nimport {getMaxFs} from './remoteMedia';\n\nexport interface ActiveSpeakerPolicyInfo {\n policy: 'active-speaker';\n priority: number;\n crossPriorityDuplication: boolean;\n crossPolicyDuplication: boolean;\n preferLiveVideo: boolean;\n}\n\nexport interface ReceiverSelectedPolicyInfo {\n policy: 'receiver-selected';\n csi: number;\n}\n\nexport type PolicyInfo = ActiveSpeakerPolicyInfo | ReceiverSelectedPolicyInfo;\n\nexport interface H264CodecInfo {\n codec: 'h264';\n maxFs?: number;\n maxFps?: number;\n maxMbps?: number;\n maxWidth?: number;\n maxHeight?: number;\n}\n\nexport type CodecInfo = H264CodecInfo; // we'll add AV1 here in the future when it's available\n\nexport interface MediaRequest {\n policyInfo: PolicyInfo;\n receiveSlots: Array<ReceiveSlot>;\n codecInfo?: CodecInfo;\n}\n\nexport type MediaRequestId = string;\n\nconst CODEC_DEFAULTS = {\n h264: {\n maxFs: 8192,\n maxFps: 3000,\n maxMbps: 245760,\n },\n};\n\ntype DegradationPreferences = {\n maxMacroblocksLimit: number;\n};\n\ntype SendMediaRequestsCallback = (mediaRequests: WcmeMediaRequest[]) => void;\n\nexport class MediaRequestManager {\n private sendMediaRequestsCallback: SendMediaRequestsCallback;\n\n private counter: number;\n\n private clientRequests: {[key: MediaRequestId]: MediaRequest};\n\n private degradationPreferences: DegradationPreferences;\n\n private sourceUpdateListener: () => void;\n\n constructor(\n degradationPreferences: DegradationPreferences,\n sendMediaRequestsCallback: SendMediaRequestsCallback\n ) {\n this.sendMediaRequestsCallback = sendMediaRequestsCallback;\n this.counter = 0;\n this.clientRequests = {};\n this.degradationPreferences = degradationPreferences;\n this.sourceUpdateListener = this.commit.bind(this);\n }\n\n public setDegradationPreferences(degradationPreferences: DegradationPreferences) {\n this.degradationPreferences = degradationPreferences;\n this.sendRequests(); // re-send requests after preferences are set\n }\n\n private getDegradedClientRequests() {\n const clientRequests = cloneDeep(this.clientRequests);\n const maxFsLimits = [\n getMaxFs('best'),\n getMaxFs('large'),\n getMaxFs('medium'),\n getMaxFs('small'),\n getMaxFs('very small'),\n getMaxFs('thumbnail'),\n ];\n\n // reduce max-fs until total macroblocks is below limit\n for (let i = 0; i < maxFsLimits.length; i += 1) {\n let totalMacroblocksRequested = 0;\n Object.entries(clientRequests).forEach(([id, mr]) => {\n if (mr.codecInfo) {\n mr.codecInfo.maxFs = Math.min(\n mr.codecInfo.maxFs || CODEC_DEFAULTS.h264.maxFs,\n maxFsLimits[i]\n );\n // we only consider sources with \"live\" state\n const slotsWithLiveSource = this.clientRequests[id].receiveSlots.filter(\n (rs) => rs.sourceState === 'live'\n );\n totalMacroblocksRequested += mr.codecInfo.maxFs * slotsWithLiveSource.length;\n }\n });\n if (totalMacroblocksRequested <= this.degradationPreferences.maxMacroblocksLimit) {\n if (i !== 0) {\n LoggerProxy.logger.warn(\n `multistream:mediaRequestManager --> too many streams with high max-fs, frame size will be limited to ${maxFsLimits[i]}`\n );\n }\n break;\n } else if (i === maxFsLimits.length - 1) {\n LoggerProxy.logger.warn(\n `multistream:mediaRequestManager --> even with frame size limited to ${maxFsLimits[i]} you are still requesting too many streams, consider reducing the number of requests`\n );\n }\n }\n\n return clientRequests;\n }\n\n private sendRequests() {\n const wcmeMediaRequests: WcmeMediaRequest[] = [];\n\n const clientRequests = this.getDegradedClientRequests();\n const maxPayloadBitsPerSecond = 10 * 1000 * 1000;\n\n // map all the client media requests to wcme media requests\n Object.values(clientRequests).forEach((mr) => {\n wcmeMediaRequests.push(\n new WcmeMediaRequest(\n mr.policyInfo.policy === 'active-speaker'\n ? Policy.ActiveSpeaker\n : Policy.ReceiverSelected,\n mr.policyInfo.policy === 'active-speaker'\n ? new ActiveSpeakerInfo(\n mr.policyInfo.priority,\n mr.policyInfo.crossPriorityDuplication,\n mr.policyInfo.crossPolicyDuplication,\n mr.policyInfo.preferLiveVideo\n )\n : new ReceiverSelectedInfo(mr.policyInfo.csi),\n mr.receiveSlots.map((receiveSlot) => receiveSlot.wcmeReceiveSlot),\n maxPayloadBitsPerSecond,\n mr.codecInfo && [\n new WcmeCodecInfo(\n 0x80,\n new H264Codec(\n mr.codecInfo.maxFs,\n mr.codecInfo.maxFps || CODEC_DEFAULTS.h264.maxFps,\n mr.codecInfo.maxMbps || CODEC_DEFAULTS.h264.maxMbps,\n mr.codecInfo.maxWidth,\n mr.codecInfo.maxHeight\n )\n ),\n ]\n )\n );\n });\n\n this.sendMediaRequestsCallback(wcmeMediaRequests);\n }\n\n public addRequest(mediaRequest: MediaRequest, commit = true): MediaRequestId {\n // eslint-disable-next-line no-plusplus\n const newId = `${this.counter++}`;\n\n this.clientRequests[newId] = mediaRequest;\n\n mediaRequest.receiveSlots.forEach((rs) => {\n rs.on(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);\n });\n\n if (commit) {\n this.commit();\n }\n\n return newId;\n }\n\n public cancelRequest(requestId: MediaRequestId, commit = true) {\n this.clientRequests[requestId]?.receiveSlots.forEach((rs) => {\n rs.off(ReceiveSlotEvents.SourceUpdate, this.sourceUpdateListener);\n });\n\n delete this.clientRequests[requestId];\n\n if (commit) {\n this.commit();\n }\n }\n\n public commit() {\n return this.sendRequests();\n }\n\n public reset() {\n this.clientRequests = {};\n }\n}\n"],"mappings":"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"}
|
|
@@ -167,21 +167,6 @@ var ReceiveSlot = /*#__PURE__*/function (_EventsScope) {
|
|
|
167
167
|
get: function get() {
|
|
168
168
|
return this.mcReceiveSlot;
|
|
169
169
|
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Resets the source state to the default 'no source' value.
|
|
173
|
-
* This function should be called on receive slots that are
|
|
174
|
-
* no longer part of a media request. It's needed because WCME
|
|
175
|
-
* does not send any more events on such slots, so the sourceState
|
|
176
|
-
* value would not represent the truth anymore.
|
|
177
|
-
*/
|
|
178
|
-
}, {
|
|
179
|
-
key: "resetSourceState",
|
|
180
|
-
value: function resetSourceState() {
|
|
181
|
-
(0, _classPrivateFieldSet2.default)(this, _sourceState, 'no source');
|
|
182
|
-
(0, _classPrivateFieldSet2.default)(this, _csi, undefined);
|
|
183
|
-
(0, _classPrivateFieldSet2.default)(this, _memberId, undefined);
|
|
184
|
-
}
|
|
185
170
|
}]);
|
|
186
171
|
return ReceiveSlot;
|
|
187
172
|
}(_eventsScope.default);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ReceiveSlotEvents","SourceUpdate","receiveSlotCounter","ReceiveSlot","mediaType","mcReceiveSlot","findMemberIdCallback","id","setupEventListeners","scope","file","function","on","WcmeReceiveSlotEvents","state","csi","LoggerProxy","logger","log","undefined","emit","memberId","stream","EventsScope"],"sources":["receiveSlot.ts"],"sourcesContent":["/* eslint-disable valid-jsdoc */\nimport {\n MediaType,\n ReceiveSlot as WcmeReceiveSlot,\n ReceiveSlotEvents as WcmeReceiveSlotEvents,\n SourceState,\n} from '@webex/internal-media-core';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport EventsScope from '../common/events/events-scope';\n\nexport const ReceiveSlotEvents = {\n SourceUpdate: 'sourceUpdate',\n};\n\nexport type {SourceState} from '@webex/internal-media-core';\nexport type CSI = number;\nexport type MemberId = string;\nexport type ReceiveSlotId = string;\n\nlet receiveSlotCounter = 0;\n\nexport type FindMemberIdCallback = (csi: CSI) => MemberId | undefined;\n\n/**\n * Class representing a receive slot. A single receive slot is able to receive a single track\n * for example some participant's main video or audio\n */\nexport class ReceiveSlot extends EventsScope {\n private readonly mcReceiveSlot: WcmeReceiveSlot;\n\n private readonly findMemberIdCallback: FindMemberIdCallback;\n\n public readonly id: ReceiveSlotId;\n\n public readonly mediaType: MediaType;\n\n #memberId?: MemberId;\n\n #csi?: CSI;\n\n #sourceState: SourceState;\n\n /**\n * constructor - don't use it directly, you should always use meeting.receiveSlotManager.allocateSlot()\n * to create any receive slots\n *\n * @param {MediaType} mediaType\n * @param {ReceiveSlot} mcReceiveSlot\n * @param {FindMemberIdCallback} findMemberIdCallback callback for finding memberId for given CSI\n */\n constructor(\n mediaType: MediaType,\n mcReceiveSlot: WcmeReceiveSlot,\n findMemberIdCallback: FindMemberIdCallback\n ) {\n super();\n\n receiveSlotCounter += 1;\n\n this.findMemberIdCallback = findMemberIdCallback;\n this.mediaType = mediaType;\n this.mcReceiveSlot = mcReceiveSlot;\n this.#sourceState = 'no source';\n this.id = `r${receiveSlotCounter}`;\n\n this.setupEventListeners();\n }\n\n /**\n * Getter for memberId\n */\n public get memberId() {\n return this.#memberId;\n }\n\n /**\n * Getter for csi\n */\n public get csi() {\n return this.#csi;\n }\n\n /**\n * Getter for sourceState\n */\n public get sourceState() {\n return this.#sourceState;\n }\n\n /**\n * registers event handlers with the underlying ReceiveSlot\n */\n private setupEventListeners() {\n const scope = {\n file: 'meeting/receiveSlot',\n function: 'setupEventListeners',\n };\n\n this.mcReceiveSlot.on(\n WcmeReceiveSlotEvents.SourceUpdate,\n (state: SourceState, csi?: number) => {\n LoggerProxy.logger.log(\n `ReceiveSlot#setupEventListeners --> got source update on receive slot ${this.id}, mediaType=${this.mediaType}, csi=${csi}, state=${state}`\n );\n this.#memberId = csi ? this.findMemberIdCallback(csi) : undefined;\n this.#csi = csi;\n this.#sourceState = state;\n\n this.emit(scope, ReceiveSlotEvents.SourceUpdate, {\n state: this.#sourceState,\n csi: this.#csi,\n memberId: this.#memberId,\n });\n }\n );\n }\n\n /** Tries to find the member id for this receive slot if it hasn't got one */\n public findMemberId() {\n if (this.#memberId === undefined && this.#csi) {\n this.#memberId = this.findMemberIdCallback(this.#csi);\n\n if (this.#memberId) {\n // if we found the memberId, simulate source update so that the client app knows that something's changed\n this.emit(\n {\n file: 'meeting/receiveSlot',\n function: 'findMemberId',\n },\n ReceiveSlotEvents.SourceUpdate,\n {\n state: this.#sourceState,\n csi: this.#csi,\n memberId: this.#memberId,\n }\n );\n }\n }\n }\n\n /**\n * The MediaStream object associated with this slot.\n *\n * @returns {MediaStream} The MediaStreamTrack.\n */\n get stream(): MediaStream {\n return this.mcReceiveSlot.stream;\n }\n\n /**\n * The underlying WCME receive slot\n */\n get wcmeReceiveSlot(): WcmeReceiveSlot {\n return this.mcReceiveSlot;\n }\n
|
|
1
|
+
{"version":3,"names":["ReceiveSlotEvents","SourceUpdate","receiveSlotCounter","ReceiveSlot","mediaType","mcReceiveSlot","findMemberIdCallback","id","setupEventListeners","scope","file","function","on","WcmeReceiveSlotEvents","state","csi","LoggerProxy","logger","log","undefined","emit","memberId","stream","EventsScope"],"sources":["receiveSlot.ts"],"sourcesContent":["/* eslint-disable valid-jsdoc */\nimport {\n MediaType,\n ReceiveSlot as WcmeReceiveSlot,\n ReceiveSlotEvents as WcmeReceiveSlotEvents,\n SourceState,\n} from '@webex/internal-media-core';\n\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport EventsScope from '../common/events/events-scope';\n\nexport const ReceiveSlotEvents = {\n SourceUpdate: 'sourceUpdate',\n};\n\nexport type {SourceState} from '@webex/internal-media-core';\nexport type CSI = number;\nexport type MemberId = string;\nexport type ReceiveSlotId = string;\n\nlet receiveSlotCounter = 0;\n\nexport type FindMemberIdCallback = (csi: CSI) => MemberId | undefined;\n\n/**\n * Class representing a receive slot. A single receive slot is able to receive a single track\n * for example some participant's main video or audio\n */\nexport class ReceiveSlot extends EventsScope {\n private readonly mcReceiveSlot: WcmeReceiveSlot;\n\n private readonly findMemberIdCallback: FindMemberIdCallback;\n\n public readonly id: ReceiveSlotId;\n\n public readonly mediaType: MediaType;\n\n #memberId?: MemberId;\n\n #csi?: CSI;\n\n #sourceState: SourceState;\n\n /**\n * constructor - don't use it directly, you should always use meeting.receiveSlotManager.allocateSlot()\n * to create any receive slots\n *\n * @param {MediaType} mediaType\n * @param {ReceiveSlot} mcReceiveSlot\n * @param {FindMemberIdCallback} findMemberIdCallback callback for finding memberId for given CSI\n */\n constructor(\n mediaType: MediaType,\n mcReceiveSlot: WcmeReceiveSlot,\n findMemberIdCallback: FindMemberIdCallback\n ) {\n super();\n\n receiveSlotCounter += 1;\n\n this.findMemberIdCallback = findMemberIdCallback;\n this.mediaType = mediaType;\n this.mcReceiveSlot = mcReceiveSlot;\n this.#sourceState = 'no source';\n this.id = `r${receiveSlotCounter}`;\n\n this.setupEventListeners();\n }\n\n /**\n * Getter for memberId\n */\n public get memberId() {\n return this.#memberId;\n }\n\n /**\n * Getter for csi\n */\n public get csi() {\n return this.#csi;\n }\n\n /**\n * Getter for sourceState\n */\n public get sourceState() {\n return this.#sourceState;\n }\n\n /**\n * registers event handlers with the underlying ReceiveSlot\n */\n private setupEventListeners() {\n const scope = {\n file: 'meeting/receiveSlot',\n function: 'setupEventListeners',\n };\n\n this.mcReceiveSlot.on(\n WcmeReceiveSlotEvents.SourceUpdate,\n (state: SourceState, csi?: number) => {\n LoggerProxy.logger.log(\n `ReceiveSlot#setupEventListeners --> got source update on receive slot ${this.id}, mediaType=${this.mediaType}, csi=${csi}, state=${state}`\n );\n this.#memberId = csi ? this.findMemberIdCallback(csi) : undefined;\n this.#csi = csi;\n this.#sourceState = state;\n\n this.emit(scope, ReceiveSlotEvents.SourceUpdate, {\n state: this.#sourceState,\n csi: this.#csi,\n memberId: this.#memberId,\n });\n }\n );\n }\n\n /** Tries to find the member id for this receive slot if it hasn't got one */\n public findMemberId() {\n if (this.#memberId === undefined && this.#csi) {\n this.#memberId = this.findMemberIdCallback(this.#csi);\n\n if (this.#memberId) {\n // if we found the memberId, simulate source update so that the client app knows that something's changed\n this.emit(\n {\n file: 'meeting/receiveSlot',\n function: 'findMemberId',\n },\n ReceiveSlotEvents.SourceUpdate,\n {\n state: this.#sourceState,\n csi: this.#csi,\n memberId: this.#memberId,\n }\n );\n }\n }\n }\n\n /**\n * The MediaStream object associated with this slot.\n *\n * @returns {MediaStream} The MediaStreamTrack.\n */\n get stream(): MediaStream {\n return this.mcReceiveSlot.stream;\n }\n\n /**\n * The underlying WCME receive slot\n */\n get wcmeReceiveSlot(): WcmeReceiveSlot {\n return this.mcReceiveSlot;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AACA;AAOA;AACA;AAAwD;AAAA;AAAA;AAAA;AAEjD,IAAMA,iBAAiB,GAAG;EAC/BC,YAAY,EAAE;AAChB,CAAC;AAAC;AAOF,IAAIC,kBAAkB,GAAG,CAAC;AAAC;AAAA;AAAA;AAI3B;AACA;AACA;AACA;AAHA,IAIaC,WAAW;EAAA;EAAA;EAetB;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACE,qBACEC,SAAoB,EACpBC,aAA8B,EAC9BC,oBAA0C,EAC1C;IAAA;IAAA;IACA;IAAQ;IAAA;IAAA;IAAA;IAAA;MAAA;MAAA;IAAA;IAAA;MAAA;MAAA;IAAA;IAAA;MAAA;MAAA;IAAA;IAERJ,kBAAkB,IAAI,CAAC;IAEvB,MAAKI,oBAAoB,GAAGA,oBAAoB;IAChD,MAAKF,SAAS,GAAGA,SAAS;IAC1B,MAAKC,aAAa,GAAGA,aAAa;IAClC,+FAAoB,WAAW;IAC/B,MAAKE,EAAE,cAAOL,kBAAkB,CAAE;IAElC,MAAKM,mBAAmB,EAAE;IAAC;EAC7B;;EAEA;AACF;AACA;EAFE;IAAA;IAAA,KAGA,eAAsB;MACpB,2CAAO,IAAI;IACb;;IAEA;AACF;AACA;EAFE;IAAA;IAAA,KAGA,eAAiB;MACf,2CAAO,IAAI;IACb;;IAEA;AACF;AACA;EAFE;IAAA;IAAA,KAGA,eAAyB;MACvB,2CAAO,IAAI;IACb;;IAEA;AACF;AACA;EAFE;IAAA;IAAA,OAGA,+BAA8B;MAAA;MAC5B,IAAMC,KAAK,GAAG;QACZC,IAAI,EAAE,qBAAqB;QAC3BC,QAAQ,EAAE;MACZ,CAAC;MAED,IAAI,CAACN,aAAa,CAACO,EAAE,CACnBC,oCAAqB,CAACZ,YAAY,EAClC,UAACa,KAAkB,EAAEC,GAAY,EAAK;QACpCC,oBAAW,CAACC,MAAM,CAACC,GAAG,iFACqD,MAAI,CAACX,EAAE,yBAAe,MAAI,CAACH,SAAS,mBAASW,GAAG,qBAAWD,KAAK,EAC1I;QACD,0CAAI,aAAaC,GAAG,GAAG,MAAI,CAACT,oBAAoB,CAACS,GAAG,CAAC,GAAGI,SAAS;QACjE,0CAAI,QAAQJ,GAAG;QACf,0CAAI,gBAAgBD,KAAK;QAEzB,MAAI,CAACM,IAAI,CAACX,KAAK,EAAET,iBAAiB,CAACC,YAAY,EAAE;UAC/Ca,KAAK,sCAAE,MAAI,eAAa;UACxBC,GAAG,sCAAE,MAAI,OAAK;UACdM,QAAQ,sCAAE,MAAI;QAChB,CAAC,CAAC;MACJ,CAAC,CACF;IACH;;IAEA;EAAA;IAAA;IAAA,OACA,wBAAsB;MACpB,IAAI,wCAAI,iBAAeF,SAAS,wCAAI,IAAI,OAAK,EAAE;QAC7C,wCAAI,aAAa,IAAI,CAACb,oBAAoB,qCAAC,IAAI,QAAM;QAErD,wCAAI,IAAI,cAAY;UAClB;UACA,IAAI,CAACc,IAAI,CACP;YACEV,IAAI,EAAE,qBAAqB;YAC3BC,QAAQ,EAAE;UACZ,CAAC,EACDX,iBAAiB,CAACC,YAAY,EAC9B;YACEa,KAAK,sCAAE,IAAI,eAAa;YACxBC,GAAG,sCAAE,IAAI,OAAK;YACdM,QAAQ,sCAAE,IAAI;UAChB,CAAC,CACF;QACH;MACF;IACF;;IAEA;AACF;AACA;AACA;AACA;EAJE;IAAA;IAAA,KAKA,eAA0B;MACxB,OAAO,IAAI,CAAChB,aAAa,CAACiB,MAAM;IAClC;;IAEA;AACF;AACA;EAFE;IAAA;IAAA,KAGA,eAAuC;MACrC,OAAO,IAAI,CAACjB,aAAa;IAC3B;EAAC;EAAA;AAAA,EA/H8BkB,oBAAW;AAAA"}
|
|
@@ -528,28 +528,32 @@ var StatsAnalyzer = /*#__PURE__*/function (_EventsScope) {
|
|
|
528
528
|
return (0, _keys.default)(_this7.statsResults).filter(function (key) {
|
|
529
529
|
return key.startsWith(keyPrefix);
|
|
530
530
|
}).reduce(function (prev, cur) {
|
|
531
|
-
|
|
531
|
+
var _this7$statsResults$c;
|
|
532
|
+
return prev + (((_this7$statsResults$c = _this7.statsResults[cur]) === null || _this7$statsResults$c === void 0 ? void 0 : _this7$statsResults$c.recv[value]) || 0);
|
|
532
533
|
}, 0);
|
|
533
534
|
};
|
|
534
535
|
var getPreviousStatsTotals = function getPreviousStatsTotals(keyPrefix, value) {
|
|
535
536
|
return (0, _keys.default)(_this7.statsResults).filter(function (key) {
|
|
536
537
|
return key.startsWith(keyPrefix);
|
|
537
538
|
}).reduce(function (prev, cur) {
|
|
538
|
-
|
|
539
|
+
var _this7$lastStatsResul;
|
|
540
|
+
return prev + (((_this7$lastStatsResul = _this7.lastStatsResults[cur]) === null || _this7$lastStatsResul === void 0 ? void 0 : _this7$lastStatsResul.recv[value]) || 0);
|
|
539
541
|
}, 0);
|
|
540
542
|
};
|
|
541
543
|
var getCurrentResolutionsStatsTotals = function getCurrentResolutionsStatsTotals(keyPrefix, value) {
|
|
542
544
|
return (0, _keys.default)(_this7.statsResults).filter(function (key) {
|
|
543
545
|
return key.startsWith(keyPrefix);
|
|
544
546
|
}).reduce(function (prev, cur) {
|
|
545
|
-
|
|
547
|
+
var _this7$statsResults$r;
|
|
548
|
+
return prev + (((_this7$statsResults$r = _this7.statsResults.resolutions[cur]) === null || _this7$statsResults$r === void 0 ? void 0 : _this7$statsResults$r.recv[value]) || 0);
|
|
546
549
|
}, 0);
|
|
547
550
|
};
|
|
548
551
|
var getPreviousResolutionsStatsTotals = function getPreviousResolutionsStatsTotals(keyPrefix, value) {
|
|
549
552
|
return (0, _keys.default)(_this7.statsResults).filter(function (key) {
|
|
550
553
|
return key.startsWith(keyPrefix);
|
|
551
554
|
}).reduce(function (prev, cur) {
|
|
552
|
-
|
|
555
|
+
var _this7$lastStatsResul2;
|
|
556
|
+
return prev + (((_this7$lastStatsResul2 = _this7.lastStatsResults.resolutions[cur]) === null || _this7$lastStatsResul2 === void 0 ? void 0 : _this7$lastStatsResul2.recv[value]) || 0);
|
|
553
557
|
}, 0);
|
|
554
558
|
};
|
|
555
559
|
if (this.meetingMediaStatus.expected.sendAudio && this.lastStatsResults['audio-send']) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["EVENTS","MEDIA_QUALITY","LOCAL_MEDIA_STARTED","LOCAL_MEDIA_STOPPED","REMOTE_MEDIA_STARTED","REMOTE_MEDIA_STOPPED","emptySender","trackLabel","maxPacketLossRatio","availableBandwidth","bytesSent","meanRemoteJitter","meanRoundTripTime","emptyReceiver","bytesReceived","meanRtpJitter","StatsAnalyzer","config","networkQualityMonitor","statsResults","defaultStats","mediaType","previousValue","currentValue","isLocal","Error","undefined","lastEmittedStartStopEvent","lastEmittedEvent","local","remote","newEvent","emit","file","function","type","result","isSender","isRemote","id","RemoteCandidateType","RemoteTransport","RemoteIpAddress","RemoteNetworkType","sendRecvType","STATS","SEND_DIRECTION","RECEIVE_DIRECTION","ipType","REMOTE","LOCAL","candidateType","indexOf","push","protocol","toUpperCase","ip","portNumber","networkType","internal","candidates","ipAddress","port","priority","transport","timestamp","time","connectionType","NETWORK_TYPE","VPN","UNKNOWN","totalRoundTripTime","statsStarted","lastStatsResults","correlationId","mqaSentCount","lastMqaDataSent","forEach","includes","recv","send","status","meetingMediaStatus","newMqa","emptyMqaInterval","audioSender","emptyAudioTransmit","getAudioSenderMqa","audioTransmit","audioReceiver","emptyAudioReceive","getAudioReceiverMqa","audioReceive","videoSender","emptyVideoTransmit","getVideoSenderMqa","videoTransmit","videoReceiver","emptyVideoReceive","getVideoReceiverMqa","videoReceive","intervalMetadata","peerReflexiveIP","peripherals","information","_UNKNOWN_","name","MEDIA_DEVICES","SPEAKER","MICROPHONE","CAMERA","intervalNumber","resetStatsResults","data","mediaConnection","getStatsAndParse","then","statsInterval","setInterval","analyzerInterval","sendMqaData","mqaInterval","MQA_INTEVAL","resolve","sendOneLastMqa","clearInterval","getStatsResult","resolutions","processOutboundRTPResult","processInboundRTPResult","processTrackResult","compareSentAndReceived","parseCandidate","parseAudioSource","statsItem","types","DEFAULT_GET_STATS_FILTER","report","parseGetStatsResult","direction","currentDirection","localTrackLabel","csi","audioLevel","totalAudioEnergy","getCurrentStatsTotals","keyPrefix","value","filter","key","startsWith","reduce","prev","cur","getPreviousStatsTotals","getCurrentResolutionsStatsTotals","getPreviousResolutionsStatsTotals","expected","sendAudio","currentStats","previousStats","totalPacketsSent","LoggerProxy","logger","info","emitStartStopEvents","receiveAudio","currentPacketsReceived","previousPacketsReceived","currentSamplesReceived","previousSamplesReceived","sendVideo","framesEncoded","framesSent","receiveVideo","currentFramesReceived","previousFramesReceived","currentFramesDecoded","previousFramesDecoded","currentFramesDropped","previousFramesDropped","sendShare","getConnectionState","ConnectionState","Failed","trace","getTransceiverStats","transceiverStats","video","receivers","receiver","i","filterAndParseGetStatsResults","audio","screenShareVideo","screenShareAudio","senders","sender","compareLastStatsResult","JSON","parse","sendrecvType","kilobytes","prevBytesSent","keyFramesEncoded","bytes","toFixed","outboundRtpId","packetsSent","totalKeyFramesEncoded","totalNackCount","nackCount","totalPliCount","pliCount","totalFirCount","firCount","encoderImplementation","qualityLimitationReason","qualityLimitationResolutionChanges","retransmittedPacketsSent","totalBytesSent","headerBytesSent","retransmittedBytesSent","prevBytesReceived","packetsLost","totalPacketsReceived","packetsReceived","lastPacketReceivedTimestamp","currentPacketsLost","currentPacketLossRatio","totalPacketsLost","framesDecoded","keyFramesDecoded","decoderImplementation","fecPacketsDiscarded","fecPacketsReceived","totalBytesReceived","headerBytesReceived","jitter","totalSamplesReceived","totalSamplesDecoded","concealedSamples","remoteSource","frameWidth","frameHeight","width","height","hugeFramesSent","framesReceived","framesDropped","trackIdentifier","jitterBufferDelay","jitterBufferEmittedCount","avgJitterDelay","totalPacketsLostOnReceiver","currentPacketLoss","packetsLostOnReceiver","roundTripTime","ssrc","reportsReceived","overAllPacketLossRatio","determineUplinkNetworkQuality","remoteRtpResults","statsAnalyzerCurrentStats","EventsScope"],"sources":["index.ts"],"sourcesContent":["/* eslint-disable prefer-destructuring */\n\nimport {cloneDeep} from 'lodash';\nimport {ConnectionState} from '@webex/internal-media-core';\n\nimport EventsScope from '../common/events/events-scope';\nimport {\n DEFAULT_GET_STATS_FILTER,\n STATS,\n MQA_INTEVAL,\n NETWORK_TYPE,\n MEDIA_DEVICES,\n _UNKNOWN_,\n} from '../constants';\nimport {\n emptyAudioReceive,\n emptyAudioTransmit,\n emptyMqaInterval,\n emptyVideoReceive,\n emptyVideoTransmit,\n} from '../mediaQualityMetrics/config';\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport defaultStats from './global';\nimport {\n getAudioSenderMqa,\n getAudioReceiverMqa,\n getVideoSenderMqa,\n getVideoReceiverMqa,\n} from './mqaUtil';\n\nexport const EVENTS = {\n MEDIA_QUALITY: 'MEDIA_QUALITY',\n LOCAL_MEDIA_STARTED: 'LOCAL_MEDIA_STARTED',\n LOCAL_MEDIA_STOPPED: 'LOCAL_MEDIA_STOPPED',\n REMOTE_MEDIA_STARTED: 'REMOTE_MEDIA_STARTED',\n REMOTE_MEDIA_STOPPED: 'REMOTE_MEDIA_STOPPED',\n};\n\nconst emptySender = {\n trackLabel: '',\n maxPacketLossRatio: 0,\n availableBandwidth: 0,\n bytesSent: 0,\n meanRemoteJitter: [],\n meanRoundTripTime: [],\n};\n\nconst emptyReceiver = {\n availableBandwidth: 0,\n bytesReceived: 0,\n meanRtpJitter: [],\n meanRoundTripTime: [],\n};\n\n/**\n * Stats Analyzer class that will emit events based on detected quality\n *\n * @export\n * @class StatsAnalyzer\n * @extends {EventsScope}\n */\nexport class StatsAnalyzer extends EventsScope {\n config: any;\n correlationId: any;\n lastEmittedStartStopEvent: any;\n lastMqaDataSent: any;\n lastStatsResults: any;\n meetingMediaStatus: any;\n mqaInterval: NodeJS.Timeout;\n mqaSentCount: any;\n networkQualityMonitor: any;\n mediaConnection: any;\n statsInterval: NodeJS.Timeout;\n statsResults: any;\n statsStarted: any;\n\n /**\n * Creates a new instance of StatsAnalyzer\n * @constructor\n * @public\n * @param {Object} config SDK Configuration Object\n * @param {Object} networkQualityMonitor class for assessing network characteristics (jitter, packetLoss, latency)\n * @param {Object} statsResults Default properties for stats\n */\n constructor(\n config: any,\n networkQualityMonitor: object = {},\n statsResults: object = defaultStats\n ) {\n super();\n this.statsStarted = false;\n this.statsResults = statsResults;\n this.lastStatsResults = null;\n this.config = config;\n this.networkQualityMonitor = networkQualityMonitor;\n this.correlationId = config.correlationId;\n this.mqaSentCount = -1;\n this.lastMqaDataSent = {};\n this.lastEmittedStartStopEvent = {};\n }\n\n /**\n * Resets cumulative stats arrays.\n *\n * @public\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n resetStatsResults() {\n Object.keys(this.statsResults).forEach((mediaType) => {\n if (mediaType.includes('recv')) {\n this.statsResults[mediaType].recv.meanRtpJitter = [];\n }\n\n if (mediaType.includes('send')) {\n this.statsResults[mediaType].send.meanRemoteJitter = [];\n this.statsResults[mediaType].send.meanRoundTripTime = [];\n }\n });\n }\n\n /**\n * sets mediaStatus status for analyzing metrics\n *\n * @public\n * @param {Object} status for the audio and video\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n public updateMediaStatus(status: object) {\n this.meetingMediaStatus = status;\n }\n\n /**\n * captures MQA data from media connection\n *\n * @public\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n sendMqaData() {\n const newMqa = cloneDeep(emptyMqaInterval);\n\n Object.keys(this.statsResults).forEach((mediaType) => {\n if (mediaType.includes('audio-send') || mediaType.includes('audio-share-send')) {\n const audioSender = cloneDeep(emptyAudioTransmit);\n\n getAudioSenderMqa({\n audioSender,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.audioTransmit.push(audioSender);\n } else if (mediaType.includes('audio-recv') || mediaType.includes('audio-share-recv')) {\n const audioReceiver = cloneDeep(emptyAudioReceive);\n\n getAudioReceiverMqa({\n audioReceiver,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.audioReceive.push(audioReceiver);\n } else if (mediaType.includes('video-send') || mediaType.includes('video-share-send')) {\n const videoSender = cloneDeep(emptyVideoTransmit);\n\n getVideoSenderMqa({\n videoSender,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.videoTransmit.push(videoSender);\n } else if (mediaType.includes('video-recv') || mediaType.includes('video-share-recv')) {\n const videoReceiver = cloneDeep(emptyVideoReceive);\n\n getVideoReceiverMqa({\n videoReceiver,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.videoReceive.push(videoReceiver);\n }\n });\n\n newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress[0];\n\n // Adding peripheral information\n newMqa.intervalMetadata.peripherals = [];\n\n newMqa.intervalMetadata.peripherals.push({information: _UNKNOWN_, name: MEDIA_DEVICES.SPEAKER});\n if (this.statsResults['audio-send']) {\n newMqa.intervalMetadata.peripherals.push({\n information: this.statsResults['audio-send']?.trackLabel,\n name: MEDIA_DEVICES.MICROPHONE,\n });\n }\n if (this.statsResults['video-send']) {\n newMqa.intervalMetadata.peripherals.push({\n information: this.statsResults['video-send']?.trackLabel,\n name: MEDIA_DEVICES.CAMERA,\n });\n }\n\n newMqa.networkType = this.statsResults.connectionType.local.networkType;\n\n this.mqaSentCount += 1;\n\n newMqa.intervalNumber = this.mqaSentCount;\n\n this.resetStatsResults();\n\n this.emit(\n {\n file: 'statsAnalyzer',\n function: 'sendMqaData',\n },\n EVENTS.MEDIA_QUALITY,\n {\n data: newMqa,\n // @ts-ignore\n networkType: newMqa.networkType,\n }\n );\n }\n\n /**\n * updated the media connection when changed\n *\n * @private\n * @memberof StatsAnalyzer\n * @param {RoapMediaConnection} mediaConnection\n * @returns {void}\n */\n updateMediaConnection(mediaConnection: any) {\n this.mediaConnection = mediaConnection;\n }\n\n /**\n * Starts the stats analyzer on interval\n *\n * @public\n * @memberof StatsAnalyzer\n * @param {RoapMediaConnection} mediaConnection\n * @returns {Promise}\n */\n public startAnalyzer(mediaConnection: any) {\n if (!this.statsStarted) {\n this.statsStarted = true;\n this.mediaConnection = mediaConnection;\n\n return this.getStatsAndParse().then(() => {\n this.statsInterval = setInterval(() => {\n this.getStatsAndParse();\n }, this.config.analyzerInterval);\n // Trigger initial fetch\n this.sendMqaData();\n this.mqaInterval = setInterval(() => {\n this.sendMqaData();\n }, MQA_INTEVAL);\n });\n }\n\n return Promise.resolve();\n }\n\n /**\n * Cleans up the analyzer when done\n *\n * @public\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n public stopAnalyzer() {\n const sendOneLastMqa = this.mqaInterval && this.statsInterval;\n\n if (this.statsInterval) {\n clearInterval(this.statsInterval);\n this.statsInterval = undefined;\n }\n\n if (this.mqaInterval) {\n clearInterval(this.mqaInterval);\n this.mqaInterval = undefined;\n }\n\n if (sendOneLastMqa) {\n return this.getStatsAndParse().then(() => {\n this.sendMqaData();\n this.mediaConnection = null;\n });\n }\n this.mediaConnection = null;\n\n return Promise.resolve();\n }\n\n /**\n * Parse a single result of get stats\n *\n * @private\n * @param {*} getStatsResult\n * @param {String} type\n * @param {boolean} isSender\n * @returns {void}\n * @memberof StatsAnalyzer\n */\n private parseGetStatsResult(getStatsResult: any, type: string, isSender: boolean) {\n if (!getStatsResult) {\n return;\n }\n\n // Generate empty stats results\n if (!this.statsResults[type]) {\n this.statsResults[type] = {};\n }\n\n if (isSender && !this.statsResults[type].send) {\n this.statsResults[type].send = cloneDeep(emptySender);\n } else if (!isSender && !this.statsResults[type].recv) {\n this.statsResults[type].recv = cloneDeep(emptyReceiver);\n }\n\n if (!this.statsResults.resolutions[type]) {\n this.statsResults.resolutions[type] = {};\n }\n\n if (isSender && !this.statsResults.resolutions[type].send) {\n this.statsResults.resolutions[type].send = cloneDeep(emptySender);\n } else if (!isSender && !this.statsResults.resolutions[type].recv) {\n this.statsResults.resolutions[type].recv = cloneDeep(emptyReceiver);\n }\n\n if (!this.statsResults.internal[type]) {\n this.statsResults.internal[type] = {};\n }\n\n if (isSender && !this.statsResults.internal[type].send) {\n this.statsResults.internal[type].send = cloneDeep(emptySender);\n } else if (!isSender && !this.statsResults.internal[type].recv) {\n this.statsResults.internal[type].recv = cloneDeep(emptyReceiver);\n }\n\n switch (getStatsResult.type) {\n case 'outbound-rtp':\n this.processOutboundRTPResult(getStatsResult, type);\n break;\n case 'inbound-rtp':\n this.processInboundRTPResult(getStatsResult, type);\n break;\n case 'track':\n this.processTrackResult(getStatsResult, type);\n break;\n case 'remote-inbound-rtp':\n case 'remote-outbound-rtp':\n // @ts-ignore\n this.compareSentAndReceived(getStatsResult, type, isSender);\n break;\n case 'remotecandidate':\n case 'remote-candidate':\n this.parseCandidate(getStatsResult, type, isSender, true);\n break;\n case 'local-candidate':\n this.parseCandidate(getStatsResult, type, isSender, false);\n break;\n case 'media-source':\n // @ts-ignore\n this.parseAudioSource(getStatsResult, type);\n break;\n default:\n break;\n }\n }\n\n /**\n * Filters the get stats results for types\n * @private\n * @param {Array} statsItem\n * @param {String} type\n * @param {boolean} isSender\n * @returns {void}\n */\n filterAndParseGetStatsResults(statsItem: any, type: string, isSender: boolean) {\n const {types} = DEFAULT_GET_STATS_FILTER;\n\n statsItem.report.forEach((result) => {\n if (types.includes(result.type)) {\n this.parseGetStatsResult(result, type, isSender);\n }\n });\n\n if (this.statsResults[type]) {\n this.statsResults[type].direction = statsItem.currentDirection;\n this.statsResults[type].trackLabel = statsItem.localTrackLabel;\n this.statsResults[type].csi = statsItem.csi;\n }\n }\n\n /**\n * parse the audio\n * @param {String} result\n * @param {boolean} type\n * @returns {void}\n */\n parseAudioSource(result: any, type: any) {\n if (!result) {\n return;\n }\n\n if (type.includes('audio-send')) {\n this.statsResults[type].send.audioLevel = result.audioLevel;\n this.statsResults[type].send.totalAudioEnergy = result.totalAudioEnergy;\n }\n }\n\n /**\n * emits started/stopped events for local/remote media by checking\n * if given values are increasing or not. The previousValue, currentValue\n * params can be any numerical value like number of receive packets or\n * decoded frames, etc.\n *\n * @private\n * @param {string} mediaType\n * @param {number} previousValue - value to compare\n * @param {number} currentValue - value to compare (must be same type of value as previousValue)\n * @param {boolean} isLocal - true if stats are for local media being sent out, false for remote media being received\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n emitStartStopEvents = (\n mediaType: string,\n previousValue: number,\n currentValue: number,\n isLocal: boolean\n ) => {\n if (mediaType !== 'audio' && mediaType !== 'video' && mediaType !== 'share') {\n throw new Error(`Unsupported mediaType: ${mediaType}`);\n }\n\n // eslint-disable-next-line no-param-reassign\n if (previousValue === undefined) previousValue = 0;\n // eslint-disable-next-line no-param-reassign\n if (currentValue === undefined) currentValue = 0;\n\n if (!this.lastEmittedStartStopEvent[mediaType]) {\n this.lastEmittedStartStopEvent[mediaType] = {};\n }\n\n const lastEmittedEvent = isLocal\n ? this.lastEmittedStartStopEvent[mediaType].local\n : this.lastEmittedStartStopEvent[mediaType].remote;\n\n let newEvent;\n\n if (currentValue - previousValue > 0) {\n newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STARTED : EVENTS.REMOTE_MEDIA_STARTED;\n } else if (currentValue === previousValue && currentValue > 0) {\n newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STOPPED : EVENTS.REMOTE_MEDIA_STOPPED;\n }\n\n if (newEvent && lastEmittedEvent !== newEvent) {\n if (isLocal) {\n this.lastEmittedStartStopEvent[mediaType].local = newEvent;\n } else {\n this.lastEmittedStartStopEvent[mediaType].remote = newEvent;\n }\n this.emit(\n {\n file: 'statsAnalyzer/index',\n function: 'compareLastStatsResult',\n },\n newEvent,\n {\n type: mediaType,\n }\n );\n }\n };\n\n /**\n * compares current and previous stats to check if packets are not sent\n *\n * @private\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n private compareLastStatsResult() {\n if (this.lastStatsResults !== null && this.meetingMediaStatus) {\n const getCurrentStatsTotals = (keyPrefix: string, value: string): number =>\n Object.keys(this.statsResults)\n .filter((key) => key.startsWith(keyPrefix))\n .reduce((prev, cur) => prev + (this.statsResults[cur].recv[value] || 0), 0);\n\n const getPreviousStatsTotals = (keyPrefix: string, value: string): number =>\n Object.keys(this.statsResults)\n .filter((key) => key.startsWith(keyPrefix))\n .reduce((prev, cur) => prev + (this.lastStatsResults[cur].recv[value] || 0), 0);\n\n const getCurrentResolutionsStatsTotals = (keyPrefix: string, value: string): number =>\n Object.keys(this.statsResults)\n .filter((key) => key.startsWith(keyPrefix))\n .reduce((prev, cur) => prev + (this.statsResults.resolutions[cur].recv[value] || 0), 0);\n\n const getPreviousResolutionsStatsTotals = (keyPrefix: string, value: string): number =>\n Object.keys(this.statsResults)\n .filter((key) => key.startsWith(keyPrefix))\n .reduce(\n (prev, cur) => prev + (this.lastStatsResults.resolutions[cur].recv[value] || 0),\n 0\n );\n\n if (this.meetingMediaStatus.expected.sendAudio && this.lastStatsResults['audio-send']) {\n // compare audio stats sent\n // NOTE: relies on there being only one sender.\n const currentStats = this.statsResults['audio-send'].send;\n const previousStats = this.lastStatsResults['audio-send'].send;\n\n if (\n currentStats.totalPacketsSent === previousStats.totalPacketsSent ||\n currentStats.totalPacketsSent === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent`\n );\n } else {\n if (\n currentStats.totalAudioEnergy === previousStats.totalAudioEnergy ||\n currentStats.totalAudioEnergy === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present`\n );\n }\n\n if (currentStats.audioLevel === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> audio level is 0 for the user`\n );\n }\n }\n\n this.emitStartStopEvents(\n 'audio',\n previousStats.totalPacketsSent,\n currentStats.totalPacketsSent,\n true\n );\n }\n\n if (this.meetingMediaStatus.expected.receiveAudio) {\n // compare audio stats received\n const currentPacketsReceived = getCurrentStatsTotals('audio-recv', 'totalPacketsReceived');\n const previousPacketsReceived = getPreviousStatsTotals(\n 'audio-recv',\n 'totalPacketsReceived'\n );\n const currentSamplesReceived = getCurrentStatsTotals('audio-recv', 'totalSamplesReceived');\n const previousSamplesReceived = getPreviousStatsTotals(\n 'audio-recv',\n 'totalSamplesReceived'\n );\n\n if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received`\n );\n } else if (\n currentSamplesReceived === previousSamplesReceived ||\n currentSamplesReceived === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No audio samples received`\n );\n }\n\n this.emitStartStopEvents('audio', previousPacketsReceived, currentPacketsReceived, false);\n }\n\n if (this.meetingMediaStatus.expected.sendVideo && this.lastStatsResults['video-send']) {\n // compare video stats sent\n const currentStats = this.statsResults['video-send'].send;\n const previousStats = this.lastStatsResults['video-send'].send;\n\n if (\n currentStats.totalPacketsSent === previousStats.totalPacketsSent ||\n currentStats.totalPacketsSent === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent`\n );\n } else {\n if (\n currentStats.framesEncoded === previousStats.framesEncoded ||\n currentStats.framesEncoded === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded`\n );\n }\n\n if (\n this.statsResults.resolutions['video-send'].send.framesSent ===\n this.lastStatsResults.resolutions['video-send'].send.framesSent ||\n this.statsResults.resolutions['video-send'].send.framesSent === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent`\n );\n }\n }\n\n this.emitStartStopEvents('video', previousStats.framesSent, currentStats.framesSent, true);\n }\n\n if (this.meetingMediaStatus.expected.receiveVideo) {\n // compare video stats received\n const currentPacketsReceived = getCurrentStatsTotals('video-recv', 'totalPacketsReceived');\n const previousPacketsReceived = getPreviousStatsTotals(\n 'video-recv',\n 'totalPacketsReceived'\n );\n const currentFramesReceived = getCurrentResolutionsStatsTotals(\n 'video-recv',\n 'framesReceived'\n );\n const previousFramesReceived = getPreviousResolutionsStatsTotals(\n 'video-recv',\n 'framesReceived'\n );\n const currentFramesDecoded = getCurrentStatsTotals('video-recv', 'framesDecoded');\n const previousFramesDecoded = getPreviousStatsTotals('video-recv', 'framesDecoded');\n const currentFramesDropped = getCurrentResolutionsStatsTotals(\n 'video-recv',\n 'framesDropped'\n );\n const previousFramesDropped = getPreviousResolutionsStatsTotals(\n 'video-recv',\n 'framesDropped'\n );\n\n if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets received`\n );\n } else {\n if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video frames received`\n );\n }\n\n if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video frames decoded`\n );\n }\n\n if (currentFramesDropped - previousFramesDropped > 10) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> video frames are getting dropped`\n );\n }\n }\n\n this.emitStartStopEvents('video', previousFramesDecoded, currentFramesDecoded, false);\n }\n\n if (this.meetingMediaStatus.expected.sendShare && this.lastStatsResults['video-share-send']) {\n // compare share stats sent\n\n const currentStats = this.statsResults['video-share-send'].send;\n const previousStats = this.lastStatsResults['video-share-send'].send;\n\n if (\n currentStats.totalPacketsSent === previousStats.totalPacketsSent ||\n currentStats.totalPacketsSent === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent`\n );\n } else {\n if (\n currentStats.framesEncoded === previousStats.framesEncoded ||\n currentStats.framesEncoded === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded`\n );\n }\n\n if (\n this.statsResults.resolutions['video-share-send'].send.framesSent ===\n this.lastStatsResults.resolutions['video-share-send'].send.framesSent ||\n this.statsResults.resolutions['video-share-send'].send.framesSent === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share frames sent`\n );\n }\n }\n }\n\n if (this.meetingMediaStatus.expected.sendShare) {\n // TODO:need to check receive share value\n // compare share stats received\n const currentPacketsReceived = getCurrentStatsTotals(\n 'video-share-recv',\n 'totalPacketsReceived'\n );\n const previousPacketsReceived = getPreviousStatsTotals(\n 'video-share-recv',\n 'totalPacketsReceived'\n );\n const currentFramesReceived = getCurrentResolutionsStatsTotals(\n 'video-share-recv',\n 'framesReceived'\n );\n const previousFramesReceived = getPreviousResolutionsStatsTotals(\n 'video-share-recv',\n 'framesReceived'\n );\n const currentFramesDecoded = getCurrentStatsTotals('video-share-recv', 'framesDecoded');\n const previousFramesDecoded = getPreviousStatsTotals('video-share-recv', 'framesDecoded');\n const currentFramesDropped = getCurrentResolutionsStatsTotals(\n 'video-share-recv',\n 'framesDropped'\n );\n const previousFramesDropped = getPreviousResolutionsStatsTotals(\n 'video-share-recv',\n 'framesDropped'\n );\n\n if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets received`\n );\n } else {\n if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share frames received`\n );\n }\n\n if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share frames decoded`\n );\n }\n\n if (currentFramesDropped - previousFramesDropped > 10) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> share frames are getting dropped`\n );\n }\n }\n\n // we are not calling emitStartStopEvents() for sending or receiving share because sharing is often started and stopped\n // in meetings and this.meetingMediaStatus.expected values can be out of sync with the actual packet flow\n // so we would send \"sharing stopped\" events incorrectly\n }\n }\n }\n\n /**\n * Does a `getStats` on all the transceivers and parses the results\n *\n * @private\n * @memberof StatsAnalyzer\n * @returns {Promise}\n */\n private getStatsAndParse() {\n if (!this.mediaConnection) {\n return Promise.resolve();\n }\n\n if (\n this.mediaConnection &&\n this.mediaConnection.getConnectionState() === ConnectionState.Failed\n ) {\n LoggerProxy.logger.trace(\n 'StatsAnalyzer:index#getStatsAndParse --> media connection is in failed state'\n );\n\n return Promise.resolve();\n }\n\n LoggerProxy.logger.trace('StatsAnalyzer:index#getStatsAndParse --> Collecting Stats');\n\n return this.mediaConnection.getTransceiverStats().then((transceiverStats) => {\n transceiverStats.video.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `video-recv-${i}`, false)\n );\n transceiverStats.audio.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `audio-recv-${i}`, false)\n );\n transceiverStats.screenShareVideo.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `video-share-recv-${i}`, false)\n );\n transceiverStats.screenShareAudio.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `audio-share-recv-${i}`, false)\n );\n\n transceiverStats.video.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'video-send', true);\n });\n transceiverStats.audio.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'audio-send', true);\n });\n transceiverStats.screenShareVideo.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'video-share-send', true);\n });\n transceiverStats.screenShareAudio.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'audio-share-send', true);\n });\n\n this.compareLastStatsResult();\n\n // Save the last results to compare with the current\n // DO Deep copy, for some reason it takes the reference all the time rather then old value set\n this.lastStatsResults = JSON.parse(JSON.stringify(this.statsResults));\n\n LoggerProxy.logger.trace(\n 'StatsAnalyzer:index#getStatsAndParse --> Finished Collecting Stats'\n );\n });\n }\n\n /**\n * Processes OutboundRTP stats result and stores\n * @private\n * @param {*} result\n * @param {*} mediaType\n * @returns {void}\n */\n private processOutboundRTPResult(result: any, mediaType: any) {\n const sendrecvType = STATS.SEND_DIRECTION;\n\n if (result.bytesSent) {\n let kilobytes = 0;\n\n if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesSent) {\n this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;\n }\n if (!this.statsResults.internal[mediaType][sendrecvType].framesEncoded) {\n this.statsResults.internal[mediaType][sendrecvType].framesEncoded = result.framesEncoded;\n }\n if (!this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded) {\n this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded =\n result.keyFramesEncoded;\n }\n\n const bytes =\n result.bytesSent - this.statsResults.internal[mediaType][sendrecvType].prevBytesSent;\n\n this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;\n\n kilobytes = bytes / 1024;\n\n this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);\n this.statsResults[mediaType].bytesSent = kilobytes;\n\n this.statsResults[mediaType][sendrecvType].framesEncoded =\n result.framesEncoded - this.statsResults.internal[mediaType][sendrecvType].framesEncoded;\n this.statsResults[mediaType][sendrecvType].keyFramesEncoded =\n result.keyFramesEncoded -\n this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded;\n this.statsResults.internal[mediaType].outboundRtpId = result.id;\n\n if (!this.statsResults.internal[mediaType][sendrecvType].packetsSent) {\n this.statsResults.internal[mediaType][sendrecvType].packetsSent = result.packetsSent;\n }\n\n this.statsResults[mediaType][sendrecvType].packetsSent =\n result.packetsSent - this.statsResults.internal[mediaType][sendrecvType].packetsSent;\n this.statsResults.internal[mediaType][sendrecvType].packetsSent = result.packetsSent;\n\n // Data saved to send MQA metrics\n\n this.statsResults[mediaType][sendrecvType].totalKeyFramesEncoded = result.keyFramesEncoded;\n this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;\n this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;\n this.statsResults[mediaType][sendrecvType].totalPacketsSent = result.packetsSent;\n this.statsResults[mediaType][sendrecvType].totalFirCount = result.firCount;\n this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;\n this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;\n this.statsResults[mediaType][sendrecvType].encoderImplementation =\n result.encoderImplementation;\n this.statsResults[mediaType][sendrecvType].qualityLimitationReason =\n result.qualityLimitationReason;\n this.statsResults[mediaType][sendrecvType].qualityLimitationResolutionChanges =\n result.qualityLimitationResolutionChanges;\n this.statsResults[mediaType][sendrecvType].retransmittedPacketsSent =\n result.retransmittedPacketsSent;\n this.statsResults[mediaType][sendrecvType].totalBytesSent = result.bytesSent;\n this.statsResults[mediaType][sendrecvType].headerBytesSent = result.headerBytesSent;\n this.statsResults[mediaType][sendrecvType].retransmittedBytesSent =\n result.retransmittedBytesSent;\n }\n }\n\n /**\n * Processes InboundRTP stats result and stores\n * @private\n * @param {*} result\n * @param {*} mediaType\n * @returns {void}\n */\n private processInboundRTPResult(result: any, mediaType: any) {\n const sendrecvType = STATS.RECEIVE_DIRECTION;\n\n if (result.bytesReceived) {\n let kilobytes = 0;\n\n if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived) {\n this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived =\n result.bytesReceived;\n }\n\n if (!this.statsResults.internal[mediaType][sendrecvType].pliCount) {\n this.statsResults.internal[mediaType][sendrecvType].pliCount = result.pliCount;\n }\n\n if (!this.statsResults.internal[mediaType][sendrecvType].packetsLost) {\n this.statsResults.internal[mediaType][sendrecvType].packetsLost = result.packetsLost;\n }\n\n if (!this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived) {\n this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived =\n result.packetsReceived;\n }\n\n if (!this.statsResults.internal[mediaType][sendrecvType].lastPacketReceivedTimestamp) {\n this.statsResults.internal[mediaType][sendrecvType].lastPacketReceivedTimestamp =\n result.lastPacketReceivedTimestamp;\n }\n\n const bytes =\n result.bytesReceived -\n this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived;\n\n this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived = result.bytesReceived;\n\n kilobytes = bytes / 1024;\n this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);\n this.statsResults[mediaType].bytesReceived = kilobytes.toFixed(1);\n\n this.statsResults[mediaType][sendrecvType].pliCount =\n result.pliCount - this.statsResults.internal[mediaType][sendrecvType].pliCount;\n this.statsResults[mediaType][sendrecvType].currentPacketsLost =\n result.packetsLost - this.statsResults.internal[mediaType][sendrecvType].packetsLost;\n if (this.statsResults[mediaType][sendrecvType].currentPacketsLost < 0) {\n this.statsResults[mediaType][sendrecvType].currentPacketsLost = 0;\n }\n\n this.statsResults[mediaType][sendrecvType].packetsReceived =\n result.packetsReceived -\n this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived;\n this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived =\n result.packetsReceived;\n\n if (this.statsResults[mediaType][sendrecvType].packetsReceived === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#processInboundRTPResult --> No packets received for ${mediaType} `,\n this.statsResults[mediaType][sendrecvType].packetsReceived\n );\n }\n\n // Check the over all packet Lost ratio\n this.statsResults[mediaType][sendrecvType].currentPacketLossRatio =\n this.statsResults[mediaType][sendrecvType].currentPacketsLost > 0\n ? this.statsResults[mediaType][sendrecvType].currentPacketsLost /\n (this.statsResults[mediaType][sendrecvType].packetsReceived +\n this.statsResults[mediaType][sendrecvType].currentPacketsLost)\n : 0;\n if (this.statsResults[mediaType][sendrecvType].currentPacketLossRatio > 3) {\n LoggerProxy.logger.info(\n 'StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver ',\n this.statsResults[mediaType][sendrecvType].currentPacketLossRatio\n );\n }\n\n // TODO: check the packet loss value is negative values here\n\n if (result.packetsLost) {\n this.statsResults[mediaType][sendrecvType].totalPacketsLost =\n result.packetsLost > 0 ? result.packetsLost : -result.packetsLost;\n } else {\n this.statsResults[mediaType][sendrecvType].totalPacketsLost = 0;\n }\n\n this.statsResults[mediaType][sendrecvType].lastPacketReceivedTimestamp =\n result.lastPacketReceivedTimestamp;\n\n // From Thin\n this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;\n this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;\n this.statsResults[mediaType][sendrecvType].framesDecoded = result.framesDecoded;\n this.statsResults[mediaType][sendrecvType].keyFramesDecoded = result.keyFramesDecoded;\n\n this.statsResults[mediaType][sendrecvType].decoderImplementation =\n result.decoderImplementation;\n this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;\n\n this.statsResults[mediaType][sendrecvType].fecPacketsDiscarded = result.fecPacketsDiscarded;\n this.statsResults[mediaType][sendrecvType].fecPacketsReceived = result.fecPacketsReceived;\n this.statsResults[mediaType][sendrecvType].totalBytesReceived = result.bytesReceived;\n this.statsResults[mediaType][sendrecvType].headerBytesReceived = result.headerBytesReceived;\n\n this.statsResults[mediaType][sendrecvType].meanRtpJitter.push(result.jitter);\n\n // Audio stats\n\n this.statsResults[mediaType][sendrecvType].audioLevel = result.audioLevel;\n this.statsResults[mediaType][sendrecvType].totalAudioEnergy = result.totalAudioEnergy;\n this.statsResults[mediaType][sendrecvType].totalSamplesReceived =\n result.totalSamplesReceived || 0;\n this.statsResults[mediaType][sendrecvType].totalSamplesDecoded =\n result.totalSamplesDecoded || 0;\n this.statsResults[mediaType][sendrecvType].concealedSamples = result.concealedSamples || 0;\n }\n }\n\n /**\n * Processes remote and local candidate result and stores\n * @private\n * @param {*} result\n * @param {*} type\n * @param {boolean} isSender\n * @param {boolean} isRemote\n *\n * @returns {void}\n */\n parseCandidate = (result: any, type: any, isSender: boolean, isRemote: boolean) => {\n if (!result || !result.id) {\n return;\n }\n const RemoteCandidateType = {};\n const RemoteTransport = {};\n const RemoteIpAddress = {};\n const RemoteNetworkType = {};\n\n if (!result.id) return;\n\n const sendRecvType = isSender ? STATS.SEND_DIRECTION : STATS.RECEIVE_DIRECTION;\n const ipType = isRemote ? STATS.REMOTE : STATS.LOCAL;\n\n if (!RemoteCandidateType[result.id]) {\n RemoteCandidateType[result.id] = [];\n }\n\n if (!RemoteTransport[result.id]) {\n RemoteTransport[result.id] = [];\n }\n\n if (!RemoteIpAddress[result.id]) {\n RemoteIpAddress[result.id] = [];\n }\n if (!RemoteNetworkType[result.id]) {\n RemoteNetworkType[result.id] = [];\n }\n\n if (\n result.candidateType &&\n RemoteCandidateType[result.id].indexOf(result.candidateType) === -1\n ) {\n RemoteCandidateType[result.id].push(result.candidateType);\n }\n\n if (result.protocol && RemoteTransport[result.id].indexOf(result.protocol) === -1) {\n RemoteTransport[result.id].push(result.protocol.toUpperCase());\n }\n\n if (\n result.ip &&\n RemoteIpAddress[result.id].indexOf(`${result.ip}:${result.portNumber}`) === -1\n ) {\n RemoteIpAddress[result.id].push(`${result.ip}`); // TODO: Add ports\n }\n\n if (result.networkType && RemoteNetworkType[result.id].indexOf(result.networkType) === -1) {\n RemoteNetworkType[result.id].push(result.networkType);\n }\n\n this.statsResults.internal.candidates[result.id] = {\n candidateType: RemoteCandidateType[result.id],\n ipAddress: RemoteIpAddress[result.id],\n portNumber: result.port,\n networkType: RemoteNetworkType[result.id],\n priority: result.priority,\n transport: RemoteTransport[result.id],\n timestamp: result.time,\n id: result.id,\n type: result.type,\n };\n\n this.statsResults.connectionType[ipType].candidateType = RemoteCandidateType[result.id];\n this.statsResults.connectionType[ipType].ipAddress = RemoteIpAddress[result.id];\n\n this.statsResults.connectionType[ipType].networkType =\n RemoteNetworkType[result.id][0] === NETWORK_TYPE.VPN\n ? NETWORK_TYPE.UNKNOWN\n : RemoteNetworkType[result.id][0];\n this.statsResults.connectionType[ipType].transport = RemoteTransport[result.id];\n\n this.statsResults[type][sendRecvType].totalRoundTripTime = result.totalRoundTripTime;\n };\n\n /**\n * Process Track results\n *\n * @private\n * @param {*} result\n * @param {*} mediaType\n * @returns {void}\n * @memberof StatsAnalyzer\n */\n private processTrackResult(result: any, mediaType: any) {\n if (!result || result.type !== 'track') {\n return;\n }\n\n const sendrecvType =\n result.remoteSource === true ? STATS.RECEIVE_DIRECTION : STATS.SEND_DIRECTION;\n\n if (result.frameWidth && result.frameHeight) {\n this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;\n this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;\n this.statsResults.resolutions[mediaType][sendrecvType].framesSent = result.framesSent;\n this.statsResults.resolutions[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;\n }\n\n if (sendrecvType === STATS.RECEIVE_DIRECTION) {\n this.statsResults.resolutions[mediaType][sendrecvType].framesReceived = result.framesReceived;\n this.statsResults.resolutions[mediaType][sendrecvType].framesDecoded = result.framesDecoded;\n this.statsResults.resolutions[mediaType][sendrecvType].framesDropped = result.framesDropped;\n }\n\n if (result.trackIdentifier && !mediaType.includes('audio')) {\n this.statsResults.resolutions[mediaType][sendrecvType].trackIdentifier =\n result.trackIdentifier;\n\n const jitterBufferDelay = result && result.jitterBufferDelay;\n const jitterBufferEmittedCount = result && result.jitterBufferEmittedCount;\n\n this.statsResults.resolutions[mediaType][sendrecvType].avgJitterDelay =\n jitterBufferEmittedCount && +jitterBufferDelay / +jitterBufferEmittedCount;\n\n // Used to calculate the jitter\n this.statsResults.resolutions[mediaType][sendrecvType].jitterBufferDelay =\n result.jitterBufferDelay;\n this.statsResults.resolutions[mediaType][sendrecvType].jitterBufferEmittedCount =\n result.jitterBufferEmittedCount;\n }\n }\n\n /**\n *\n * @private\n * @param {*} result\n * @param {*} type\n * @returns {void}\n * @memberof StatsAnalyzer\n */\n compareSentAndReceived(result, type) {\n // Don't compare on transceivers without a sender.\n if (!type || !this.statsResults.internal[type].send) {\n return;\n }\n\n const mediaType = type;\n\n if (!this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver) {\n this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;\n }\n\n const currentPacketLoss =\n result.packetsLost - this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver;\n\n this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;\n this.statsResults[mediaType].send.packetsLostOnReceiver = currentPacketLoss;\n this.statsResults[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;\n\n this.statsResults[mediaType].send.meanRemoteJitter.push(result.jitter);\n this.statsResults[mediaType].send.meanRoundTripTime.push(result.roundTripTime);\n\n this.statsResults[mediaType].send.timestamp = result.timestamp;\n this.statsResults[mediaType].send.ssrc = result.ssrc;\n this.statsResults[mediaType].send.reportsReceived = result.reportsReceived;\n\n // Total packloss ratio on this video section of the call\n this.statsResults[mediaType].send.overAllPacketLossRatio =\n this.statsResults[mediaType].send.totalPacketsLostOnReceiver > 0\n ? this.statsResults[mediaType].send.totalPacketsLostOnReceiver /\n this.statsResults[mediaType].send.totalPacketsSent\n : 0;\n this.statsResults[mediaType].send.currentPacketLossRatio =\n this.statsResults[mediaType].send.packetsLostOnReceiver > 0\n ? (this.statsResults[mediaType].send.packetsLostOnReceiver * 100) /\n (this.statsResults[mediaType].send.packetsSent +\n this.statsResults[mediaType].send.packetsLostOnReceiver)\n : 0;\n\n if (\n this.statsResults[mediaType].send.maxPacketLossRatio <\n this.statsResults[mediaType].send.currentPacketLossRatio\n ) {\n this.statsResults[mediaType].send.maxPacketLossRatio =\n this.statsResults[mediaType].send.currentPacketLossRatio;\n }\n\n if (result.type === 'remote-inbound-rtp') {\n this.networkQualityMonitor.determineUplinkNetworkQuality({\n mediaType,\n remoteRtpResults: result,\n statsAnalyzerCurrentStats: this.statsResults,\n });\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["EVENTS","MEDIA_QUALITY","LOCAL_MEDIA_STARTED","LOCAL_MEDIA_STOPPED","REMOTE_MEDIA_STARTED","REMOTE_MEDIA_STOPPED","emptySender","trackLabel","maxPacketLossRatio","availableBandwidth","bytesSent","meanRemoteJitter","meanRoundTripTime","emptyReceiver","bytesReceived","meanRtpJitter","StatsAnalyzer","config","networkQualityMonitor","statsResults","defaultStats","mediaType","previousValue","currentValue","isLocal","Error","undefined","lastEmittedStartStopEvent","lastEmittedEvent","local","remote","newEvent","emit","file","function","type","result","isSender","isRemote","id","RemoteCandidateType","RemoteTransport","RemoteIpAddress","RemoteNetworkType","sendRecvType","STATS","SEND_DIRECTION","RECEIVE_DIRECTION","ipType","REMOTE","LOCAL","candidateType","indexOf","push","protocol","toUpperCase","ip","portNumber","networkType","internal","candidates","ipAddress","port","priority","transport","timestamp","time","connectionType","NETWORK_TYPE","VPN","UNKNOWN","totalRoundTripTime","statsStarted","lastStatsResults","correlationId","mqaSentCount","lastMqaDataSent","forEach","includes","recv","send","status","meetingMediaStatus","newMqa","emptyMqaInterval","audioSender","emptyAudioTransmit","getAudioSenderMqa","audioTransmit","audioReceiver","emptyAudioReceive","getAudioReceiverMqa","audioReceive","videoSender","emptyVideoTransmit","getVideoSenderMqa","videoTransmit","videoReceiver","emptyVideoReceive","getVideoReceiverMqa","videoReceive","intervalMetadata","peerReflexiveIP","peripherals","information","_UNKNOWN_","name","MEDIA_DEVICES","SPEAKER","MICROPHONE","CAMERA","intervalNumber","resetStatsResults","data","mediaConnection","getStatsAndParse","then","statsInterval","setInterval","analyzerInterval","sendMqaData","mqaInterval","MQA_INTEVAL","resolve","sendOneLastMqa","clearInterval","getStatsResult","resolutions","processOutboundRTPResult","processInboundRTPResult","processTrackResult","compareSentAndReceived","parseCandidate","parseAudioSource","statsItem","types","DEFAULT_GET_STATS_FILTER","report","parseGetStatsResult","direction","currentDirection","localTrackLabel","csi","audioLevel","totalAudioEnergy","getCurrentStatsTotals","keyPrefix","value","filter","key","startsWith","reduce","prev","cur","getPreviousStatsTotals","getCurrentResolutionsStatsTotals","getPreviousResolutionsStatsTotals","expected","sendAudio","currentStats","previousStats","totalPacketsSent","LoggerProxy","logger","info","emitStartStopEvents","receiveAudio","currentPacketsReceived","previousPacketsReceived","currentSamplesReceived","previousSamplesReceived","sendVideo","framesEncoded","framesSent","receiveVideo","currentFramesReceived","previousFramesReceived","currentFramesDecoded","previousFramesDecoded","currentFramesDropped","previousFramesDropped","sendShare","getConnectionState","ConnectionState","Failed","trace","getTransceiverStats","transceiverStats","video","receivers","receiver","i","filterAndParseGetStatsResults","audio","screenShareVideo","screenShareAudio","senders","sender","compareLastStatsResult","JSON","parse","sendrecvType","kilobytes","prevBytesSent","keyFramesEncoded","bytes","toFixed","outboundRtpId","packetsSent","totalKeyFramesEncoded","totalNackCount","nackCount","totalPliCount","pliCount","totalFirCount","firCount","encoderImplementation","qualityLimitationReason","qualityLimitationResolutionChanges","retransmittedPacketsSent","totalBytesSent","headerBytesSent","retransmittedBytesSent","prevBytesReceived","packetsLost","totalPacketsReceived","packetsReceived","lastPacketReceivedTimestamp","currentPacketsLost","currentPacketLossRatio","totalPacketsLost","framesDecoded","keyFramesDecoded","decoderImplementation","fecPacketsDiscarded","fecPacketsReceived","totalBytesReceived","headerBytesReceived","jitter","totalSamplesReceived","totalSamplesDecoded","concealedSamples","remoteSource","frameWidth","frameHeight","width","height","hugeFramesSent","framesReceived","framesDropped","trackIdentifier","jitterBufferDelay","jitterBufferEmittedCount","avgJitterDelay","totalPacketsLostOnReceiver","currentPacketLoss","packetsLostOnReceiver","roundTripTime","ssrc","reportsReceived","overAllPacketLossRatio","determineUplinkNetworkQuality","remoteRtpResults","statsAnalyzerCurrentStats","EventsScope"],"sources":["index.ts"],"sourcesContent":["/* eslint-disable prefer-destructuring */\n\nimport {cloneDeep} from 'lodash';\nimport {ConnectionState} from '@webex/internal-media-core';\n\nimport EventsScope from '../common/events/events-scope';\nimport {\n DEFAULT_GET_STATS_FILTER,\n STATS,\n MQA_INTEVAL,\n NETWORK_TYPE,\n MEDIA_DEVICES,\n _UNKNOWN_,\n} from '../constants';\nimport {\n emptyAudioReceive,\n emptyAudioTransmit,\n emptyMqaInterval,\n emptyVideoReceive,\n emptyVideoTransmit,\n} from '../mediaQualityMetrics/config';\nimport LoggerProxy from '../common/logs/logger-proxy';\n\nimport defaultStats from './global';\nimport {\n getAudioSenderMqa,\n getAudioReceiverMqa,\n getVideoSenderMqa,\n getVideoReceiverMqa,\n} from './mqaUtil';\n\nexport const EVENTS = {\n MEDIA_QUALITY: 'MEDIA_QUALITY',\n LOCAL_MEDIA_STARTED: 'LOCAL_MEDIA_STARTED',\n LOCAL_MEDIA_STOPPED: 'LOCAL_MEDIA_STOPPED',\n REMOTE_MEDIA_STARTED: 'REMOTE_MEDIA_STARTED',\n REMOTE_MEDIA_STOPPED: 'REMOTE_MEDIA_STOPPED',\n};\n\nconst emptySender = {\n trackLabel: '',\n maxPacketLossRatio: 0,\n availableBandwidth: 0,\n bytesSent: 0,\n meanRemoteJitter: [],\n meanRoundTripTime: [],\n};\n\nconst emptyReceiver = {\n availableBandwidth: 0,\n bytesReceived: 0,\n meanRtpJitter: [],\n meanRoundTripTime: [],\n};\n\n/**\n * Stats Analyzer class that will emit events based on detected quality\n *\n * @export\n * @class StatsAnalyzer\n * @extends {EventsScope}\n */\nexport class StatsAnalyzer extends EventsScope {\n config: any;\n correlationId: any;\n lastEmittedStartStopEvent: any;\n lastMqaDataSent: any;\n lastStatsResults: any;\n meetingMediaStatus: any;\n mqaInterval: NodeJS.Timeout;\n mqaSentCount: any;\n networkQualityMonitor: any;\n mediaConnection: any;\n statsInterval: NodeJS.Timeout;\n statsResults: any;\n statsStarted: any;\n\n /**\n * Creates a new instance of StatsAnalyzer\n * @constructor\n * @public\n * @param {Object} config SDK Configuration Object\n * @param {Object} networkQualityMonitor class for assessing network characteristics (jitter, packetLoss, latency)\n * @param {Object} statsResults Default properties for stats\n */\n constructor(\n config: any,\n networkQualityMonitor: object = {},\n statsResults: object = defaultStats\n ) {\n super();\n this.statsStarted = false;\n this.statsResults = statsResults;\n this.lastStatsResults = null;\n this.config = config;\n this.networkQualityMonitor = networkQualityMonitor;\n this.correlationId = config.correlationId;\n this.mqaSentCount = -1;\n this.lastMqaDataSent = {};\n this.lastEmittedStartStopEvent = {};\n }\n\n /**\n * Resets cumulative stats arrays.\n *\n * @public\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n resetStatsResults() {\n Object.keys(this.statsResults).forEach((mediaType) => {\n if (mediaType.includes('recv')) {\n this.statsResults[mediaType].recv.meanRtpJitter = [];\n }\n\n if (mediaType.includes('send')) {\n this.statsResults[mediaType].send.meanRemoteJitter = [];\n this.statsResults[mediaType].send.meanRoundTripTime = [];\n }\n });\n }\n\n /**\n * sets mediaStatus status for analyzing metrics\n *\n * @public\n * @param {Object} status for the audio and video\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n public updateMediaStatus(status: object) {\n this.meetingMediaStatus = status;\n }\n\n /**\n * captures MQA data from media connection\n *\n * @public\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n sendMqaData() {\n const newMqa = cloneDeep(emptyMqaInterval);\n\n Object.keys(this.statsResults).forEach((mediaType) => {\n if (mediaType.includes('audio-send') || mediaType.includes('audio-share-send')) {\n const audioSender = cloneDeep(emptyAudioTransmit);\n\n getAudioSenderMqa({\n audioSender,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.audioTransmit.push(audioSender);\n } else if (mediaType.includes('audio-recv') || mediaType.includes('audio-share-recv')) {\n const audioReceiver = cloneDeep(emptyAudioReceive);\n\n getAudioReceiverMqa({\n audioReceiver,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.audioReceive.push(audioReceiver);\n } else if (mediaType.includes('video-send') || mediaType.includes('video-share-send')) {\n const videoSender = cloneDeep(emptyVideoTransmit);\n\n getVideoSenderMqa({\n videoSender,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.videoTransmit.push(videoSender);\n } else if (mediaType.includes('video-recv') || mediaType.includes('video-share-recv')) {\n const videoReceiver = cloneDeep(emptyVideoReceive);\n\n getVideoReceiverMqa({\n videoReceiver,\n statsResults: this.statsResults,\n lastMqaDataSent: this.lastMqaDataSent,\n mediaType,\n });\n newMqa.videoReceive.push(videoReceiver);\n }\n });\n\n newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress[0];\n\n // Adding peripheral information\n newMqa.intervalMetadata.peripherals = [];\n\n newMqa.intervalMetadata.peripherals.push({information: _UNKNOWN_, name: MEDIA_DEVICES.SPEAKER});\n if (this.statsResults['audio-send']) {\n newMqa.intervalMetadata.peripherals.push({\n information: this.statsResults['audio-send']?.trackLabel,\n name: MEDIA_DEVICES.MICROPHONE,\n });\n }\n if (this.statsResults['video-send']) {\n newMqa.intervalMetadata.peripherals.push({\n information: this.statsResults['video-send']?.trackLabel,\n name: MEDIA_DEVICES.CAMERA,\n });\n }\n\n newMqa.networkType = this.statsResults.connectionType.local.networkType;\n\n this.mqaSentCount += 1;\n\n newMqa.intervalNumber = this.mqaSentCount;\n\n this.resetStatsResults();\n\n this.emit(\n {\n file: 'statsAnalyzer',\n function: 'sendMqaData',\n },\n EVENTS.MEDIA_QUALITY,\n {\n data: newMqa,\n // @ts-ignore\n networkType: newMqa.networkType,\n }\n );\n }\n\n /**\n * updated the media connection when changed\n *\n * @private\n * @memberof StatsAnalyzer\n * @param {RoapMediaConnection} mediaConnection\n * @returns {void}\n */\n updateMediaConnection(mediaConnection: any) {\n this.mediaConnection = mediaConnection;\n }\n\n /**\n * Starts the stats analyzer on interval\n *\n * @public\n * @memberof StatsAnalyzer\n * @param {RoapMediaConnection} mediaConnection\n * @returns {Promise}\n */\n public startAnalyzer(mediaConnection: any) {\n if (!this.statsStarted) {\n this.statsStarted = true;\n this.mediaConnection = mediaConnection;\n\n return this.getStatsAndParse().then(() => {\n this.statsInterval = setInterval(() => {\n this.getStatsAndParse();\n }, this.config.analyzerInterval);\n // Trigger initial fetch\n this.sendMqaData();\n this.mqaInterval = setInterval(() => {\n this.sendMqaData();\n }, MQA_INTEVAL);\n });\n }\n\n return Promise.resolve();\n }\n\n /**\n * Cleans up the analyzer when done\n *\n * @public\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n public stopAnalyzer() {\n const sendOneLastMqa = this.mqaInterval && this.statsInterval;\n\n if (this.statsInterval) {\n clearInterval(this.statsInterval);\n this.statsInterval = undefined;\n }\n\n if (this.mqaInterval) {\n clearInterval(this.mqaInterval);\n this.mqaInterval = undefined;\n }\n\n if (sendOneLastMqa) {\n return this.getStatsAndParse().then(() => {\n this.sendMqaData();\n this.mediaConnection = null;\n });\n }\n this.mediaConnection = null;\n\n return Promise.resolve();\n }\n\n /**\n * Parse a single result of get stats\n *\n * @private\n * @param {*} getStatsResult\n * @param {String} type\n * @param {boolean} isSender\n * @returns {void}\n * @memberof StatsAnalyzer\n */\n private parseGetStatsResult(getStatsResult: any, type: string, isSender: boolean) {\n if (!getStatsResult) {\n return;\n }\n\n // Generate empty stats results\n if (!this.statsResults[type]) {\n this.statsResults[type] = {};\n }\n\n if (isSender && !this.statsResults[type].send) {\n this.statsResults[type].send = cloneDeep(emptySender);\n } else if (!isSender && !this.statsResults[type].recv) {\n this.statsResults[type].recv = cloneDeep(emptyReceiver);\n }\n\n if (!this.statsResults.resolutions[type]) {\n this.statsResults.resolutions[type] = {};\n }\n\n if (isSender && !this.statsResults.resolutions[type].send) {\n this.statsResults.resolutions[type].send = cloneDeep(emptySender);\n } else if (!isSender && !this.statsResults.resolutions[type].recv) {\n this.statsResults.resolutions[type].recv = cloneDeep(emptyReceiver);\n }\n\n if (!this.statsResults.internal[type]) {\n this.statsResults.internal[type] = {};\n }\n\n if (isSender && !this.statsResults.internal[type].send) {\n this.statsResults.internal[type].send = cloneDeep(emptySender);\n } else if (!isSender && !this.statsResults.internal[type].recv) {\n this.statsResults.internal[type].recv = cloneDeep(emptyReceiver);\n }\n\n switch (getStatsResult.type) {\n case 'outbound-rtp':\n this.processOutboundRTPResult(getStatsResult, type);\n break;\n case 'inbound-rtp':\n this.processInboundRTPResult(getStatsResult, type);\n break;\n case 'track':\n this.processTrackResult(getStatsResult, type);\n break;\n case 'remote-inbound-rtp':\n case 'remote-outbound-rtp':\n // @ts-ignore\n this.compareSentAndReceived(getStatsResult, type, isSender);\n break;\n case 'remotecandidate':\n case 'remote-candidate':\n this.parseCandidate(getStatsResult, type, isSender, true);\n break;\n case 'local-candidate':\n this.parseCandidate(getStatsResult, type, isSender, false);\n break;\n case 'media-source':\n // @ts-ignore\n this.parseAudioSource(getStatsResult, type);\n break;\n default:\n break;\n }\n }\n\n /**\n * Filters the get stats results for types\n * @private\n * @param {Array} statsItem\n * @param {String} type\n * @param {boolean} isSender\n * @returns {void}\n */\n filterAndParseGetStatsResults(statsItem: any, type: string, isSender: boolean) {\n const {types} = DEFAULT_GET_STATS_FILTER;\n\n statsItem.report.forEach((result) => {\n if (types.includes(result.type)) {\n this.parseGetStatsResult(result, type, isSender);\n }\n });\n\n if (this.statsResults[type]) {\n this.statsResults[type].direction = statsItem.currentDirection;\n this.statsResults[type].trackLabel = statsItem.localTrackLabel;\n this.statsResults[type].csi = statsItem.csi;\n }\n }\n\n /**\n * parse the audio\n * @param {String} result\n * @param {boolean} type\n * @returns {void}\n */\n parseAudioSource(result: any, type: any) {\n if (!result) {\n return;\n }\n\n if (type.includes('audio-send')) {\n this.statsResults[type].send.audioLevel = result.audioLevel;\n this.statsResults[type].send.totalAudioEnergy = result.totalAudioEnergy;\n }\n }\n\n /**\n * emits started/stopped events for local/remote media by checking\n * if given values are increasing or not. The previousValue, currentValue\n * params can be any numerical value like number of receive packets or\n * decoded frames, etc.\n *\n * @private\n * @param {string} mediaType\n * @param {number} previousValue - value to compare\n * @param {number} currentValue - value to compare (must be same type of value as previousValue)\n * @param {boolean} isLocal - true if stats are for local media being sent out, false for remote media being received\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n emitStartStopEvents = (\n mediaType: string,\n previousValue: number,\n currentValue: number,\n isLocal: boolean\n ) => {\n if (mediaType !== 'audio' && mediaType !== 'video' && mediaType !== 'share') {\n throw new Error(`Unsupported mediaType: ${mediaType}`);\n }\n\n // eslint-disable-next-line no-param-reassign\n if (previousValue === undefined) previousValue = 0;\n // eslint-disable-next-line no-param-reassign\n if (currentValue === undefined) currentValue = 0;\n\n if (!this.lastEmittedStartStopEvent[mediaType]) {\n this.lastEmittedStartStopEvent[mediaType] = {};\n }\n\n const lastEmittedEvent = isLocal\n ? this.lastEmittedStartStopEvent[mediaType].local\n : this.lastEmittedStartStopEvent[mediaType].remote;\n\n let newEvent;\n\n if (currentValue - previousValue > 0) {\n newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STARTED : EVENTS.REMOTE_MEDIA_STARTED;\n } else if (currentValue === previousValue && currentValue > 0) {\n newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STOPPED : EVENTS.REMOTE_MEDIA_STOPPED;\n }\n\n if (newEvent && lastEmittedEvent !== newEvent) {\n if (isLocal) {\n this.lastEmittedStartStopEvent[mediaType].local = newEvent;\n } else {\n this.lastEmittedStartStopEvent[mediaType].remote = newEvent;\n }\n this.emit(\n {\n file: 'statsAnalyzer/index',\n function: 'compareLastStatsResult',\n },\n newEvent,\n {\n type: mediaType,\n }\n );\n }\n };\n\n /**\n * compares current and previous stats to check if packets are not sent\n *\n * @private\n * @memberof StatsAnalyzer\n * @returns {void}\n */\n private compareLastStatsResult() {\n if (this.lastStatsResults !== null && this.meetingMediaStatus) {\n const getCurrentStatsTotals = (keyPrefix: string, value: string): number =>\n Object.keys(this.statsResults)\n .filter((key) => key.startsWith(keyPrefix))\n .reduce((prev, cur) => prev + (this.statsResults[cur]?.recv[value] || 0), 0);\n\n const getPreviousStatsTotals = (keyPrefix: string, value: string): number =>\n Object.keys(this.statsResults)\n .filter((key) => key.startsWith(keyPrefix))\n .reduce((prev, cur) => prev + (this.lastStatsResults[cur]?.recv[value] || 0), 0);\n\n const getCurrentResolutionsStatsTotals = (keyPrefix: string, value: string): number =>\n Object.keys(this.statsResults)\n .filter((key) => key.startsWith(keyPrefix))\n .reduce((prev, cur) => prev + (this.statsResults.resolutions[cur]?.recv[value] || 0), 0);\n\n const getPreviousResolutionsStatsTotals = (keyPrefix: string, value: string): number =>\n Object.keys(this.statsResults)\n .filter((key) => key.startsWith(keyPrefix))\n .reduce(\n (prev, cur) => prev + (this.lastStatsResults.resolutions[cur]?.recv[value] || 0),\n 0\n );\n\n if (this.meetingMediaStatus.expected.sendAudio && this.lastStatsResults['audio-send']) {\n // compare audio stats sent\n // NOTE: relies on there being only one sender.\n const currentStats = this.statsResults['audio-send'].send;\n const previousStats = this.lastStatsResults['audio-send'].send;\n\n if (\n currentStats.totalPacketsSent === previousStats.totalPacketsSent ||\n currentStats.totalPacketsSent === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent`\n );\n } else {\n if (\n currentStats.totalAudioEnergy === previousStats.totalAudioEnergy ||\n currentStats.totalAudioEnergy === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present`\n );\n }\n\n if (currentStats.audioLevel === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> audio level is 0 for the user`\n );\n }\n }\n\n this.emitStartStopEvents(\n 'audio',\n previousStats.totalPacketsSent,\n currentStats.totalPacketsSent,\n true\n );\n }\n\n if (this.meetingMediaStatus.expected.receiveAudio) {\n // compare audio stats received\n const currentPacketsReceived = getCurrentStatsTotals('audio-recv', 'totalPacketsReceived');\n const previousPacketsReceived = getPreviousStatsTotals(\n 'audio-recv',\n 'totalPacketsReceived'\n );\n const currentSamplesReceived = getCurrentStatsTotals('audio-recv', 'totalSamplesReceived');\n const previousSamplesReceived = getPreviousStatsTotals(\n 'audio-recv',\n 'totalSamplesReceived'\n );\n\n if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received`\n );\n } else if (\n currentSamplesReceived === previousSamplesReceived ||\n currentSamplesReceived === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No audio samples received`\n );\n }\n\n this.emitStartStopEvents('audio', previousPacketsReceived, currentPacketsReceived, false);\n }\n\n if (this.meetingMediaStatus.expected.sendVideo && this.lastStatsResults['video-send']) {\n // compare video stats sent\n const currentStats = this.statsResults['video-send'].send;\n const previousStats = this.lastStatsResults['video-send'].send;\n\n if (\n currentStats.totalPacketsSent === previousStats.totalPacketsSent ||\n currentStats.totalPacketsSent === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent`\n );\n } else {\n if (\n currentStats.framesEncoded === previousStats.framesEncoded ||\n currentStats.framesEncoded === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded`\n );\n }\n\n if (\n this.statsResults.resolutions['video-send'].send.framesSent ===\n this.lastStatsResults.resolutions['video-send'].send.framesSent ||\n this.statsResults.resolutions['video-send'].send.framesSent === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent`\n );\n }\n }\n\n this.emitStartStopEvents('video', previousStats.framesSent, currentStats.framesSent, true);\n }\n\n if (this.meetingMediaStatus.expected.receiveVideo) {\n // compare video stats received\n const currentPacketsReceived = getCurrentStatsTotals('video-recv', 'totalPacketsReceived');\n const previousPacketsReceived = getPreviousStatsTotals(\n 'video-recv',\n 'totalPacketsReceived'\n );\n const currentFramesReceived = getCurrentResolutionsStatsTotals(\n 'video-recv',\n 'framesReceived'\n );\n const previousFramesReceived = getPreviousResolutionsStatsTotals(\n 'video-recv',\n 'framesReceived'\n );\n const currentFramesDecoded = getCurrentStatsTotals('video-recv', 'framesDecoded');\n const previousFramesDecoded = getPreviousStatsTotals('video-recv', 'framesDecoded');\n const currentFramesDropped = getCurrentResolutionsStatsTotals(\n 'video-recv',\n 'framesDropped'\n );\n const previousFramesDropped = getPreviousResolutionsStatsTotals(\n 'video-recv',\n 'framesDropped'\n );\n\n if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets received`\n );\n } else {\n if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video frames received`\n );\n }\n\n if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No video frames decoded`\n );\n }\n\n if (currentFramesDropped - previousFramesDropped > 10) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> video frames are getting dropped`\n );\n }\n }\n\n this.emitStartStopEvents('video', previousFramesDecoded, currentFramesDecoded, false);\n }\n\n if (this.meetingMediaStatus.expected.sendShare && this.lastStatsResults['video-share-send']) {\n // compare share stats sent\n\n const currentStats = this.statsResults['video-share-send'].send;\n const previousStats = this.lastStatsResults['video-share-send'].send;\n\n if (\n currentStats.totalPacketsSent === previousStats.totalPacketsSent ||\n currentStats.totalPacketsSent === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent`\n );\n } else {\n if (\n currentStats.framesEncoded === previousStats.framesEncoded ||\n currentStats.framesEncoded === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded`\n );\n }\n\n if (\n this.statsResults.resolutions['video-share-send'].send.framesSent ===\n this.lastStatsResults.resolutions['video-share-send'].send.framesSent ||\n this.statsResults.resolutions['video-share-send'].send.framesSent === 0\n ) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share frames sent`\n );\n }\n }\n }\n\n if (this.meetingMediaStatus.expected.sendShare) {\n // TODO:need to check receive share value\n // compare share stats received\n const currentPacketsReceived = getCurrentStatsTotals(\n 'video-share-recv',\n 'totalPacketsReceived'\n );\n const previousPacketsReceived = getPreviousStatsTotals(\n 'video-share-recv',\n 'totalPacketsReceived'\n );\n const currentFramesReceived = getCurrentResolutionsStatsTotals(\n 'video-share-recv',\n 'framesReceived'\n );\n const previousFramesReceived = getPreviousResolutionsStatsTotals(\n 'video-share-recv',\n 'framesReceived'\n );\n const currentFramesDecoded = getCurrentStatsTotals('video-share-recv', 'framesDecoded');\n const previousFramesDecoded = getPreviousStatsTotals('video-share-recv', 'framesDecoded');\n const currentFramesDropped = getCurrentResolutionsStatsTotals(\n 'video-share-recv',\n 'framesDropped'\n );\n const previousFramesDropped = getPreviousResolutionsStatsTotals(\n 'video-share-recv',\n 'framesDropped'\n );\n\n if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets received`\n );\n } else {\n if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share frames received`\n );\n }\n\n if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> No share frames decoded`\n );\n }\n\n if (currentFramesDropped - previousFramesDropped > 10) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#compareLastStatsResult --> share frames are getting dropped`\n );\n }\n }\n\n // we are not calling emitStartStopEvents() for sending or receiving share because sharing is often started and stopped\n // in meetings and this.meetingMediaStatus.expected values can be out of sync with the actual packet flow\n // so we would send \"sharing stopped\" events incorrectly\n }\n }\n }\n\n /**\n * Does a `getStats` on all the transceivers and parses the results\n *\n * @private\n * @memberof StatsAnalyzer\n * @returns {Promise}\n */\n private getStatsAndParse() {\n if (!this.mediaConnection) {\n return Promise.resolve();\n }\n\n if (\n this.mediaConnection &&\n this.mediaConnection.getConnectionState() === ConnectionState.Failed\n ) {\n LoggerProxy.logger.trace(\n 'StatsAnalyzer:index#getStatsAndParse --> media connection is in failed state'\n );\n\n return Promise.resolve();\n }\n\n LoggerProxy.logger.trace('StatsAnalyzer:index#getStatsAndParse --> Collecting Stats');\n\n return this.mediaConnection.getTransceiverStats().then((transceiverStats) => {\n transceiverStats.video.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `video-recv-${i}`, false)\n );\n transceiverStats.audio.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `audio-recv-${i}`, false)\n );\n transceiverStats.screenShareVideo.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `video-share-recv-${i}`, false)\n );\n transceiverStats.screenShareAudio.receivers.forEach((receiver, i) =>\n this.filterAndParseGetStatsResults(receiver, `audio-share-recv-${i}`, false)\n );\n\n transceiverStats.video.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'video-send', true);\n });\n transceiverStats.audio.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'audio-send', true);\n });\n transceiverStats.screenShareVideo.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'video-share-send', true);\n });\n transceiverStats.screenShareAudio.senders.forEach((sender, i) => {\n if (i > 0) {\n throw new Error('Stats Analyzer does not support multiple senders.');\n }\n this.filterAndParseGetStatsResults(sender, 'audio-share-send', true);\n });\n\n this.compareLastStatsResult();\n\n // Save the last results to compare with the current\n // DO Deep copy, for some reason it takes the reference all the time rather then old value set\n this.lastStatsResults = JSON.parse(JSON.stringify(this.statsResults));\n\n LoggerProxy.logger.trace(\n 'StatsAnalyzer:index#getStatsAndParse --> Finished Collecting Stats'\n );\n });\n }\n\n /**\n * Processes OutboundRTP stats result and stores\n * @private\n * @param {*} result\n * @param {*} mediaType\n * @returns {void}\n */\n private processOutboundRTPResult(result: any, mediaType: any) {\n const sendrecvType = STATS.SEND_DIRECTION;\n\n if (result.bytesSent) {\n let kilobytes = 0;\n\n if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesSent) {\n this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;\n }\n if (!this.statsResults.internal[mediaType][sendrecvType].framesEncoded) {\n this.statsResults.internal[mediaType][sendrecvType].framesEncoded = result.framesEncoded;\n }\n if (!this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded) {\n this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded =\n result.keyFramesEncoded;\n }\n\n const bytes =\n result.bytesSent - this.statsResults.internal[mediaType][sendrecvType].prevBytesSent;\n\n this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;\n\n kilobytes = bytes / 1024;\n\n this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);\n this.statsResults[mediaType].bytesSent = kilobytes;\n\n this.statsResults[mediaType][sendrecvType].framesEncoded =\n result.framesEncoded - this.statsResults.internal[mediaType][sendrecvType].framesEncoded;\n this.statsResults[mediaType][sendrecvType].keyFramesEncoded =\n result.keyFramesEncoded -\n this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded;\n this.statsResults.internal[mediaType].outboundRtpId = result.id;\n\n if (!this.statsResults.internal[mediaType][sendrecvType].packetsSent) {\n this.statsResults.internal[mediaType][sendrecvType].packetsSent = result.packetsSent;\n }\n\n this.statsResults[mediaType][sendrecvType].packetsSent =\n result.packetsSent - this.statsResults.internal[mediaType][sendrecvType].packetsSent;\n this.statsResults.internal[mediaType][sendrecvType].packetsSent = result.packetsSent;\n\n // Data saved to send MQA metrics\n\n this.statsResults[mediaType][sendrecvType].totalKeyFramesEncoded = result.keyFramesEncoded;\n this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;\n this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;\n this.statsResults[mediaType][sendrecvType].totalPacketsSent = result.packetsSent;\n this.statsResults[mediaType][sendrecvType].totalFirCount = result.firCount;\n this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;\n this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;\n this.statsResults[mediaType][sendrecvType].encoderImplementation =\n result.encoderImplementation;\n this.statsResults[mediaType][sendrecvType].qualityLimitationReason =\n result.qualityLimitationReason;\n this.statsResults[mediaType][sendrecvType].qualityLimitationResolutionChanges =\n result.qualityLimitationResolutionChanges;\n this.statsResults[mediaType][sendrecvType].retransmittedPacketsSent =\n result.retransmittedPacketsSent;\n this.statsResults[mediaType][sendrecvType].totalBytesSent = result.bytesSent;\n this.statsResults[mediaType][sendrecvType].headerBytesSent = result.headerBytesSent;\n this.statsResults[mediaType][sendrecvType].retransmittedBytesSent =\n result.retransmittedBytesSent;\n }\n }\n\n /**\n * Processes InboundRTP stats result and stores\n * @private\n * @param {*} result\n * @param {*} mediaType\n * @returns {void}\n */\n private processInboundRTPResult(result: any, mediaType: any) {\n const sendrecvType = STATS.RECEIVE_DIRECTION;\n\n if (result.bytesReceived) {\n let kilobytes = 0;\n\n if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived) {\n this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived =\n result.bytesReceived;\n }\n\n if (!this.statsResults.internal[mediaType][sendrecvType].pliCount) {\n this.statsResults.internal[mediaType][sendrecvType].pliCount = result.pliCount;\n }\n\n if (!this.statsResults.internal[mediaType][sendrecvType].packetsLost) {\n this.statsResults.internal[mediaType][sendrecvType].packetsLost = result.packetsLost;\n }\n\n if (!this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived) {\n this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived =\n result.packetsReceived;\n }\n\n if (!this.statsResults.internal[mediaType][sendrecvType].lastPacketReceivedTimestamp) {\n this.statsResults.internal[mediaType][sendrecvType].lastPacketReceivedTimestamp =\n result.lastPacketReceivedTimestamp;\n }\n\n const bytes =\n result.bytesReceived -\n this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived;\n\n this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived = result.bytesReceived;\n\n kilobytes = bytes / 1024;\n this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);\n this.statsResults[mediaType].bytesReceived = kilobytes.toFixed(1);\n\n this.statsResults[mediaType][sendrecvType].pliCount =\n result.pliCount - this.statsResults.internal[mediaType][sendrecvType].pliCount;\n this.statsResults[mediaType][sendrecvType].currentPacketsLost =\n result.packetsLost - this.statsResults.internal[mediaType][sendrecvType].packetsLost;\n if (this.statsResults[mediaType][sendrecvType].currentPacketsLost < 0) {\n this.statsResults[mediaType][sendrecvType].currentPacketsLost = 0;\n }\n\n this.statsResults[mediaType][sendrecvType].packetsReceived =\n result.packetsReceived -\n this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived;\n this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived =\n result.packetsReceived;\n\n if (this.statsResults[mediaType][sendrecvType].packetsReceived === 0) {\n LoggerProxy.logger.info(\n `StatsAnalyzer:index#processInboundRTPResult --> No packets received for ${mediaType} `,\n this.statsResults[mediaType][sendrecvType].packetsReceived\n );\n }\n\n // Check the over all packet Lost ratio\n this.statsResults[mediaType][sendrecvType].currentPacketLossRatio =\n this.statsResults[mediaType][sendrecvType].currentPacketsLost > 0\n ? this.statsResults[mediaType][sendrecvType].currentPacketsLost /\n (this.statsResults[mediaType][sendrecvType].packetsReceived +\n this.statsResults[mediaType][sendrecvType].currentPacketsLost)\n : 0;\n if (this.statsResults[mediaType][sendrecvType].currentPacketLossRatio > 3) {\n LoggerProxy.logger.info(\n 'StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver ',\n this.statsResults[mediaType][sendrecvType].currentPacketLossRatio\n );\n }\n\n // TODO: check the packet loss value is negative values here\n\n if (result.packetsLost) {\n this.statsResults[mediaType][sendrecvType].totalPacketsLost =\n result.packetsLost > 0 ? result.packetsLost : -result.packetsLost;\n } else {\n this.statsResults[mediaType][sendrecvType].totalPacketsLost = 0;\n }\n\n this.statsResults[mediaType][sendrecvType].lastPacketReceivedTimestamp =\n result.lastPacketReceivedTimestamp;\n\n // From Thin\n this.statsResults[mediaType][sendrecvType].totalNackCount = result.nackCount;\n this.statsResults[mediaType][sendrecvType].totalPliCount = result.pliCount;\n this.statsResults[mediaType][sendrecvType].framesDecoded = result.framesDecoded;\n this.statsResults[mediaType][sendrecvType].keyFramesDecoded = result.keyFramesDecoded;\n\n this.statsResults[mediaType][sendrecvType].decoderImplementation =\n result.decoderImplementation;\n this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;\n\n this.statsResults[mediaType][sendrecvType].fecPacketsDiscarded = result.fecPacketsDiscarded;\n this.statsResults[mediaType][sendrecvType].fecPacketsReceived = result.fecPacketsReceived;\n this.statsResults[mediaType][sendrecvType].totalBytesReceived = result.bytesReceived;\n this.statsResults[mediaType][sendrecvType].headerBytesReceived = result.headerBytesReceived;\n\n this.statsResults[mediaType][sendrecvType].meanRtpJitter.push(result.jitter);\n\n // Audio stats\n\n this.statsResults[mediaType][sendrecvType].audioLevel = result.audioLevel;\n this.statsResults[mediaType][sendrecvType].totalAudioEnergy = result.totalAudioEnergy;\n this.statsResults[mediaType][sendrecvType].totalSamplesReceived =\n result.totalSamplesReceived || 0;\n this.statsResults[mediaType][sendrecvType].totalSamplesDecoded =\n result.totalSamplesDecoded || 0;\n this.statsResults[mediaType][sendrecvType].concealedSamples = result.concealedSamples || 0;\n }\n }\n\n /**\n * Processes remote and local candidate result and stores\n * @private\n * @param {*} result\n * @param {*} type\n * @param {boolean} isSender\n * @param {boolean} isRemote\n *\n * @returns {void}\n */\n parseCandidate = (result: any, type: any, isSender: boolean, isRemote: boolean) => {\n if (!result || !result.id) {\n return;\n }\n const RemoteCandidateType = {};\n const RemoteTransport = {};\n const RemoteIpAddress = {};\n const RemoteNetworkType = {};\n\n if (!result.id) return;\n\n const sendRecvType = isSender ? STATS.SEND_DIRECTION : STATS.RECEIVE_DIRECTION;\n const ipType = isRemote ? STATS.REMOTE : STATS.LOCAL;\n\n if (!RemoteCandidateType[result.id]) {\n RemoteCandidateType[result.id] = [];\n }\n\n if (!RemoteTransport[result.id]) {\n RemoteTransport[result.id] = [];\n }\n\n if (!RemoteIpAddress[result.id]) {\n RemoteIpAddress[result.id] = [];\n }\n if (!RemoteNetworkType[result.id]) {\n RemoteNetworkType[result.id] = [];\n }\n\n if (\n result.candidateType &&\n RemoteCandidateType[result.id].indexOf(result.candidateType) === -1\n ) {\n RemoteCandidateType[result.id].push(result.candidateType);\n }\n\n if (result.protocol && RemoteTransport[result.id].indexOf(result.protocol) === -1) {\n RemoteTransport[result.id].push(result.protocol.toUpperCase());\n }\n\n if (\n result.ip &&\n RemoteIpAddress[result.id].indexOf(`${result.ip}:${result.portNumber}`) === -1\n ) {\n RemoteIpAddress[result.id].push(`${result.ip}`); // TODO: Add ports\n }\n\n if (result.networkType && RemoteNetworkType[result.id].indexOf(result.networkType) === -1) {\n RemoteNetworkType[result.id].push(result.networkType);\n }\n\n this.statsResults.internal.candidates[result.id] = {\n candidateType: RemoteCandidateType[result.id],\n ipAddress: RemoteIpAddress[result.id],\n portNumber: result.port,\n networkType: RemoteNetworkType[result.id],\n priority: result.priority,\n transport: RemoteTransport[result.id],\n timestamp: result.time,\n id: result.id,\n type: result.type,\n };\n\n this.statsResults.connectionType[ipType].candidateType = RemoteCandidateType[result.id];\n this.statsResults.connectionType[ipType].ipAddress = RemoteIpAddress[result.id];\n\n this.statsResults.connectionType[ipType].networkType =\n RemoteNetworkType[result.id][0] === NETWORK_TYPE.VPN\n ? NETWORK_TYPE.UNKNOWN\n : RemoteNetworkType[result.id][0];\n this.statsResults.connectionType[ipType].transport = RemoteTransport[result.id];\n\n this.statsResults[type][sendRecvType].totalRoundTripTime = result.totalRoundTripTime;\n };\n\n /**\n * Process Track results\n *\n * @private\n * @param {*} result\n * @param {*} mediaType\n * @returns {void}\n * @memberof StatsAnalyzer\n */\n private processTrackResult(result: any, mediaType: any) {\n if (!result || result.type !== 'track') {\n return;\n }\n\n const sendrecvType =\n result.remoteSource === true ? STATS.RECEIVE_DIRECTION : STATS.SEND_DIRECTION;\n\n if (result.frameWidth && result.frameHeight) {\n this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;\n this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;\n this.statsResults.resolutions[mediaType][sendrecvType].framesSent = result.framesSent;\n this.statsResults.resolutions[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;\n }\n\n if (sendrecvType === STATS.RECEIVE_DIRECTION) {\n this.statsResults.resolutions[mediaType][sendrecvType].framesReceived = result.framesReceived;\n this.statsResults.resolutions[mediaType][sendrecvType].framesDecoded = result.framesDecoded;\n this.statsResults.resolutions[mediaType][sendrecvType].framesDropped = result.framesDropped;\n }\n\n if (result.trackIdentifier && !mediaType.includes('audio')) {\n this.statsResults.resolutions[mediaType][sendrecvType].trackIdentifier =\n result.trackIdentifier;\n\n const jitterBufferDelay = result && result.jitterBufferDelay;\n const jitterBufferEmittedCount = result && result.jitterBufferEmittedCount;\n\n this.statsResults.resolutions[mediaType][sendrecvType].avgJitterDelay =\n jitterBufferEmittedCount && +jitterBufferDelay / +jitterBufferEmittedCount;\n\n // Used to calculate the jitter\n this.statsResults.resolutions[mediaType][sendrecvType].jitterBufferDelay =\n result.jitterBufferDelay;\n this.statsResults.resolutions[mediaType][sendrecvType].jitterBufferEmittedCount =\n result.jitterBufferEmittedCount;\n }\n }\n\n /**\n *\n * @private\n * @param {*} result\n * @param {*} type\n * @returns {void}\n * @memberof StatsAnalyzer\n */\n compareSentAndReceived(result, type) {\n // Don't compare on transceivers without a sender.\n if (!type || !this.statsResults.internal[type].send) {\n return;\n }\n\n const mediaType = type;\n\n if (!this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver) {\n this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;\n }\n\n const currentPacketLoss =\n result.packetsLost - this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver;\n\n this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;\n this.statsResults[mediaType].send.packetsLostOnReceiver = currentPacketLoss;\n this.statsResults[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;\n\n this.statsResults[mediaType].send.meanRemoteJitter.push(result.jitter);\n this.statsResults[mediaType].send.meanRoundTripTime.push(result.roundTripTime);\n\n this.statsResults[mediaType].send.timestamp = result.timestamp;\n this.statsResults[mediaType].send.ssrc = result.ssrc;\n this.statsResults[mediaType].send.reportsReceived = result.reportsReceived;\n\n // Total packloss ratio on this video section of the call\n this.statsResults[mediaType].send.overAllPacketLossRatio =\n this.statsResults[mediaType].send.totalPacketsLostOnReceiver > 0\n ? this.statsResults[mediaType].send.totalPacketsLostOnReceiver /\n this.statsResults[mediaType].send.totalPacketsSent\n : 0;\n this.statsResults[mediaType].send.currentPacketLossRatio =\n this.statsResults[mediaType].send.packetsLostOnReceiver > 0\n ? (this.statsResults[mediaType].send.packetsLostOnReceiver * 100) /\n (this.statsResults[mediaType].send.packetsSent +\n this.statsResults[mediaType].send.packetsLostOnReceiver)\n : 0;\n\n if (\n this.statsResults[mediaType].send.maxPacketLossRatio <\n this.statsResults[mediaType].send.currentPacketLossRatio\n ) {\n this.statsResults[mediaType].send.maxPacketLossRatio =\n this.statsResults[mediaType].send.currentPacketLossRatio;\n }\n\n if (result.type === 'remote-inbound-rtp') {\n this.networkQualityMonitor.determineUplinkNetworkQuality({\n mediaType,\n remoteRtpResults: result,\n statsAnalyzerCurrentStats: this.statsResults,\n });\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -35,11 +35,9 @@ export declare class MediaRequestManager {
|
|
|
35
35
|
private sendMediaRequestsCallback;
|
|
36
36
|
private counter;
|
|
37
37
|
private clientRequests;
|
|
38
|
-
private slotsActiveInLastMediaRequest;
|
|
39
38
|
private degradationPreferences;
|
|
40
39
|
private sourceUpdateListener;
|
|
41
40
|
constructor(degradationPreferences: DegradationPreferences, sendMediaRequestsCallback: SendMediaRequestsCallback);
|
|
42
|
-
private resetInactiveReceiveSlots;
|
|
43
41
|
setDegradationPreferences(degradationPreferences: DegradationPreferences): void;
|
|
44
42
|
private getDegradedClientRequests;
|
|
45
43
|
private sendRequests;
|
|
@@ -55,12 +55,4 @@ export declare class ReceiveSlot extends EventsScope {
|
|
|
55
55
|
* The underlying WCME receive slot
|
|
56
56
|
*/
|
|
57
57
|
get wcmeReceiveSlot(): WcmeReceiveSlot;
|
|
58
|
-
/**
|
|
59
|
-
* Resets the source state to the default 'no source' value.
|
|
60
|
-
* This function should be called on receive slots that are
|
|
61
|
-
* no longer part of a media request. It's needed because WCME
|
|
62
|
-
* does not send any more events on such slots, so the sourceState
|
|
63
|
-
* value would not represent the truth anymore.
|
|
64
|
-
*/
|
|
65
|
-
resetSourceState(): void;
|
|
66
58
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/plugin-meetings",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.38",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
|
|
6
6
|
"contributors": [
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
"build": "yarn run -T tsc --declaration true --declarationDir ./dist/types"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@webex/plugin-meetings": "3.0.0-beta.
|
|
36
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
37
|
-
"@webex/test-helper-mocha": "3.0.0-beta.
|
|
38
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
39
|
-
"@webex/test-helper-retry": "3.0.0-beta.
|
|
40
|
-
"@webex/test-helper-test-users": "3.0.0-beta.
|
|
35
|
+
"@webex/plugin-meetings": "3.0.0-beta.38",
|
|
36
|
+
"@webex/test-helper-chai": "3.0.0-beta.38",
|
|
37
|
+
"@webex/test-helper-mocha": "3.0.0-beta.38",
|
|
38
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.38",
|
|
39
|
+
"@webex/test-helper-retry": "3.0.0-beta.38",
|
|
40
|
+
"@webex/test-helper-test-users": "3.0.0-beta.38",
|
|
41
41
|
"chai": "^4.3.4",
|
|
42
42
|
"chai-as-promised": "^7.1.1",
|
|
43
43
|
"jsdom-global": "3.0.2",
|
|
@@ -46,18 +46,18 @@
|
|
|
46
46
|
"typescript": "^4.7.4"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@webex/common": "3.0.0-beta.
|
|
50
|
-
"@webex/internal-media-core": "1.35.
|
|
51
|
-
"@webex/internal-plugin-conversation": "3.0.0-beta.
|
|
52
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
53
|
-
"@webex/internal-plugin-llm": "3.0.0-beta.
|
|
54
|
-
"@webex/internal-plugin-mercury": "3.0.0-beta.
|
|
55
|
-
"@webex/internal-plugin-metrics": "3.0.0-beta.
|
|
56
|
-
"@webex/internal-plugin-support": "3.0.0-beta.
|
|
57
|
-
"@webex/internal-plugin-user": "3.0.0-beta.
|
|
58
|
-
"@webex/plugin-people": "3.0.0-beta.
|
|
59
|
-
"@webex/plugin-rooms": "3.0.0-beta.
|
|
60
|
-
"@webex/webex-core": "3.0.0-beta.
|
|
49
|
+
"@webex/common": "3.0.0-beta.38",
|
|
50
|
+
"@webex/internal-media-core": "1.35.2",
|
|
51
|
+
"@webex/internal-plugin-conversation": "3.0.0-beta.38",
|
|
52
|
+
"@webex/internal-plugin-device": "3.0.0-beta.38",
|
|
53
|
+
"@webex/internal-plugin-llm": "3.0.0-beta.38",
|
|
54
|
+
"@webex/internal-plugin-mercury": "3.0.0-beta.38",
|
|
55
|
+
"@webex/internal-plugin-metrics": "3.0.0-beta.38",
|
|
56
|
+
"@webex/internal-plugin-support": "3.0.0-beta.38",
|
|
57
|
+
"@webex/internal-plugin-user": "3.0.0-beta.38",
|
|
58
|
+
"@webex/plugin-people": "3.0.0-beta.38",
|
|
59
|
+
"@webex/plugin-rooms": "3.0.0-beta.38",
|
|
60
|
+
"@webex/webex-core": "3.0.0-beta.38",
|
|
61
61
|
"ampersand-collection": "^2.0.2",
|
|
62
62
|
"bowser": "^2.11.0",
|
|
63
63
|
"btoa": "^1.2.1",
|
|
@@ -69,8 +69,6 @@ export class MediaRequestManager {
|
|
|
69
69
|
|
|
70
70
|
private clientRequests: {[key: MediaRequestId]: MediaRequest};
|
|
71
71
|
|
|
72
|
-
private slotsActiveInLastMediaRequest: {[key: ReceiveSlotId]: ReceiveSlot};
|
|
73
|
-
|
|
74
72
|
private degradationPreferences: DegradationPreferences;
|
|
75
73
|
|
|
76
74
|
private sourceUpdateListener: () => void;
|
|
@@ -82,36 +80,10 @@ export class MediaRequestManager {
|
|
|
82
80
|
this.sendMediaRequestsCallback = sendMediaRequestsCallback;
|
|
83
81
|
this.counter = 0;
|
|
84
82
|
this.clientRequests = {};
|
|
85
|
-
this.slotsActiveInLastMediaRequest = {};
|
|
86
83
|
this.degradationPreferences = degradationPreferences;
|
|
87
84
|
this.sourceUpdateListener = this.commit.bind(this);
|
|
88
85
|
}
|
|
89
86
|
|
|
90
|
-
private resetInactiveReceiveSlots() {
|
|
91
|
-
const activeSlots: {[key: ReceiveSlotId]: ReceiveSlot} = {};
|
|
92
|
-
|
|
93
|
-
// create a map of all currently used slot ids
|
|
94
|
-
Object.values(this.clientRequests).forEach((request) =>
|
|
95
|
-
request.receiveSlots.forEach((slot) => {
|
|
96
|
-
activeSlots[slot.id] = slot;
|
|
97
|
-
})
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
// when we stop using some receive slots and they are not included in the new media request,
|
|
101
|
-
// we will never get a 'no source' notification for them, so we reset their state,
|
|
102
|
-
// so that the client doesn't try to display their video anymore
|
|
103
|
-
for (const [slotId, slot] of Object.entries(this.slotsActiveInLastMediaRequest)) {
|
|
104
|
-
if (!(slotId in activeSlots)) {
|
|
105
|
-
LoggerProxy.logger.info(
|
|
106
|
-
`multistream:mediaRequestManager --> resetting sourceState to "no source" for slot ${slot.id}`
|
|
107
|
-
);
|
|
108
|
-
slot.resetSourceState();
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
this.slotsActiveInLastMediaRequest = activeSlots;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
87
|
public setDegradationPreferences(degradationPreferences: DegradationPreferences) {
|
|
116
88
|
this.degradationPreferences = degradationPreferences;
|
|
117
89
|
this.sendRequests(); // re-send requests after preferences are set
|
|
@@ -201,8 +173,6 @@ export class MediaRequestManager {
|
|
|
201
173
|
});
|
|
202
174
|
|
|
203
175
|
this.sendMediaRequestsCallback(wcmeMediaRequests);
|
|
204
|
-
|
|
205
|
-
this.resetInactiveReceiveSlots();
|
|
206
176
|
}
|
|
207
177
|
|
|
208
178
|
public addRequest(mediaRequest: MediaRequest, commit = true): MediaRequestId {
|
|
@@ -240,6 +210,5 @@ export class MediaRequestManager {
|
|
|
240
210
|
|
|
241
211
|
public reset() {
|
|
242
212
|
this.clientRequests = {};
|
|
243
|
-
this.slotsActiveInLastMediaRequest = {};
|
|
244
213
|
}
|
|
245
214
|
}
|
|
@@ -154,17 +154,4 @@ export class ReceiveSlot extends EventsScope {
|
|
|
154
154
|
get wcmeReceiveSlot(): WcmeReceiveSlot {
|
|
155
155
|
return this.mcReceiveSlot;
|
|
156
156
|
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Resets the source state to the default 'no source' value.
|
|
160
|
-
* This function should be called on receive slots that are
|
|
161
|
-
* no longer part of a media request. It's needed because WCME
|
|
162
|
-
* does not send any more events on such slots, so the sourceState
|
|
163
|
-
* value would not represent the truth anymore.
|
|
164
|
-
*/
|
|
165
|
-
public resetSourceState() {
|
|
166
|
-
this.#sourceState = 'no source';
|
|
167
|
-
this.#csi = undefined;
|
|
168
|
-
this.#memberId = undefined;
|
|
169
|
-
}
|
|
170
157
|
}
|
|
@@ -492,23 +492,23 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
492
492
|
const getCurrentStatsTotals = (keyPrefix: string, value: string): number =>
|
|
493
493
|
Object.keys(this.statsResults)
|
|
494
494
|
.filter((key) => key.startsWith(keyPrefix))
|
|
495
|
-
.reduce((prev, cur) => prev + (this.statsResults[cur]
|
|
495
|
+
.reduce((prev, cur) => prev + (this.statsResults[cur]?.recv[value] || 0), 0);
|
|
496
496
|
|
|
497
497
|
const getPreviousStatsTotals = (keyPrefix: string, value: string): number =>
|
|
498
498
|
Object.keys(this.statsResults)
|
|
499
499
|
.filter((key) => key.startsWith(keyPrefix))
|
|
500
|
-
.reduce((prev, cur) => prev + (this.lastStatsResults[cur]
|
|
500
|
+
.reduce((prev, cur) => prev + (this.lastStatsResults[cur]?.recv[value] || 0), 0);
|
|
501
501
|
|
|
502
502
|
const getCurrentResolutionsStatsTotals = (keyPrefix: string, value: string): number =>
|
|
503
503
|
Object.keys(this.statsResults)
|
|
504
504
|
.filter((key) => key.startsWith(keyPrefix))
|
|
505
|
-
.reduce((prev, cur) => prev + (this.statsResults.resolutions[cur]
|
|
505
|
+
.reduce((prev, cur) => prev + (this.statsResults.resolutions[cur]?.recv[value] || 0), 0);
|
|
506
506
|
|
|
507
507
|
const getPreviousResolutionsStatsTotals = (keyPrefix: string, value: string): number =>
|
|
508
508
|
Object.keys(this.statsResults)
|
|
509
509
|
.filter((key) => key.startsWith(keyPrefix))
|
|
510
510
|
.reduce(
|
|
511
|
-
(prev, cur) => prev + (this.lastStatsResults.resolutions[cur]
|
|
511
|
+
(prev, cur) => prev + (this.lastStatsResults.resolutions[cur]?.recv[value] || 0),
|
|
512
512
|
0
|
|
513
513
|
);
|
|
514
514
|
|
|
@@ -62,7 +62,6 @@ describe('MediaRequestManager', () => {
|
|
|
62
62
|
off: sinon.stub(),
|
|
63
63
|
sourceState: 'live',
|
|
64
64
|
wcmeReceiveSlot: fakeWcmeSlots[index],
|
|
65
|
-
resetSourceState: sinon.stub(),
|
|
66
65
|
} as unknown as ReceiveSlot)
|
|
67
66
|
);
|
|
68
67
|
});
|
|
@@ -609,78 +608,6 @@ describe('MediaRequestManager', () => {
|
|
|
609
608
|
checkMediaRequestsSent([]);
|
|
610
609
|
});
|
|
611
610
|
|
|
612
|
-
it('calls resetSourceState() on slots that are stopped being used', () => {
|
|
613
|
-
const requestIds = [
|
|
614
|
-
addActiveSpeakerRequest(
|
|
615
|
-
255,
|
|
616
|
-
[fakeReceiveSlots[0], fakeReceiveSlots[1]],
|
|
617
|
-
ACTIVE_SPEAKER_MAX_FS
|
|
618
|
-
),
|
|
619
|
-
addActiveSpeakerRequest(
|
|
620
|
-
255,
|
|
621
|
-
[fakeReceiveSlots[2], fakeReceiveSlots[3]],
|
|
622
|
-
ACTIVE_SPEAKER_MAX_FS
|
|
623
|
-
),
|
|
624
|
-
addReceiverSelectedRequest(100, fakeReceiveSlots[4], RECEIVER_SELECTED_MAX_FS),
|
|
625
|
-
addReceiverSelectedRequest(200, fakeReceiveSlots[5], RECEIVER_SELECTED_MAX_FS),
|
|
626
|
-
];
|
|
627
|
-
|
|
628
|
-
mediaRequestManager.commit();
|
|
629
|
-
checkMediaRequestsSent([
|
|
630
|
-
{
|
|
631
|
-
policy: 'active-speaker',
|
|
632
|
-
priority: 255,
|
|
633
|
-
receiveSlots: [fakeWcmeSlots[0], fakeWcmeSlots[1]],
|
|
634
|
-
maxFs: ACTIVE_SPEAKER_MAX_FS,
|
|
635
|
-
},
|
|
636
|
-
{
|
|
637
|
-
policy: 'active-speaker',
|
|
638
|
-
priority: 255,
|
|
639
|
-
receiveSlots: [fakeWcmeSlots[2], fakeWcmeSlots[3]],
|
|
640
|
-
maxFs: ACTIVE_SPEAKER_MAX_FS,
|
|
641
|
-
},
|
|
642
|
-
{
|
|
643
|
-
policy: 'receiver-selected',
|
|
644
|
-
csi: 100,
|
|
645
|
-
receiveSlot: fakeWcmeSlots[4],
|
|
646
|
-
maxFs: RECEIVER_SELECTED_MAX_FS,
|
|
647
|
-
},
|
|
648
|
-
{
|
|
649
|
-
policy: 'receiver-selected',
|
|
650
|
-
csi: 200,
|
|
651
|
-
receiveSlot: fakeWcmeSlots[5],
|
|
652
|
-
maxFs: RECEIVER_SELECTED_MAX_FS,
|
|
653
|
-
},
|
|
654
|
-
]);
|
|
655
|
-
|
|
656
|
-
// cancel 2 of the requests
|
|
657
|
-
mediaRequestManager.cancelRequest(requestIds[1], false);
|
|
658
|
-
mediaRequestManager.cancelRequest(requestIds[3], false);
|
|
659
|
-
|
|
660
|
-
mediaRequestManager.commit();
|
|
661
|
-
|
|
662
|
-
// expect only the 2 remaining requests to be sent out
|
|
663
|
-
checkMediaRequestsSent([
|
|
664
|
-
{
|
|
665
|
-
policy: 'active-speaker',
|
|
666
|
-
priority: 255,
|
|
667
|
-
receiveSlots: [fakeWcmeSlots[0], fakeWcmeSlots[1]],
|
|
668
|
-
maxFs: ACTIVE_SPEAKER_MAX_FS,
|
|
669
|
-
},
|
|
670
|
-
{
|
|
671
|
-
policy: 'receiver-selected',
|
|
672
|
-
csi: 100,
|
|
673
|
-
receiveSlot: fakeWcmeSlots[4],
|
|
674
|
-
maxFs: RECEIVER_SELECTED_MAX_FS,
|
|
675
|
-
},
|
|
676
|
-
]);
|
|
677
|
-
|
|
678
|
-
// and that the receive slots of the 2 cancelled ones had resetSourceState() called
|
|
679
|
-
assert.calledOnce(fakeReceiveSlots[2].resetSourceState);
|
|
680
|
-
assert.calledOnce(fakeReceiveSlots[3].resetSourceState);
|
|
681
|
-
assert.calledOnce(fakeReceiveSlots[5].resetSourceState);
|
|
682
|
-
});
|
|
683
|
-
|
|
684
611
|
it('re-sends media requests after degradation preferences are set', () => {
|
|
685
612
|
// set max macroblocks limit
|
|
686
613
|
mediaRequestManager.setDegradationPreferences({maxMacroblocksLimit: 32400});
|
|
@@ -83,25 +83,6 @@ describe('ReceiveSlot', () => {
|
|
|
83
83
|
assert.strictEqual(receiveSlot.sourceState, 'live');
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
-
it('resets source related properties when resetSourceState() is called', () => {
|
|
87
|
-
const csi = 123456;
|
|
88
|
-
const fakeMemberId = '00000001-5555-6666-9012-345678901234';
|
|
89
|
-
|
|
90
|
-
findMemberIdCallbackStub.returns(fakeMemberId);
|
|
91
|
-
|
|
92
|
-
fakeWcmeSlot.emit(WcmeReceiveSlotEvents.SourceUpdate, 'live', csi);
|
|
93
|
-
|
|
94
|
-
assert.strictEqual(receiveSlot.memberId, fakeMemberId);
|
|
95
|
-
assert.strictEqual(receiveSlot.csi, csi);
|
|
96
|
-
assert.strictEqual(receiveSlot.sourceState, 'live');
|
|
97
|
-
|
|
98
|
-
receiveSlot.resetSourceState();
|
|
99
|
-
|
|
100
|
-
assert.strictEqual(receiveSlot.memberId, undefined);
|
|
101
|
-
assert.strictEqual(receiveSlot.csi, undefined);
|
|
102
|
-
assert.strictEqual(receiveSlot.sourceState, 'no source');
|
|
103
|
-
});
|
|
104
|
-
|
|
105
86
|
describe('findMemberId()', () => {
|
|
106
87
|
it('doesn\'t do anything if csi is not set', () => {
|
|
107
88
|
// by default the receiveSlot does not have any csi or member id
|