@webex/plugin-meetings 3.0.0-beta.34 → 3.0.0-beta.340
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/README.md +46 -8
- package/dist/annotation/annotation.types.js +7 -0
- package/dist/annotation/annotation.types.js.map +1 -0
- package/dist/annotation/constants.js +49 -0
- package/dist/annotation/constants.js.map +1 -0
- package/dist/annotation/index.js +342 -0
- package/dist/annotation/index.js.map +1 -0
- package/dist/breakouts/breakout.js +94 -15
- package/dist/breakouts/breakout.js.map +1 -1
- package/dist/breakouts/edit-lock-error.js +52 -0
- package/dist/breakouts/edit-lock-error.js.map +1 -0
- package/dist/breakouts/events.js +45 -0
- package/dist/breakouts/events.js.map +1 -0
- package/dist/breakouts/index.js +709 -35
- package/dist/breakouts/index.js.map +1 -1
- package/dist/breakouts/utils.js +45 -1
- package/dist/breakouts/utils.js.map +1 -1
- package/dist/common/errors/no-meeting-info.js +51 -0
- package/dist/common/errors/no-meeting-info.js.map +1 -0
- package/dist/common/errors/reclaim-host-role-errors.js +158 -0
- package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
- package/dist/common/errors/webex-errors.js +48 -7
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/common/logs/logger-proxy.js +1 -1
- package/dist/common/logs/logger-proxy.js.map +1 -1
- package/dist/common/logs/request.js +5 -1
- package/dist/common/logs/request.js.map +1 -1
- package/dist/common/queue.js +24 -9
- package/dist/common/queue.js.map +1 -1
- package/dist/config.js +5 -10
- package/dist/config.js.map +1 -1
- package/dist/constants.js +233 -29
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +14 -2
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.js +109 -15
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/types.js +7 -0
- package/dist/controls-options-manager/types.js.map +1 -0
- package/dist/controls-options-manager/util.js +309 -18
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/index.js +112 -1
- package/dist/index.js.map +1 -1
- package/dist/interpretation/collection.js +23 -0
- package/dist/interpretation/collection.js.map +1 -0
- package/dist/interpretation/index.js +366 -0
- package/dist/interpretation/index.js.map +1 -0
- package/dist/interpretation/siLanguage.js +25 -0
- package/dist/interpretation/siLanguage.js.map +1 -0
- package/dist/locus-info/controlsUtils.js +91 -2
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +383 -62
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js +7 -1
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js +57 -1
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.js +249 -72
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js +89 -14
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/media/index.js +62 -116
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +73 -124
- package/dist/media/properties.js.map +1 -1
- package/dist/mediaQualityMetrics/config.js +1 -204
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +86 -2
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +3927 -2960
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +292 -0
- package/dist/meeting/locusMediaRequest.js.map +1 -0
- package/dist/meeting/muteState.js +224 -131
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +260 -196
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +601 -417
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/index.js +73 -7
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +192 -51
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/util.js +1 -1
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +36 -36
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +39 -0
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +424 -116
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.js +7 -0
- package/dist/meetings/meetings.types.js.map +1 -0
- package/dist/meetings/request.js +2 -0
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +72 -6
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +58 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js +25 -0
- package/dist/member/types.js.map +1 -0
- package/dist/member/util.js +132 -25
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js +10 -0
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +102 -6
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +106 -38
- package/dist/members/request.js.map +1 -1
- package/dist/members/types.js +15 -0
- package/dist/members/types.js.map +1 -0
- package/dist/members/util.js +326 -232
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +16 -5
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +1 -446
- package/dist/metrics/index.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +228 -58
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +29 -16
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +39 -36
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +44 -18
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +60 -3
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +209 -59
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +233 -0
- package/dist/multistream/sendSlotManager.js.map +1 -0
- package/dist/reachability/clusterReachability.js +356 -0
- package/dist/reachability/clusterReachability.js.map +1 -0
- package/dist/reachability/index.js +273 -391
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/request.js +17 -8
- package/dist/reachability/request.js.map +1 -1
- package/dist/reachability/util.js +29 -0
- package/dist/reachability/util.js.map +1 -0
- package/dist/reconnection-manager/index.js +214 -170
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/index.js +21 -2
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.js +9 -8
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js +62 -35
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +112 -97
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +95 -38
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/rtcMetrics/constants.js +12 -0
- package/dist/rtcMetrics/constants.js.map +1 -0
- package/dist/rtcMetrics/index.js +142 -0
- package/dist/rtcMetrics/index.js.map +1 -0
- package/dist/statsAnalyzer/index.js +181 -214
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.js +22 -18
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/types/annotation/annotation.types.d.ts +42 -0
- package/dist/types/annotation/constants.d.ts +31 -0
- package/dist/types/annotation/index.d.ts +117 -0
- package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
- package/dist/types/breakouts/events.d.ts +8 -0
- package/dist/types/breakouts/utils.d.ts +14 -0
- package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
- package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
- package/dist/types/common/errors/webex-errors.d.ts +25 -1
- package/dist/types/common/logs/request.d.ts +2 -0
- package/dist/types/common/queue.d.ts +9 -7
- package/dist/types/config.d.ts +2 -7
- package/dist/types/constants.d.ts +201 -30
- package/dist/types/controls-options-manager/enums.d.ts +11 -1
- package/dist/types/controls-options-manager/index.d.ts +17 -1
- package/dist/types/controls-options-manager/types.d.ts +43 -0
- package/dist/types/controls-options-manager/util.d.ts +1 -7
- package/dist/types/index.d.ts +6 -4
- package/dist/types/interpretation/collection.d.ts +5 -0
- package/dist/types/interpretation/index.d.ts +5 -0
- package/dist/types/interpretation/siLanguage.d.ts +5 -0
- package/dist/types/locus-info/index.d.ts +57 -4
- package/dist/types/locus-info/parser.d.ts +66 -6
- package/dist/types/media/index.d.ts +2 -0
- package/dist/types/media/properties.d.ts +34 -48
- package/dist/types/mediaQualityMetrics/config.d.ts +0 -128
- package/dist/types/meeting/in-meeting-actions.d.ts +86 -2
- package/dist/types/meeting/index.d.ts +506 -512
- package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
- package/dist/types/meeting/muteState.d.ts +93 -25
- package/dist/types/meeting/request.d.ts +72 -43
- package/dist/types/meeting/util.d.ts +101 -1
- package/dist/types/meeting-info/index.d.ts +13 -1
- package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
- package/dist/types/meetings/collection.d.ts +17 -0
- package/dist/types/meetings/index.d.ts +91 -21
- package/dist/types/meetings/meetings.types.d.ts +4 -0
- package/dist/types/member/index.d.ts +14 -0
- package/dist/types/member/types.d.ts +32 -0
- package/dist/types/members/collection.d.ts +5 -0
- package/dist/types/members/index.d.ts +35 -2
- package/dist/types/members/request.d.ts +73 -9
- package/dist/types/members/types.d.ts +25 -0
- package/dist/types/members/util.d.ts +214 -1
- package/dist/types/metrics/constants.d.ts +15 -4
- package/dist/types/metrics/index.d.ts +4 -111
- package/dist/types/multistream/mediaRequestManager.d.ts +72 -5
- package/dist/types/multistream/receiveSlot.d.ts +13 -11
- package/dist/types/multistream/receiveSlotManager.d.ts +14 -4
- package/dist/types/multistream/remoteMedia.d.ts +8 -29
- package/dist/types/multistream/remoteMediaGroup.d.ts +0 -9
- package/dist/types/multistream/remoteMediaManager.d.ts +46 -2
- package/dist/types/multistream/sendSlotManager.d.ts +61 -0
- package/dist/types/reachability/clusterReachability.d.ts +109 -0
- package/dist/types/reachability/index.d.ts +60 -95
- package/dist/types/reachability/request.d.ts +7 -3
- package/dist/types/reachability/util.d.ts +8 -0
- package/dist/types/reconnection-manager/index.d.ts +19 -0
- package/dist/types/recording-controller/index.d.ts +15 -1
- package/dist/types/recording-controller/util.d.ts +5 -4
- package/dist/types/roap/index.d.ts +2 -1
- package/dist/types/roap/request.d.ts +15 -11
- package/dist/types/roap/turnDiscovery.d.ts +21 -3
- package/dist/types/rtcMetrics/constants.d.ts +4 -0
- package/dist/types/rtcMetrics/index.d.ts +54 -0
- package/dist/types/statsAnalyzer/index.d.ts +29 -11
- package/dist/types/webinar/collection.d.ts +16 -0
- package/dist/types/webinar/index.d.ts +5 -0
- package/dist/webinar/collection.js +44 -0
- package/dist/webinar/collection.js.map +1 -0
- package/dist/webinar/index.js +69 -0
- package/dist/webinar/index.js.map +1 -0
- package/package.json +22 -19
- package/src/annotation/annotation.types.ts +50 -0
- package/src/annotation/constants.ts +36 -0
- package/src/annotation/index.ts +328 -0
- package/src/breakouts/README.md +42 -12
- package/src/breakouts/breakout.ts +67 -9
- package/src/breakouts/edit-lock-error.ts +25 -0
- package/src/breakouts/events.ts +56 -0
- package/src/breakouts/index.ts +592 -20
- package/src/breakouts/utils.ts +42 -0
- package/src/common/errors/no-meeting-info.ts +24 -0
- package/src/common/errors/reclaim-host-role-errors.ts +134 -0
- package/src/common/errors/webex-errors.ts +44 -2
- package/src/common/logs/logger-proxy.ts +1 -1
- package/src/common/logs/request.ts +5 -1
- package/src/common/queue.ts +22 -8
- package/src/config.ts +4 -9
- package/src/constants.ts +224 -20
- package/src/controls-options-manager/enums.ts +12 -0
- package/src/controls-options-manager/index.ts +116 -21
- package/src/controls-options-manager/types.ts +59 -0
- package/src/controls-options-manager/util.ts +294 -14
- package/src/index.ts +40 -0
- package/src/interpretation/README.md +60 -0
- package/src/interpretation/collection.ts +19 -0
- package/src/interpretation/index.ts +332 -0
- package/src/interpretation/siLanguage.ts +18 -0
- package/src/locus-info/controlsUtils.ts +108 -0
- package/src/locus-info/index.ts +413 -59
- package/src/locus-info/infoUtils.ts +10 -2
- package/src/locus-info/mediaSharesUtils.ts +64 -0
- package/src/locus-info/parser.ts +258 -47
- package/src/locus-info/selfUtils.ts +81 -5
- package/src/media/index.ts +102 -122
- package/src/media/properties.ts +87 -110
- package/src/mediaQualityMetrics/config.ts +0 -135
- package/src/meeting/in-meeting-actions.ts +171 -3
- package/src/meeting/index.ts +3276 -2555
- package/src/meeting/locusMediaRequest.ts +313 -0
- package/src/meeting/muteState.ts +223 -136
- package/src/meeting/request.ts +177 -121
- package/src/meeting/util.ts +588 -394
- package/src/meeting-info/index.ts +81 -8
- package/src/meeting-info/meeting-info-v2.ts +170 -14
- package/src/meeting-info/util.ts +1 -1
- package/src/meeting-info/utilv2.ts +23 -23
- package/src/meetings/collection.ts +33 -0
- package/src/meetings/index.ts +454 -125
- package/src/meetings/meetings.types.ts +12 -0
- package/src/meetings/request.ts +2 -0
- package/src/meetings/util.ts +80 -11
- package/src/member/index.ts +58 -0
- package/src/member/types.ts +38 -0
- package/src/member/util.ts +141 -25
- package/src/members/collection.ts +8 -0
- package/src/members/index.ts +134 -8
- package/src/members/request.ts +97 -17
- package/src/members/types.ts +29 -0
- package/src/members/util.ts +333 -240
- package/src/metrics/constants.ts +15 -4
- package/src/metrics/index.ts +1 -469
- package/src/multistream/mediaRequestManager.ts +277 -82
- package/src/multistream/receiveSlot.ts +31 -17
- package/src/multistream/receiveSlotManager.ts +34 -24
- package/src/multistream/remoteMedia.ts +27 -2
- package/src/multistream/remoteMediaGroup.ts +59 -0
- package/src/multistream/remoteMediaManager.ts +148 -30
- package/src/multistream/sendSlotManager.ts +170 -0
- package/src/reachability/clusterReachability.ts +320 -0
- package/src/reachability/index.ts +236 -342
- package/src/reachability/request.ts +17 -8
- package/src/reachability/util.ts +24 -0
- package/src/reconnection-manager/index.ts +128 -106
- package/src/recording-controller/index.ts +20 -3
- package/src/recording-controller/util.ts +26 -9
- package/src/roap/index.ts +63 -32
- package/src/roap/request.ts +100 -104
- package/src/roap/turnDiscovery.ts +48 -26
- package/src/rtcMetrics/constants.ts +3 -0
- package/src/rtcMetrics/index.ts +124 -0
- package/src/statsAnalyzer/index.ts +218 -289
- package/src/statsAnalyzer/mqaUtil.ts +28 -30
- package/src/webinar/collection.ts +31 -0
- package/src/webinar/index.ts +62 -0
- package/test/integration/spec/converged-space-meetings.js +60 -3
- package/test/integration/spec/journey.js +320 -261
- package/test/integration/spec/space-meeting.js +76 -3
- package/test/unit/spec/annotation/index.ts +418 -0
- package/test/unit/spec/breakouts/breakout.ts +118 -28
- package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
- package/test/unit/spec/breakouts/events.ts +89 -0
- package/test/unit/spec/breakouts/index.ts +1395 -69
- package/test/unit/spec/breakouts/utils.js +52 -1
- package/test/unit/spec/common/queue.js +31 -2
- package/test/unit/spec/controls-options-manager/index.js +163 -0
- package/test/unit/spec/controls-options-manager/util.js +576 -60
- package/test/unit/spec/fixture/locus.js +1 -0
- package/test/unit/spec/interpretation/collection.ts +15 -0
- package/test/unit/spec/interpretation/index.ts +589 -0
- package/test/unit/spec/interpretation/siLanguage.ts +28 -0
- package/test/unit/spec/locus-info/controlsUtils.js +316 -43
- package/test/unit/spec/locus-info/index.js +1304 -33
- package/test/unit/spec/locus-info/infoUtils.js +37 -15
- package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
- package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
- package/test/unit/spec/locus-info/parser.js +116 -35
- package/test/unit/spec/locus-info/selfConstant.js +27 -4
- package/test/unit/spec/locus-info/selfUtils.js +208 -17
- package/test/unit/spec/media/index.ts +120 -37
- package/test/unit/spec/media/properties.ts +2 -2
- package/test/unit/spec/meeting/in-meeting-actions.ts +85 -3
- package/test/unit/spec/meeting/index.js +5849 -2014
- package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
- package/test/unit/spec/meeting/muteState.js +402 -213
- package/test/unit/spec/meeting/request.js +483 -49
- package/test/unit/spec/meeting/utils.js +679 -64
- package/test/unit/spec/meeting-info/index.js +300 -0
- package/test/unit/spec/meeting-info/meetinginfov2.js +526 -5
- package/test/unit/spec/meeting-info/utilv2.js +21 -0
- package/test/unit/spec/meetings/collection.js +26 -0
- package/test/unit/spec/meetings/index.js +1231 -212
- package/test/unit/spec/meetings/utils.js +202 -2
- package/test/unit/spec/member/index.js +61 -6
- package/test/unit/spec/member/util.js +510 -34
- package/test/unit/spec/members/index.js +432 -1
- package/test/unit/spec/members/request.js +206 -27
- package/test/unit/spec/members/utils.js +210 -0
- package/test/unit/spec/metrics/index.js +1 -50
- package/test/unit/spec/multistream/mediaRequestManager.ts +776 -162
- package/test/unit/spec/multistream/receiveSlot.ts +28 -20
- package/test/unit/spec/multistream/receiveSlotManager.ts +32 -30
- package/test/unit/spec/multistream/remoteMedia.ts +30 -0
- package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
- package/test/unit/spec/multistream/remoteMediaManager.ts +326 -0
- package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
- package/test/unit/spec/reachability/clusterReachability.ts +279 -0
- package/test/unit/spec/reachability/index.ts +486 -13
- package/test/unit/spec/reachability/request.js +68 -0
- package/test/unit/spec/reachability/util.ts +40 -0
- package/test/unit/spec/reconnection-manager/index.js +117 -11
- package/test/unit/spec/recording-controller/index.js +294 -218
- package/test/unit/spec/recording-controller/util.js +223 -96
- package/test/unit/spec/roap/index.ts +174 -63
- package/test/unit/spec/roap/request.ts +226 -85
- package/test/unit/spec/roap/turnDiscovery.ts +76 -34
- package/test/unit/spec/rtcMetrics/index.ts +93 -0
- package/test/unit/spec/stats-analyzer/index.js +231 -7
- package/test/unit/spec/webinar/collection.ts +13 -0
- package/test/unit/spec/webinar/index.ts +60 -0
- package/test/utils/integrationTestUtils.js +46 -0
- package/test/utils/testUtils.js +0 -52
- package/dist/meeting/effectsState.js +0 -262
- package/dist/meeting/effectsState.js.map +0 -1
- package/dist/metrics/config.js +0 -289
- package/dist/metrics/config.js.map +0 -1
- package/dist/types/meeting/effectsState.d.ts +0 -42
- package/dist/types/metrics/config.d.ts +0 -169
- package/src/index.js +0 -16
- package/src/meeting/effectsState.ts +0 -211
- package/src/metrics/config.ts +0 -485
- package/test/unit/spec/meeting/effectsState.js +0 -285
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable prefer-destructuring */
|
|
2
2
|
|
|
3
|
-
import {cloneDeep} from 'lodash';
|
|
3
|
+
import {cloneDeep, isEmpty} from 'lodash';
|
|
4
4
|
import {ConnectionState} from '@webex/internal-media-core';
|
|
5
5
|
|
|
6
6
|
import EventsScope from '../common/events/events-scope';
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
getVideoSenderMqa,
|
|
29
29
|
getVideoReceiverMqa,
|
|
30
30
|
} from './mqaUtil';
|
|
31
|
+
import {ReceiveSlot} from '../multistream/receiveSlot';
|
|
31
32
|
|
|
32
33
|
export const EVENTS = {
|
|
33
34
|
MEDIA_QUALITY: 'MEDIA_QUALITY',
|
|
@@ -53,6 +54,8 @@ const emptyReceiver = {
|
|
|
53
54
|
meanRoundTripTime: [],
|
|
54
55
|
};
|
|
55
56
|
|
|
57
|
+
type ReceiveSlotCallback = (csi: number) => ReceiveSlot | undefined;
|
|
58
|
+
|
|
56
59
|
/**
|
|
57
60
|
* Stats Analyzer class that will emit events based on detected quality
|
|
58
61
|
*
|
|
@@ -74,17 +77,22 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
74
77
|
statsInterval: NodeJS.Timeout;
|
|
75
78
|
statsResults: any;
|
|
76
79
|
statsStarted: any;
|
|
80
|
+
successfulCandidatePair: any;
|
|
81
|
+
localIpAddress: string; // Returns the local IP address for diagnostics. this is the local IP of the interface used for the current media connection a host can have many local Ip Addresses
|
|
82
|
+
receiveSlotCallback: ReceiveSlotCallback;
|
|
77
83
|
|
|
78
84
|
/**
|
|
79
85
|
* Creates a new instance of StatsAnalyzer
|
|
80
86
|
* @constructor
|
|
81
87
|
* @public
|
|
82
88
|
* @param {Object} config SDK Configuration Object
|
|
89
|
+
* @param {Function} receiveSlotCallback Callback used to access receive slots.
|
|
83
90
|
* @param {Object} networkQualityMonitor class for assessing network characteristics (jitter, packetLoss, latency)
|
|
84
91
|
* @param {Object} statsResults Default properties for stats
|
|
85
92
|
*/
|
|
86
93
|
constructor(
|
|
87
94
|
config: any,
|
|
95
|
+
receiveSlotCallback: ReceiveSlotCallback = () => undefined,
|
|
88
96
|
networkQualityMonitor: object = {},
|
|
89
97
|
statsResults: object = defaultStats
|
|
90
98
|
) {
|
|
@@ -98,6 +106,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
98
106
|
this.mqaSentCount = -1;
|
|
99
107
|
this.lastMqaDataSent = {};
|
|
100
108
|
this.lastEmittedStartStopEvent = {};
|
|
109
|
+
this.receiveSlotCallback = receiveSlotCallback;
|
|
110
|
+
this.successfulCandidatePair = {};
|
|
111
|
+
this.localIpAddress = '';
|
|
101
112
|
}
|
|
102
113
|
|
|
103
114
|
/**
|
|
@@ -143,6 +154,18 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
143
154
|
const newMqa = cloneDeep(emptyMqaInterval);
|
|
144
155
|
|
|
145
156
|
Object.keys(this.statsResults).forEach((mediaType) => {
|
|
157
|
+
if (!this.lastMqaDataSent[mediaType]) {
|
|
158
|
+
this.lastMqaDataSent[mediaType] = {};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!this.lastMqaDataSent[mediaType].send && mediaType.includes('-send')) {
|
|
162
|
+
this.lastMqaDataSent[mediaType].send = {};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (!this.lastMqaDataSent[mediaType].recv && mediaType.includes('-recv')) {
|
|
166
|
+
this.lastMqaDataSent[mediaType].recv = {};
|
|
167
|
+
}
|
|
168
|
+
|
|
146
169
|
if (mediaType.includes('audio-send') || mediaType.includes('audio-share-send')) {
|
|
147
170
|
const audioSender = cloneDeep(emptyAudioTransmit);
|
|
148
171
|
|
|
@@ -153,6 +176,8 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
153
176
|
mediaType,
|
|
154
177
|
});
|
|
155
178
|
newMqa.audioTransmit.push(audioSender);
|
|
179
|
+
|
|
180
|
+
this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
|
|
156
181
|
} else if (mediaType.includes('audio-recv') || mediaType.includes('audio-share-recv')) {
|
|
157
182
|
const audioReceiver = cloneDeep(emptyAudioReceive);
|
|
158
183
|
|
|
@@ -163,6 +188,8 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
163
188
|
mediaType,
|
|
164
189
|
});
|
|
165
190
|
newMqa.audioReceive.push(audioReceiver);
|
|
191
|
+
|
|
192
|
+
this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
|
|
166
193
|
} else if (mediaType.includes('video-send') || mediaType.includes('video-share-send')) {
|
|
167
194
|
const videoSender = cloneDeep(emptyVideoTransmit);
|
|
168
195
|
|
|
@@ -173,6 +200,8 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
173
200
|
mediaType,
|
|
174
201
|
});
|
|
175
202
|
newMqa.videoTransmit.push(videoSender);
|
|
203
|
+
|
|
204
|
+
this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
|
|
176
205
|
} else if (mediaType.includes('video-recv') || mediaType.includes('video-share-recv')) {
|
|
177
206
|
const videoReceiver = cloneDeep(emptyVideoReceive);
|
|
178
207
|
|
|
@@ -183,24 +212,24 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
183
212
|
mediaType,
|
|
184
213
|
});
|
|
185
214
|
newMqa.videoReceive.push(videoReceiver);
|
|
215
|
+
|
|
216
|
+
this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
|
|
186
217
|
}
|
|
187
218
|
});
|
|
188
219
|
|
|
189
|
-
newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress
|
|
220
|
+
newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress;
|
|
190
221
|
|
|
191
222
|
// Adding peripheral information
|
|
192
|
-
newMqa.intervalMetadata.peripherals = [];
|
|
193
|
-
|
|
194
223
|
newMqa.intervalMetadata.peripherals.push({information: _UNKNOWN_, name: MEDIA_DEVICES.SPEAKER});
|
|
195
224
|
if (this.statsResults['audio-send']) {
|
|
196
225
|
newMqa.intervalMetadata.peripherals.push({
|
|
197
|
-
information: this.statsResults['audio-send']
|
|
226
|
+
information: this.statsResults['audio-send'].trackLabel || _UNKNOWN_,
|
|
198
227
|
name: MEDIA_DEVICES.MICROPHONE,
|
|
199
228
|
});
|
|
200
229
|
}
|
|
201
230
|
if (this.statsResults['video-send']) {
|
|
202
231
|
newMqa.intervalMetadata.peripherals.push({
|
|
203
|
-
information: this.statsResults['video-send']
|
|
232
|
+
information: this.statsResults['video-send'].trackLabel || _UNKNOWN_,
|
|
204
233
|
name: MEDIA_DEVICES.CAMERA,
|
|
205
234
|
});
|
|
206
235
|
}
|
|
@@ -239,6 +268,16 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
239
268
|
this.mediaConnection = mediaConnection;
|
|
240
269
|
}
|
|
241
270
|
|
|
271
|
+
/**
|
|
272
|
+
* Returns the local IP address for diagnostics.
|
|
273
|
+
* this is the local IP of the interface used for the current media connection
|
|
274
|
+
* a host can have many local Ip Addresses
|
|
275
|
+
* @returns {string | undefined} The local IP address.
|
|
276
|
+
*/
|
|
277
|
+
getLocalIpAddress(): string {
|
|
278
|
+
return this.localIpAddress;
|
|
279
|
+
}
|
|
280
|
+
|
|
242
281
|
/**
|
|
243
282
|
* Starts the stats analyzer on interval
|
|
244
283
|
*
|
|
@@ -293,7 +332,6 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
293
332
|
this.mediaConnection = null;
|
|
294
333
|
});
|
|
295
334
|
}
|
|
296
|
-
this.mediaConnection = null;
|
|
297
335
|
|
|
298
336
|
return Promise.resolve();
|
|
299
337
|
}
|
|
@@ -324,26 +362,6 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
324
362
|
this.statsResults[type].recv = cloneDeep(emptyReceiver);
|
|
325
363
|
}
|
|
326
364
|
|
|
327
|
-
if (!this.statsResults.resolutions[type]) {
|
|
328
|
-
this.statsResults.resolutions[type] = {};
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
if (isSender && !this.statsResults.resolutions[type].send) {
|
|
332
|
-
this.statsResults.resolutions[type].send = cloneDeep(emptySender);
|
|
333
|
-
} else if (!isSender && !this.statsResults.resolutions[type].recv) {
|
|
334
|
-
this.statsResults.resolutions[type].recv = cloneDeep(emptyReceiver);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (!this.statsResults.internal[type]) {
|
|
338
|
-
this.statsResults.internal[type] = {};
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
if (isSender && !this.statsResults.internal[type].send) {
|
|
342
|
-
this.statsResults.internal[type].send = cloneDeep(emptySender);
|
|
343
|
-
} else if (!isSender && !this.statsResults.internal[type].recv) {
|
|
344
|
-
this.statsResults.internal[type].recv = cloneDeep(emptyReceiver);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
365
|
switch (getStatsResult.type) {
|
|
348
366
|
case 'outbound-rtp':
|
|
349
367
|
this.processOutboundRTPResult(getStatsResult, type);
|
|
@@ -351,13 +369,9 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
351
369
|
case 'inbound-rtp':
|
|
352
370
|
this.processInboundRTPResult(getStatsResult, type);
|
|
353
371
|
break;
|
|
354
|
-
case 'track':
|
|
355
|
-
this.processTrackResult(getStatsResult, type);
|
|
356
|
-
break;
|
|
357
372
|
case 'remote-inbound-rtp':
|
|
358
373
|
case 'remote-outbound-rtp':
|
|
359
|
-
|
|
360
|
-
this.compareSentAndReceived(getStatsResult, type, isSender);
|
|
374
|
+
this.compareSentAndReceived(getStatsResult, type);
|
|
361
375
|
break;
|
|
362
376
|
case 'remotecandidate':
|
|
363
377
|
case 'remote-candidate':
|
|
@@ -386,6 +400,13 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
386
400
|
filterAndParseGetStatsResults(statsItem: any, type: string, isSender: boolean) {
|
|
387
401
|
const {types} = DEFAULT_GET_STATS_FILTER;
|
|
388
402
|
|
|
403
|
+
// get the successful candidate pair before parsing stats.
|
|
404
|
+
statsItem.report.forEach((report) => {
|
|
405
|
+
if (report.type === 'candidate-pair' && report.state === 'succeeded') {
|
|
406
|
+
this.successfulCandidatePair = report;
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
|
|
389
410
|
statsItem.report.forEach((result) => {
|
|
390
411
|
if (types.includes(result.type)) {
|
|
391
412
|
this.parseGetStatsResult(result, type, isSender);
|
|
@@ -396,6 +417,12 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
396
417
|
this.statsResults[type].direction = statsItem.currentDirection;
|
|
397
418
|
this.statsResults[type].trackLabel = statsItem.localTrackLabel;
|
|
398
419
|
this.statsResults[type].csi = statsItem.csi;
|
|
420
|
+
this.extractAndSetLocalIpAddressInfoForDiagnostics(
|
|
421
|
+
this.successfulCandidatePair?.localCandidateId,
|
|
422
|
+
this.statsResults?.candidates
|
|
423
|
+
);
|
|
424
|
+
// reset the successful candidate pair.
|
|
425
|
+
this.successfulCandidatePair = {};
|
|
399
426
|
}
|
|
400
427
|
}
|
|
401
428
|
|
|
@@ -492,25 +519,12 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
492
519
|
const getCurrentStatsTotals = (keyPrefix: string, value: string): number =>
|
|
493
520
|
Object.keys(this.statsResults)
|
|
494
521
|
.filter((key) => key.startsWith(keyPrefix))
|
|
495
|
-
.reduce((prev, cur) => prev + (this.statsResults[cur]
|
|
522
|
+
.reduce((prev, cur) => prev + (this.statsResults[cur]?.recv[value] || 0), 0);
|
|
496
523
|
|
|
497
524
|
const getPreviousStatsTotals = (keyPrefix: string, value: string): number =>
|
|
498
525
|
Object.keys(this.statsResults)
|
|
499
526
|
.filter((key) => key.startsWith(keyPrefix))
|
|
500
|
-
.reduce((prev, cur) => prev + (this.lastStatsResults[cur]
|
|
501
|
-
|
|
502
|
-
const getCurrentResolutionsStatsTotals = (keyPrefix: string, value: string): number =>
|
|
503
|
-
Object.keys(this.statsResults)
|
|
504
|
-
.filter((key) => key.startsWith(keyPrefix))
|
|
505
|
-
.reduce((prev, cur) => prev + (this.statsResults.resolutions[cur].recv[value] || 0), 0);
|
|
506
|
-
|
|
507
|
-
const getPreviousResolutionsStatsTotals = (keyPrefix: string, value: string): number =>
|
|
508
|
-
Object.keys(this.statsResults)
|
|
509
|
-
.filter((key) => key.startsWith(keyPrefix))
|
|
510
|
-
.reduce(
|
|
511
|
-
(prev, cur) => prev + (this.lastStatsResults.resolutions[cur].recv[value] || 0),
|
|
512
|
-
0
|
|
513
|
-
);
|
|
527
|
+
.reduce((prev, cur) => prev + (this.lastStatsResults[cur]?.recv[value] || 0), 0);
|
|
514
528
|
|
|
515
529
|
if (this.meetingMediaStatus.expected.sendAudio && this.lastStatsResults['audio-send']) {
|
|
516
530
|
// compare audio stats sent
|
|
@@ -523,7 +537,8 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
523
537
|
currentStats.totalPacketsSent === 0
|
|
524
538
|
) {
|
|
525
539
|
LoggerProxy.logger.info(
|
|
526
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent
|
|
540
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent`,
|
|
541
|
+
currentStats.totalPacketsSent
|
|
527
542
|
);
|
|
528
543
|
} else {
|
|
529
544
|
if (
|
|
@@ -531,7 +546,8 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
531
546
|
currentStats.totalAudioEnergy === 0
|
|
532
547
|
) {
|
|
533
548
|
LoggerProxy.logger.info(
|
|
534
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present
|
|
549
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present`,
|
|
550
|
+
currentStats.totalAudioEnergy
|
|
535
551
|
);
|
|
536
552
|
}
|
|
537
553
|
|
|
@@ -565,14 +581,16 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
565
581
|
|
|
566
582
|
if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
|
|
567
583
|
LoggerProxy.logger.info(
|
|
568
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received
|
|
584
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received`,
|
|
585
|
+
currentPacketsReceived
|
|
569
586
|
);
|
|
570
587
|
} else if (
|
|
571
588
|
currentSamplesReceived === previousSamplesReceived ||
|
|
572
589
|
currentSamplesReceived === 0
|
|
573
590
|
) {
|
|
574
591
|
LoggerProxy.logger.info(
|
|
575
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No audio samples received
|
|
592
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No audio samples received`,
|
|
593
|
+
currentSamplesReceived
|
|
576
594
|
);
|
|
577
595
|
}
|
|
578
596
|
|
|
@@ -589,7 +607,8 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
589
607
|
currentStats.totalPacketsSent === 0
|
|
590
608
|
) {
|
|
591
609
|
LoggerProxy.logger.info(
|
|
592
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent
|
|
610
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent`,
|
|
611
|
+
currentStats.totalPacketsSent
|
|
593
612
|
);
|
|
594
613
|
} else {
|
|
595
614
|
if (
|
|
@@ -597,17 +616,19 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
597
616
|
currentStats.framesEncoded === 0
|
|
598
617
|
) {
|
|
599
618
|
LoggerProxy.logger.info(
|
|
600
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded
|
|
619
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded`,
|
|
620
|
+
currentStats.framesEncoded
|
|
601
621
|
);
|
|
602
622
|
}
|
|
603
623
|
|
|
604
624
|
if (
|
|
605
|
-
this.statsResults
|
|
606
|
-
this.lastStatsResults
|
|
607
|
-
this.statsResults
|
|
625
|
+
this.statsResults['video-send'].send.framesSent ===
|
|
626
|
+
this.lastStatsResults['video-send'].send.framesSent ||
|
|
627
|
+
this.statsResults['video-send'].send.framesSent === 0
|
|
608
628
|
) {
|
|
609
629
|
LoggerProxy.logger.info(
|
|
610
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent
|
|
630
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent`,
|
|
631
|
+
this.statsResults['video-send'].send.framesSent
|
|
611
632
|
);
|
|
612
633
|
}
|
|
613
634
|
}
|
|
@@ -622,45 +643,37 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
622
643
|
'video-recv',
|
|
623
644
|
'totalPacketsReceived'
|
|
624
645
|
);
|
|
625
|
-
const currentFramesReceived =
|
|
626
|
-
|
|
627
|
-
'framesReceived'
|
|
628
|
-
);
|
|
629
|
-
const previousFramesReceived = getPreviousResolutionsStatsTotals(
|
|
630
|
-
'video-recv',
|
|
631
|
-
'framesReceived'
|
|
632
|
-
);
|
|
646
|
+
const currentFramesReceived = getCurrentStatsTotals('video-recv', 'framesReceived');
|
|
647
|
+
const previousFramesReceived = getPreviousStatsTotals('video-recv', 'framesReceived');
|
|
633
648
|
const currentFramesDecoded = getCurrentStatsTotals('video-recv', 'framesDecoded');
|
|
634
649
|
const previousFramesDecoded = getPreviousStatsTotals('video-recv', 'framesDecoded');
|
|
635
|
-
const currentFramesDropped =
|
|
636
|
-
|
|
637
|
-
'framesDropped'
|
|
638
|
-
);
|
|
639
|
-
const previousFramesDropped = getPreviousResolutionsStatsTotals(
|
|
640
|
-
'video-recv',
|
|
641
|
-
'framesDropped'
|
|
642
|
-
);
|
|
650
|
+
const currentFramesDropped = getCurrentStatsTotals('video-recv', 'framesDropped');
|
|
651
|
+
const previousFramesDropped = getPreviousStatsTotals('video-recv', 'framesDropped');
|
|
643
652
|
|
|
644
653
|
if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
|
|
645
654
|
LoggerProxy.logger.info(
|
|
646
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets received
|
|
655
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets received`,
|
|
656
|
+
currentPacketsReceived
|
|
647
657
|
);
|
|
648
658
|
} else {
|
|
649
659
|
if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {
|
|
650
660
|
LoggerProxy.logger.info(
|
|
651
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No video frames received
|
|
661
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No video frames received`,
|
|
662
|
+
currentFramesReceived
|
|
652
663
|
);
|
|
653
664
|
}
|
|
654
665
|
|
|
655
666
|
if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {
|
|
656
667
|
LoggerProxy.logger.info(
|
|
657
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No video frames decoded
|
|
668
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No video frames decoded`,
|
|
669
|
+
currentFramesDecoded
|
|
658
670
|
);
|
|
659
671
|
}
|
|
660
672
|
|
|
661
673
|
if (currentFramesDropped - previousFramesDropped > 10) {
|
|
662
674
|
LoggerProxy.logger.info(
|
|
663
|
-
`StatsAnalyzer:index#compareLastStatsResult --> video frames are getting dropped
|
|
675
|
+
`StatsAnalyzer:index#compareLastStatsResult --> video frames are getting dropped`,
|
|
676
|
+
currentFramesDropped - previousFramesDropped
|
|
664
677
|
);
|
|
665
678
|
}
|
|
666
679
|
}
|
|
@@ -679,7 +692,8 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
679
692
|
currentStats.totalPacketsSent === 0
|
|
680
693
|
) {
|
|
681
694
|
LoggerProxy.logger.info(
|
|
682
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent
|
|
695
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent`,
|
|
696
|
+
currentStats.totalPacketsSent
|
|
683
697
|
);
|
|
684
698
|
} else {
|
|
685
699
|
if (
|
|
@@ -687,17 +701,19 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
687
701
|
currentStats.framesEncoded === 0
|
|
688
702
|
) {
|
|
689
703
|
LoggerProxy.logger.info(
|
|
690
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded
|
|
704
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded`,
|
|
705
|
+
currentStats.framesEncoded
|
|
691
706
|
);
|
|
692
707
|
}
|
|
693
708
|
|
|
694
709
|
if (
|
|
695
|
-
this.statsResults
|
|
696
|
-
this.lastStatsResults
|
|
697
|
-
this.statsResults
|
|
710
|
+
this.statsResults['video-share-send'].send.framesSent ===
|
|
711
|
+
this.lastStatsResults['video-share-send'].send.framesSent ||
|
|
712
|
+
this.statsResults['video-share-send'].send.framesSent === 0
|
|
698
713
|
) {
|
|
699
714
|
LoggerProxy.logger.info(
|
|
700
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No share frames sent
|
|
715
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No share frames sent`,
|
|
716
|
+
this.statsResults['video-share-send'].send.framesSent
|
|
701
717
|
);
|
|
702
718
|
}
|
|
703
719
|
}
|
|
@@ -714,45 +730,37 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
714
730
|
'video-share-recv',
|
|
715
731
|
'totalPacketsReceived'
|
|
716
732
|
);
|
|
717
|
-
const currentFramesReceived =
|
|
718
|
-
|
|
719
|
-
'framesReceived'
|
|
720
|
-
);
|
|
721
|
-
const previousFramesReceived = getPreviousResolutionsStatsTotals(
|
|
722
|
-
'video-share-recv',
|
|
723
|
-
'framesReceived'
|
|
724
|
-
);
|
|
733
|
+
const currentFramesReceived = getCurrentStatsTotals('video-share-recv', 'framesReceived');
|
|
734
|
+
const previousFramesReceived = getPreviousStatsTotals('video-share-recv', 'framesReceived');
|
|
725
735
|
const currentFramesDecoded = getCurrentStatsTotals('video-share-recv', 'framesDecoded');
|
|
726
736
|
const previousFramesDecoded = getPreviousStatsTotals('video-share-recv', 'framesDecoded');
|
|
727
|
-
const currentFramesDropped =
|
|
728
|
-
|
|
729
|
-
'framesDropped'
|
|
730
|
-
);
|
|
731
|
-
const previousFramesDropped = getPreviousResolutionsStatsTotals(
|
|
732
|
-
'video-share-recv',
|
|
733
|
-
'framesDropped'
|
|
734
|
-
);
|
|
737
|
+
const currentFramesDropped = getCurrentStatsTotals('video-share-recv', 'framesDropped');
|
|
738
|
+
const previousFramesDropped = getPreviousStatsTotals('video-share-recv', 'framesDropped');
|
|
735
739
|
|
|
736
740
|
if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
|
|
737
741
|
LoggerProxy.logger.info(
|
|
738
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets received
|
|
742
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets received`,
|
|
743
|
+
currentPacketsReceived
|
|
739
744
|
);
|
|
740
745
|
} else {
|
|
741
746
|
if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {
|
|
742
747
|
LoggerProxy.logger.info(
|
|
743
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No share frames received
|
|
748
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No share frames received`,
|
|
749
|
+
currentFramesReceived
|
|
744
750
|
);
|
|
745
751
|
}
|
|
746
752
|
|
|
747
753
|
if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {
|
|
748
754
|
LoggerProxy.logger.info(
|
|
749
|
-
`StatsAnalyzer:index#compareLastStatsResult --> No share frames decoded
|
|
755
|
+
`StatsAnalyzer:index#compareLastStatsResult --> No share frames decoded`,
|
|
756
|
+
currentFramesDecoded
|
|
750
757
|
);
|
|
751
758
|
}
|
|
752
759
|
|
|
753
760
|
if (currentFramesDropped - previousFramesDropped > 10) {
|
|
754
761
|
LoggerProxy.logger.info(
|
|
755
|
-
`StatsAnalyzer:index#compareLastStatsResult --> share frames are getting dropped
|
|
762
|
+
`StatsAnalyzer:index#compareLastStatsResult --> share frames are getting dropped`,
|
|
763
|
+
currentFramesDropped - previousFramesDropped
|
|
756
764
|
);
|
|
757
765
|
}
|
|
758
766
|
}
|
|
@@ -851,43 +859,20 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
851
859
|
const sendrecvType = STATS.SEND_DIRECTION;
|
|
852
860
|
|
|
853
861
|
if (result.bytesSent) {
|
|
854
|
-
|
|
862
|
+
const kilobytes = 0;
|
|
855
863
|
|
|
856
|
-
if (
|
|
857
|
-
this.statsResults
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
this.statsResults
|
|
861
|
-
}
|
|
862
|
-
if (!this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded) {
|
|
863
|
-
this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded =
|
|
864
|
-
result.keyFramesEncoded;
|
|
864
|
+
if (result.frameWidth && result.frameHeight) {
|
|
865
|
+
this.statsResults[mediaType][sendrecvType].width = result.frameWidth;
|
|
866
|
+
this.statsResults[mediaType][sendrecvType].height = result.frameHeight;
|
|
867
|
+
this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;
|
|
868
|
+
this.statsResults[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;
|
|
865
869
|
}
|
|
866
870
|
|
|
867
|
-
const bytes =
|
|
868
|
-
result.bytesSent - this.statsResults.internal[mediaType][sendrecvType].prevBytesSent;
|
|
869
|
-
|
|
870
|
-
this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;
|
|
871
|
-
|
|
872
|
-
kilobytes = bytes / 1024;
|
|
873
|
-
|
|
874
871
|
this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
|
|
875
|
-
this.statsResults[mediaType].bytesSent = kilobytes;
|
|
876
|
-
|
|
877
|
-
this.statsResults[mediaType][sendrecvType].framesEncoded =
|
|
878
|
-
result.framesEncoded - this.statsResults.internal[mediaType][sendrecvType].framesEncoded;
|
|
879
|
-
this.statsResults[mediaType][sendrecvType].keyFramesEncoded =
|
|
880
|
-
result.keyFramesEncoded -
|
|
881
|
-
this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded;
|
|
882
|
-
this.statsResults.internal[mediaType].outboundRtpId = result.id;
|
|
883
|
-
|
|
884
|
-
if (!this.statsResults.internal[mediaType][sendrecvType].packetsSent) {
|
|
885
|
-
this.statsResults.internal[mediaType][sendrecvType].packetsSent = result.packetsSent;
|
|
886
|
-
}
|
|
887
872
|
|
|
888
|
-
this.statsResults[mediaType][sendrecvType].
|
|
889
|
-
|
|
890
|
-
this.statsResults
|
|
873
|
+
this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;
|
|
874
|
+
this.statsResults[mediaType][sendrecvType].keyFramesEncoded = result.keyFramesEncoded;
|
|
875
|
+
this.statsResults[mediaType][sendrecvType].packetsSent = result.packetsSent;
|
|
891
876
|
|
|
892
877
|
// Data saved to send MQA metrics
|
|
893
878
|
|
|
@@ -925,71 +910,50 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
925
910
|
|
|
926
911
|
if (result.bytesReceived) {
|
|
927
912
|
let kilobytes = 0;
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
this.statsResults
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
if (!this.statsResults.internal[mediaType][sendrecvType].packetsLost) {
|
|
939
|
-
this.statsResults.internal[mediaType][sendrecvType].packetsLost = result.packetsLost;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
if (!this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived) {
|
|
943
|
-
this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived =
|
|
944
|
-
result.packetsReceived;
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
if (!this.statsResults.internal[mediaType][sendrecvType].lastPacketReceivedTimestamp) {
|
|
948
|
-
this.statsResults.internal[mediaType][sendrecvType].lastPacketReceivedTimestamp =
|
|
949
|
-
result.lastPacketReceivedTimestamp;
|
|
913
|
+
const receiveSlot = this.receiveSlotCallback(result.ssrc);
|
|
914
|
+
const idAndCsi = receiveSlot
|
|
915
|
+
? `id: "${receiveSlot.id || ''}"${receiveSlot.csi ? ` and csi: ${receiveSlot.csi}` : ''}`
|
|
916
|
+
: '';
|
|
917
|
+
|
|
918
|
+
if (result.frameWidth && result.frameHeight) {
|
|
919
|
+
this.statsResults[mediaType][sendrecvType].width = result.frameWidth;
|
|
920
|
+
this.statsResults[mediaType][sendrecvType].height = result.frameHeight;
|
|
921
|
+
this.statsResults[mediaType][sendrecvType].framesReceived = result.framesReceived;
|
|
950
922
|
}
|
|
951
923
|
|
|
952
924
|
const bytes =
|
|
953
|
-
result.bytesReceived -
|
|
954
|
-
this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived;
|
|
955
|
-
|
|
956
|
-
this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived = result.bytesReceived;
|
|
925
|
+
result.bytesReceived - this.statsResults[mediaType][sendrecvType].totalBytesReceived;
|
|
957
926
|
|
|
958
927
|
kilobytes = bytes / 1024;
|
|
959
928
|
this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
result.packetsLost - this.statsResults.internal[mediaType][sendrecvType].packetsLost;
|
|
966
|
-
if (this.statsResults[mediaType][sendrecvType].currentPacketsLost < 0) {
|
|
967
|
-
this.statsResults[mediaType][sendrecvType].currentPacketsLost = 0;
|
|
929
|
+
|
|
930
|
+
let currentPacketsLost =
|
|
931
|
+
result.packetsLost - this.statsResults[mediaType][sendrecvType].totalPacketsLost;
|
|
932
|
+
if (currentPacketsLost < 0) {
|
|
933
|
+
currentPacketsLost = 0;
|
|
968
934
|
}
|
|
969
935
|
|
|
970
|
-
|
|
971
|
-
result.packetsReceived -
|
|
972
|
-
|
|
973
|
-
this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived =
|
|
974
|
-
result.packetsReceived;
|
|
936
|
+
const currentPacketsReceived =
|
|
937
|
+
result.packetsReceived - this.statsResults[mediaType][sendrecvType].totalPacketsReceived;
|
|
938
|
+
this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;
|
|
975
939
|
|
|
976
|
-
if (
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
940
|
+
if (currentPacketsReceived === 0) {
|
|
941
|
+
if (receiveSlot) {
|
|
942
|
+
LoggerProxy.logger.info(
|
|
943
|
+
`StatsAnalyzer:index#processInboundRTPResult --> No packets received for receive slot ${idAndCsi}`,
|
|
944
|
+
currentPacketsReceived
|
|
945
|
+
);
|
|
946
|
+
}
|
|
981
947
|
}
|
|
982
948
|
|
|
983
949
|
// Check the over all packet Lost ratio
|
|
984
950
|
this.statsResults[mediaType][sendrecvType].currentPacketLossRatio =
|
|
985
|
-
|
|
986
|
-
?
|
|
987
|
-
(this.statsResults[mediaType][sendrecvType].packetsReceived +
|
|
988
|
-
this.statsResults[mediaType][sendrecvType].currentPacketsLost)
|
|
951
|
+
currentPacketsLost > 0
|
|
952
|
+
? currentPacketsLost / (currentPacketsReceived + currentPacketsLost)
|
|
989
953
|
: 0;
|
|
990
954
|
if (this.statsResults[mediaType][sendrecvType].currentPacketLossRatio > 3) {
|
|
991
955
|
LoggerProxy.logger.info(
|
|
992
|
-
|
|
956
|
+
`StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver with slot ${idAndCsi}`,
|
|
993
957
|
this.statsResults[mediaType][sendrecvType].currentPacketLossRatio
|
|
994
958
|
);
|
|
995
959
|
}
|
|
@@ -1035,6 +999,48 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1035
999
|
}
|
|
1036
1000
|
}
|
|
1037
1001
|
|
|
1002
|
+
/**
|
|
1003
|
+
* extracts the local Ip address from the statsResult object by looking at stats results candidates
|
|
1004
|
+
* and matches that ID with the successful candidate pair. It looks at the type of local candidate it is
|
|
1005
|
+
* and then extracts the IP address from the relatedAddress or address property based on conditions known in webrtc
|
|
1006
|
+
* note, there are known incompatibilities and it is possible for this to set undefined, or for the IP address to be the public IP address
|
|
1007
|
+
* for example, firefox does not set the relayProtocol, and if the user is behind a NAT it might be the public IP
|
|
1008
|
+
* @private
|
|
1009
|
+
* @param {string} successfulCandidatePairId - The ID of the successful candidate pair.
|
|
1010
|
+
* @param {Object} candidates - the stats result candidates
|
|
1011
|
+
* @returns {void}
|
|
1012
|
+
*/
|
|
1013
|
+
extractAndSetLocalIpAddressInfoForDiagnostics = (
|
|
1014
|
+
successfulCandidatePairId: string,
|
|
1015
|
+
candidates: {[key: string]: Record<string, unknown>}
|
|
1016
|
+
) => {
|
|
1017
|
+
let newIpAddress = '';
|
|
1018
|
+
if (successfulCandidatePairId && !isEmpty(candidates)) {
|
|
1019
|
+
const localCandidate = candidates[successfulCandidatePairId];
|
|
1020
|
+
if (localCandidate) {
|
|
1021
|
+
if (localCandidate.candidateType === 'host') {
|
|
1022
|
+
// if it's a host candidate, use the address property - it will be the local IP
|
|
1023
|
+
newIpAddress = `${localCandidate.address}`;
|
|
1024
|
+
} else if (localCandidate.candidateType === 'prflx') {
|
|
1025
|
+
// if it's a peer reflexive candidate and we're not using a relay (there is no relayProtocol set)
|
|
1026
|
+
// then look at the relatedAddress - it will be the local
|
|
1027
|
+
//
|
|
1028
|
+
// Firefox doesn't populate the relayProtocol property
|
|
1029
|
+
if (!localCandidate.relayProtocol) {
|
|
1030
|
+
newIpAddress = `${localCandidate.relatedAddress}`;
|
|
1031
|
+
} else {
|
|
1032
|
+
// if it's a peer reflexive candidate and we are using a relay -
|
|
1033
|
+
// in that case the relatedAddress will be the IP of the TURN server (Linus),
|
|
1034
|
+
// so we can only look at the address, but it might be local IP or public IP,
|
|
1035
|
+
// depending on if the user is behind a NAT or not
|
|
1036
|
+
newIpAddress = `${localCandidate.address}`;
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
this.localIpAddress = newIpAddress;
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1038
1044
|
/**
|
|
1039
1045
|
* Processes remote and local candidate result and stores
|
|
1040
1046
|
* @private
|
|
@@ -1049,125 +1055,53 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1049
1055
|
if (!result || !result.id) {
|
|
1050
1056
|
return;
|
|
1051
1057
|
}
|
|
1052
|
-
const RemoteCandidateType = {};
|
|
1053
|
-
const RemoteTransport = {};
|
|
1054
|
-
const RemoteIpAddress = {};
|
|
1055
|
-
const RemoteNetworkType = {};
|
|
1056
|
-
|
|
1057
|
-
if (!result.id) return;
|
|
1058
|
-
|
|
1059
|
-
const sendRecvType = isSender ? STATS.SEND_DIRECTION : STATS.RECEIVE_DIRECTION;
|
|
1060
|
-
const ipType = isRemote ? STATS.REMOTE : STATS.LOCAL;
|
|
1061
|
-
|
|
1062
|
-
if (!RemoteCandidateType[result.id]) {
|
|
1063
|
-
RemoteCandidateType[result.id] = [];
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
if (!RemoteTransport[result.id]) {
|
|
1067
|
-
RemoteTransport[result.id] = [];
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
if (!RemoteIpAddress[result.id]) {
|
|
1071
|
-
RemoteIpAddress[result.id] = [];
|
|
1072
|
-
}
|
|
1073
|
-
if (!RemoteNetworkType[result.id]) {
|
|
1074
|
-
RemoteNetworkType[result.id] = [];
|
|
1075
|
-
}
|
|
1076
1058
|
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
) {
|
|
1081
|
-
RemoteCandidateType[result.id].push(result.candidateType);
|
|
1059
|
+
// We only care about the successful local candidate
|
|
1060
|
+
if (this.successfulCandidatePair?.localCandidateId !== result.id) {
|
|
1061
|
+
return;
|
|
1082
1062
|
}
|
|
1083
1063
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1064
|
+
let transport;
|
|
1065
|
+
if (result.relayProtocol) {
|
|
1066
|
+
transport = result.relayProtocol.toUpperCase();
|
|
1067
|
+
} else if (result.protocol) {
|
|
1068
|
+
transport = result.protocol.toUpperCase();
|
|
1086
1069
|
}
|
|
1087
1070
|
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
RemoteIpAddress[result.id].indexOf(`${result.ip}:${result.portNumber}`) === -1
|
|
1091
|
-
) {
|
|
1092
|
-
RemoteIpAddress[result.id].push(`${result.ip}`); // TODO: Add ports
|
|
1093
|
-
}
|
|
1071
|
+
const sendRecvType = isSender ? STATS.SEND_DIRECTION : STATS.RECEIVE_DIRECTION;
|
|
1072
|
+
const ipType = isRemote ? STATS.REMOTE : STATS.LOCAL;
|
|
1094
1073
|
|
|
1095
|
-
if (
|
|
1096
|
-
|
|
1074
|
+
if (!this.statsResults.candidates) {
|
|
1075
|
+
this.statsResults.candidates = {};
|
|
1097
1076
|
}
|
|
1098
1077
|
|
|
1099
|
-
this.statsResults.
|
|
1100
|
-
candidateType:
|
|
1101
|
-
ipAddress:
|
|
1078
|
+
this.statsResults.candidates[result.id] = {
|
|
1079
|
+
candidateType: result.candidateType,
|
|
1080
|
+
ipAddress: result.ip, // TODO: add ports
|
|
1081
|
+
relatedAddress: result.relatedAddress,
|
|
1082
|
+
relatedPort: result.relatedPort,
|
|
1083
|
+
relayProtocol: result.relayProtocol,
|
|
1084
|
+
protocol: result.protocol,
|
|
1085
|
+
address: result.address,
|
|
1102
1086
|
portNumber: result.port,
|
|
1103
|
-
networkType:
|
|
1087
|
+
networkType: result.networkType,
|
|
1104
1088
|
priority: result.priority,
|
|
1105
|
-
transport
|
|
1089
|
+
transport,
|
|
1106
1090
|
timestamp: result.time,
|
|
1107
1091
|
id: result.id,
|
|
1108
1092
|
type: result.type,
|
|
1109
1093
|
};
|
|
1110
1094
|
|
|
1111
|
-
this.statsResults.connectionType[ipType].candidateType =
|
|
1112
|
-
this.statsResults.connectionType[ipType].ipAddress =
|
|
1095
|
+
this.statsResults.connectionType[ipType].candidateType = result.candidateType;
|
|
1096
|
+
this.statsResults.connectionType[ipType].ipAddress = result.ipAddress;
|
|
1113
1097
|
|
|
1114
1098
|
this.statsResults.connectionType[ipType].networkType =
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
: RemoteNetworkType[result.id][0];
|
|
1118
|
-
this.statsResults.connectionType[ipType].transport = RemoteTransport[result.id];
|
|
1099
|
+
result.networkType === NETWORK_TYPE.VPN ? NETWORK_TYPE.UNKNOWN : result.networkType;
|
|
1100
|
+
this.statsResults.connectionType[ipType].transport = transport;
|
|
1119
1101
|
|
|
1120
1102
|
this.statsResults[type][sendRecvType].totalRoundTripTime = result.totalRoundTripTime;
|
|
1121
1103
|
};
|
|
1122
1104
|
|
|
1123
|
-
/**
|
|
1124
|
-
* Process Track results
|
|
1125
|
-
*
|
|
1126
|
-
* @private
|
|
1127
|
-
* @param {*} result
|
|
1128
|
-
* @param {*} mediaType
|
|
1129
|
-
* @returns {void}
|
|
1130
|
-
* @memberof StatsAnalyzer
|
|
1131
|
-
*/
|
|
1132
|
-
private processTrackResult(result: any, mediaType: any) {
|
|
1133
|
-
if (!result || result.type !== 'track') {
|
|
1134
|
-
return;
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
const sendrecvType =
|
|
1138
|
-
result.remoteSource === true ? STATS.RECEIVE_DIRECTION : STATS.SEND_DIRECTION;
|
|
1139
|
-
|
|
1140
|
-
if (result.frameWidth && result.frameHeight) {
|
|
1141
|
-
this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;
|
|
1142
|
-
this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;
|
|
1143
|
-
this.statsResults.resolutions[mediaType][sendrecvType].framesSent = result.framesSent;
|
|
1144
|
-
this.statsResults.resolutions[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
if (sendrecvType === STATS.RECEIVE_DIRECTION) {
|
|
1148
|
-
this.statsResults.resolutions[mediaType][sendrecvType].framesReceived = result.framesReceived;
|
|
1149
|
-
this.statsResults.resolutions[mediaType][sendrecvType].framesDecoded = result.framesDecoded;
|
|
1150
|
-
this.statsResults.resolutions[mediaType][sendrecvType].framesDropped = result.framesDropped;
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
if (result.trackIdentifier && !mediaType.includes('audio')) {
|
|
1154
|
-
this.statsResults.resolutions[mediaType][sendrecvType].trackIdentifier =
|
|
1155
|
-
result.trackIdentifier;
|
|
1156
|
-
|
|
1157
|
-
const jitterBufferDelay = result && result.jitterBufferDelay;
|
|
1158
|
-
const jitterBufferEmittedCount = result && result.jitterBufferEmittedCount;
|
|
1159
|
-
|
|
1160
|
-
this.statsResults.resolutions[mediaType][sendrecvType].avgJitterDelay =
|
|
1161
|
-
jitterBufferEmittedCount && +jitterBufferDelay / +jitterBufferEmittedCount;
|
|
1162
|
-
|
|
1163
|
-
// Used to calculate the jitter
|
|
1164
|
-
this.statsResults.resolutions[mediaType][sendrecvType].jitterBufferDelay =
|
|
1165
|
-
result.jitterBufferDelay;
|
|
1166
|
-
this.statsResults.resolutions[mediaType][sendrecvType].jitterBufferEmittedCount =
|
|
1167
|
-
result.jitterBufferEmittedCount;
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
1105
|
/**
|
|
1172
1106
|
*
|
|
1173
1107
|
* @private
|
|
@@ -1178,20 +1112,15 @@ export class StatsAnalyzer extends EventsScope {
|
|
|
1178
1112
|
*/
|
|
1179
1113
|
compareSentAndReceived(result, type) {
|
|
1180
1114
|
// Don't compare on transceivers without a sender.
|
|
1181
|
-
if (!type || !this.statsResults
|
|
1115
|
+
if (!type || !this.statsResults[type].send) {
|
|
1182
1116
|
return;
|
|
1183
1117
|
}
|
|
1184
1118
|
|
|
1185
1119
|
const mediaType = type;
|
|
1186
1120
|
|
|
1187
|
-
if (!this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver) {
|
|
1188
|
-
this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
1121
|
const currentPacketLoss =
|
|
1192
|
-
result.packetsLost - this.statsResults
|
|
1122
|
+
result.packetsLost - this.statsResults[mediaType].send.totalPacketsLostOnReceiver;
|
|
1193
1123
|
|
|
1194
|
-
this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
|
|
1195
1124
|
this.statsResults[mediaType].send.packetsLostOnReceiver = currentPacketLoss;
|
|
1196
1125
|
this.statsResults[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
|
|
1197
1126
|
|