@webex/plugin-meetings 2.59.8 → 2.60.0-next.10

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.
Files changed (517) hide show
  1. package/README.md +46 -8
  2. package/dist/annotation/annotation.types.d.ts +42 -0
  3. package/dist/annotation/annotation.types.js +7 -0
  4. package/dist/annotation/annotation.types.js.map +1 -0
  5. package/dist/annotation/constants.d.ts +31 -0
  6. package/dist/annotation/constants.js +41 -0
  7. package/dist/annotation/constants.js.map +1 -0
  8. package/dist/annotation/index.d.ts +117 -0
  9. package/dist/annotation/index.js +357 -0
  10. package/dist/annotation/index.js.map +1 -0
  11. package/dist/breakouts/breakout.d.ts +8 -0
  12. package/dist/breakouts/breakout.js +215 -0
  13. package/dist/breakouts/breakout.js.map +1 -0
  14. package/dist/breakouts/collection.d.ts +5 -0
  15. package/dist/breakouts/collection.js +22 -0
  16. package/dist/breakouts/collection.js.map +1 -0
  17. package/dist/breakouts/edit-lock-error.d.ts +15 -0
  18. package/dist/breakouts/edit-lock-error.js +51 -0
  19. package/dist/breakouts/edit-lock-error.js.map +1 -0
  20. package/dist/breakouts/events.d.ts +8 -0
  21. package/dist/breakouts/events.js +44 -0
  22. package/dist/breakouts/events.js.map +1 -0
  23. package/dist/breakouts/index.d.ts +5 -0
  24. package/dist/breakouts/index.js +1047 -0
  25. package/dist/breakouts/index.js.map +1 -0
  26. package/dist/breakouts/request.d.ts +22 -0
  27. package/dist/breakouts/request.js +77 -0
  28. package/dist/breakouts/request.js.map +1 -0
  29. package/dist/breakouts/utils.d.ts +15 -0
  30. package/dist/breakouts/utils.js +64 -0
  31. package/dist/breakouts/utils.js.map +1 -0
  32. package/dist/common/browser-detection.js +2 -3
  33. package/dist/common/browser-detection.js.map +1 -1
  34. package/dist/common/collection.js +3 -4
  35. package/dist/common/collection.js.map +1 -1
  36. package/dist/common/config.js +1 -2
  37. package/dist/common/config.js.map +1 -1
  38. package/dist/common/errors/captcha-error.js +1 -2
  39. package/dist/common/errors/captcha-error.js.map +1 -1
  40. package/dist/common/errors/intent-to-join.js +1 -2
  41. package/dist/common/errors/intent-to-join.js.map +1 -1
  42. package/dist/common/errors/join-meeting.js +1 -2
  43. package/dist/common/errors/join-meeting.js.map +1 -1
  44. package/dist/common/errors/media.js +1 -2
  45. package/dist/common/errors/media.js.map +1 -1
  46. package/dist/common/errors/no-meeting-info.d.ts +14 -0
  47. package/dist/common/errors/no-meeting-info.js +50 -0
  48. package/dist/common/errors/no-meeting-info.js.map +1 -0
  49. package/dist/common/errors/parameter.js +3 -4
  50. package/dist/common/errors/parameter.js.map +1 -1
  51. package/dist/common/errors/password-error.js +1 -2
  52. package/dist/common/errors/password-error.js.map +1 -1
  53. package/dist/common/errors/permission.js +1 -2
  54. package/dist/common/errors/permission.js.map +1 -1
  55. package/dist/common/errors/reclaim-host-role-errors.d.ts +60 -0
  56. package/dist/common/errors/reclaim-host-role-errors.js +154 -0
  57. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  58. package/dist/common/errors/reconnection-in-progress.js +1 -2
  59. package/dist/common/errors/reconnection-in-progress.js.map +1 -1
  60. package/dist/common/errors/reconnection.js +1 -2
  61. package/dist/common/errors/reconnection.js.map +1 -1
  62. package/dist/common/errors/stats.js +1 -2
  63. package/dist/common/errors/stats.js.map +1 -1
  64. package/dist/common/errors/webex-errors.d.ts +20 -8
  65. package/dist/common/errors/webex-errors.js +48 -28
  66. package/dist/common/errors/webex-errors.js.map +1 -1
  67. package/dist/common/errors/webex-meetings-error.js +1 -2
  68. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  69. package/dist/common/events/events-scope.js +1 -2
  70. package/dist/common/events/events-scope.js.map +1 -1
  71. package/dist/common/events/events.js +1 -2
  72. package/dist/common/events/events.js.map +1 -1
  73. package/dist/common/events/trigger-proxy.js +1 -2
  74. package/dist/common/events/trigger-proxy.js.map +1 -1
  75. package/dist/common/events/util.js +1 -2
  76. package/dist/common/events/util.js.map +1 -1
  77. package/dist/common/logs/logger-config.js +1 -2
  78. package/dist/common/logs/logger-config.js.map +1 -1
  79. package/dist/common/logs/logger-proxy.js +2 -3
  80. package/dist/common/logs/logger-proxy.js.map +1 -1
  81. package/dist/common/logs/request.d.ts +3 -1
  82. package/dist/common/logs/request.js +8 -5
  83. package/dist/common/logs/request.js.map +1 -1
  84. package/dist/common/queue.d.ts +9 -7
  85. package/dist/common/queue.js +22 -9
  86. package/dist/common/queue.js.map +1 -1
  87. package/dist/config.d.ts +5 -7
  88. package/dist/config.js +8 -11
  89. package/dist/config.js.map +1 -1
  90. package/dist/constants.d.ts +243 -97
  91. package/dist/constants.js +437 -435
  92. package/dist/constants.js.map +1 -1
  93. package/dist/controls-options-manager/constants.js +3 -6
  94. package/dist/controls-options-manager/constants.js.map +1 -1
  95. package/dist/controls-options-manager/enums.d.ts +11 -1
  96. package/dist/controls-options-manager/enums.js +15 -6
  97. package/dist/controls-options-manager/enums.js.map +1 -1
  98. package/dist/controls-options-manager/index.d.ts +17 -1
  99. package/dist/controls-options-manager/index.js +127 -38
  100. package/dist/controls-options-manager/index.js.map +1 -1
  101. package/dist/controls-options-manager/types.d.ts +43 -0
  102. package/dist/controls-options-manager/types.js +7 -0
  103. package/dist/controls-options-manager/types.js.map +1 -0
  104. package/dist/controls-options-manager/util.d.ts +1 -7
  105. package/dist/controls-options-manager/util.js +309 -19
  106. package/dist/controls-options-manager/util.js.map +1 -1
  107. package/dist/index.d.ts +6 -3
  108. package/dist/index.js +116 -4
  109. package/dist/index.js.map +1 -1
  110. package/dist/interpretation/collection.d.ts +5 -0
  111. package/dist/interpretation/collection.js +22 -0
  112. package/dist/interpretation/collection.js.map +1 -0
  113. package/dist/interpretation/index.d.ts +5 -0
  114. package/dist/interpretation/index.js +365 -0
  115. package/dist/interpretation/index.js.map +1 -0
  116. package/dist/interpretation/siLanguage.d.ts +5 -0
  117. package/dist/interpretation/siLanguage.js +24 -0
  118. package/dist/interpretation/siLanguage.js.map +1 -0
  119. package/dist/locus-info/controlsUtils.js +100 -11
  120. package/dist/locus-info/controlsUtils.js.map +1 -1
  121. package/dist/locus-info/embeddedAppsUtils.js +3 -4
  122. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  123. package/dist/locus-info/fullState.js +1 -2
  124. package/dist/locus-info/fullState.js.map +1 -1
  125. package/dist/locus-info/hostUtils.js +1 -2
  126. package/dist/locus-info/hostUtils.js.map +1 -1
  127. package/dist/locus-info/index.d.ts +57 -4
  128. package/dist/locus-info/index.js +425 -84
  129. package/dist/locus-info/index.js.map +1 -1
  130. package/dist/locus-info/infoUtils.js +13 -5
  131. package/dist/locus-info/infoUtils.js.map +1 -1
  132. package/dist/locus-info/mediaSharesUtils.js +58 -3
  133. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  134. package/dist/locus-info/parser.d.ts +66 -6
  135. package/dist/locus-info/parser.js +253 -80
  136. package/dist/locus-info/parser.js.map +1 -1
  137. package/dist/locus-info/selfUtils.js +97 -13
  138. package/dist/locus-info/selfUtils.js.map +1 -1
  139. package/dist/media/index.d.ts +2 -0
  140. package/dist/media/index.js +107 -319
  141. package/dist/media/index.js.map +1 -1
  142. package/dist/media/properties.d.ts +38 -53
  143. package/dist/media/properties.js +96 -153
  144. package/dist/media/properties.js.map +1 -1
  145. package/dist/media/util.js +1 -22
  146. package/dist/media/util.js.map +1 -1
  147. package/dist/mediaQualityMetrics/config.d.ts +234 -230
  148. package/dist/mediaQualityMetrics/config.js +302 -498
  149. package/dist/mediaQualityMetrics/config.js.map +1 -1
  150. package/dist/meeting/in-meeting-actions.d.ts +88 -0
  151. package/dist/meeting/in-meeting-actions.js +94 -3
  152. package/dist/meeting/in-meeting-actions.js.map +1 -1
  153. package/dist/meeting/index.d.ts +591 -494
  154. package/dist/meeting/index.js +4728 -2990
  155. package/dist/meeting/index.js.map +1 -1
  156. package/dist/meeting/locusMediaRequest.d.ts +74 -0
  157. package/dist/meeting/locusMediaRequest.js +291 -0
  158. package/dist/meeting/locusMediaRequest.js.map +1 -0
  159. package/dist/meeting/muteState.d.ts +93 -25
  160. package/dist/meeting/muteState.js +224 -133
  161. package/dist/meeting/muteState.js.map +1 -1
  162. package/dist/meeting/request.d.ts +82 -47
  163. package/dist/meeting/request.js +297 -199
  164. package/dist/meeting/request.js.map +1 -1
  165. package/dist/meeting/request.type.d.ts +11 -0
  166. package/dist/meeting/request.type.js +7 -0
  167. package/dist/meeting/request.type.js.map +1 -0
  168. package/dist/meeting/state.js +1 -2
  169. package/dist/meeting/state.js.map +1 -1
  170. package/dist/meeting/util.d.ts +102 -1
  171. package/dist/meeting/util.js +605 -435
  172. package/dist/meeting/util.js.map +1 -1
  173. package/dist/meeting-info/collection.js +3 -4
  174. package/dist/meeting-info/collection.js.map +1 -1
  175. package/dist/meeting-info/index.d.ts +13 -1
  176. package/dist/meeting-info/index.js +74 -7
  177. package/dist/meeting-info/index.js.map +1 -1
  178. package/dist/meeting-info/meeting-info-v2.d.ts +31 -1
  179. package/dist/meeting-info/meeting-info-v2.js +200 -63
  180. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  181. package/dist/meeting-info/request.js +1 -2
  182. package/dist/meeting-info/request.js.map +1 -1
  183. package/dist/meeting-info/util.js +2 -3
  184. package/dist/meeting-info/util.js.map +1 -1
  185. package/dist/meeting-info/utilv2.js +39 -41
  186. package/dist/meeting-info/utilv2.js.map +1 -1
  187. package/dist/meetings/collection.d.ts +17 -0
  188. package/dist/meetings/collection.js +42 -4
  189. package/dist/meetings/collection.js.map +1 -1
  190. package/dist/meetings/index.d.ts +103 -21
  191. package/dist/meetings/index.js +486 -124
  192. package/dist/meetings/index.js.map +1 -1
  193. package/dist/meetings/meetings.types.d.ts +4 -0
  194. package/dist/meetings/meetings.types.js +7 -0
  195. package/dist/meetings/meetings.types.js.map +1 -0
  196. package/dist/meetings/request.js +4 -3
  197. package/dist/meetings/request.js.map +1 -1
  198. package/dist/meetings/util.js +107 -6
  199. package/dist/meetings/util.js.map +1 -1
  200. package/dist/member/index.d.ts +14 -1
  201. package/dist/member/index.js +54 -2
  202. package/dist/member/index.js.map +1 -1
  203. package/dist/member/member.types.js +3 -4
  204. package/dist/member/member.types.js.map +1 -1
  205. package/dist/member/types.d.ts +32 -0
  206. package/dist/member/types.js +23 -0
  207. package/dist/member/types.js.map +1 -0
  208. package/dist/member/util.js +131 -29
  209. package/dist/member/util.js.map +1 -1
  210. package/dist/members/collection.d.ts +5 -0
  211. package/dist/members/collection.js +11 -2
  212. package/dist/members/collection.js.map +1 -1
  213. package/dist/members/index.d.ts +57 -2
  214. package/dist/members/index.js +174 -10
  215. package/dist/members/index.js.map +1 -1
  216. package/dist/members/request.d.ts +73 -9
  217. package/dist/members/request.js +108 -41
  218. package/dist/members/request.js.map +1 -1
  219. package/dist/members/types.d.ts +25 -0
  220. package/dist/members/types.js +14 -0
  221. package/dist/members/types.js.map +1 -0
  222. package/dist/members/util.d.ts +214 -1
  223. package/dist/members/util.js +327 -234
  224. package/dist/members/util.js.map +1 -1
  225. package/dist/metrics/constants.d.ts +15 -6
  226. package/dist/metrics/constants.js +17 -9
  227. package/dist/metrics/constants.js.map +1 -1
  228. package/dist/metrics/index.d.ts +4 -111
  229. package/dist/metrics/index.js +4 -452
  230. package/dist/metrics/index.js.map +1 -1
  231. package/dist/multistream/mediaRequestManager.d.ts +118 -0
  232. package/dist/multistream/mediaRequestManager.js +344 -0
  233. package/dist/multistream/mediaRequestManager.js.map +1 -0
  234. package/dist/multistream/receiveSlot.d.ts +68 -0
  235. package/dist/multistream/receiveSlot.js +200 -0
  236. package/dist/multistream/receiveSlot.js.map +1 -0
  237. package/dist/multistream/receiveSlotManager.d.ts +56 -0
  238. package/dist/multistream/receiveSlotManager.js +174 -0
  239. package/dist/multistream/receiveSlotManager.js.map +1 -0
  240. package/dist/multistream/remoteMedia.d.ts +72 -0
  241. package/dist/multistream/remoteMedia.js +268 -0
  242. package/dist/multistream/remoteMedia.js.map +1 -0
  243. package/dist/multistream/remoteMediaGroup.d.ts +47 -0
  244. package/dist/multistream/remoteMediaGroup.js +267 -0
  245. package/dist/multistream/remoteMediaGroup.js.map +1 -0
  246. package/dist/multistream/remoteMediaManager.d.ts +285 -0
  247. package/dist/multistream/remoteMediaManager.js +1211 -0
  248. package/dist/multistream/remoteMediaManager.js.map +1 -0
  249. package/dist/multistream/sendSlotManager.d.ts +61 -0
  250. package/dist/multistream/sendSlotManager.js +236 -0
  251. package/dist/multistream/sendSlotManager.js.map +1 -0
  252. package/dist/networkQualityMonitor/index.js +5 -4
  253. package/dist/networkQualityMonitor/index.js.map +1 -1
  254. package/dist/personal-meeting-room/index.js +2 -3
  255. package/dist/personal-meeting-room/index.js.map +1 -1
  256. package/dist/personal-meeting-room/request.js +2 -3
  257. package/dist/personal-meeting-room/request.js.map +1 -1
  258. package/dist/personal-meeting-room/util.js +1 -2
  259. package/dist/personal-meeting-room/util.js.map +1 -1
  260. package/dist/reachability/index.d.ts +62 -7
  261. package/dist/reachability/index.js +265 -72
  262. package/dist/reachability/index.js.map +1 -1
  263. package/dist/reachability/request.d.ts +7 -3
  264. package/dist/reachability/request.js +18 -10
  265. package/dist/reachability/request.js.map +1 -1
  266. package/dist/reactions/constants.d.ts +3 -0
  267. package/dist/reactions/constants.js +12 -0
  268. package/dist/reactions/constants.js.map +1 -0
  269. package/dist/reactions/reactions.d.ts +2 -2
  270. package/dist/reactions/reactions.js +4 -6
  271. package/dist/reactions/reactions.js.map +1 -1
  272. package/dist/reactions/reactions.type.d.ts +23 -3
  273. package/dist/reactions/reactions.type.js +21 -23
  274. package/dist/reactions/reactions.type.js.map +1 -1
  275. package/dist/reconnection-manager/index.d.ts +32 -8
  276. package/dist/reconnection-manager/index.js +282 -231
  277. package/dist/reconnection-manager/index.js.map +1 -1
  278. package/dist/recording-controller/enums.js +4 -5
  279. package/dist/recording-controller/enums.js.map +1 -1
  280. package/dist/recording-controller/index.d.ts +15 -1
  281. package/dist/recording-controller/index.js +57 -46
  282. package/dist/recording-controller/index.js.map +1 -1
  283. package/dist/recording-controller/util.d.ts +5 -4
  284. package/dist/recording-controller/util.js +10 -10
  285. package/dist/recording-controller/util.js.map +1 -1
  286. package/dist/roap/index.d.ts +9 -47
  287. package/dist/roap/index.js +101 -235
  288. package/dist/roap/index.js.map +1 -1
  289. package/dist/roap/request.d.ts +18 -12
  290. package/dist/roap/request.js +126 -180
  291. package/dist/roap/request.js.map +1 -1
  292. package/dist/roap/turnDiscovery.d.ts +27 -16
  293. package/dist/roap/turnDiscovery.js +115 -105
  294. package/dist/roap/turnDiscovery.js.map +1 -1
  295. package/dist/rtcMetrics/constants.d.ts +4 -0
  296. package/dist/rtcMetrics/constants.js +11 -0
  297. package/dist/rtcMetrics/constants.js.map +1 -0
  298. package/dist/rtcMetrics/index.d.ts +54 -0
  299. package/dist/rtcMetrics/index.js +140 -0
  300. package/dist/rtcMetrics/index.js.map +1 -0
  301. package/dist/statsAnalyzer/global.d.ts +1 -83
  302. package/dist/statsAnalyzer/global.js +2 -85
  303. package/dist/statsAnalyzer/global.js.map +1 -1
  304. package/dist/statsAnalyzer/index.d.ts +28 -30
  305. package/dist/statsAnalyzer/index.js +374 -509
  306. package/dist/statsAnalyzer/index.js.map +1 -1
  307. package/dist/statsAnalyzer/mqaUtil.d.ts +8 -6
  308. package/dist/statsAnalyzer/mqaUtil.js +116 -83
  309. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  310. package/dist/transcription/index.js +1 -2
  311. package/dist/transcription/index.js.map +1 -1
  312. package/dist/webinar/collection.d.ts +16 -0
  313. package/dist/webinar/collection.js +43 -0
  314. package/dist/webinar/collection.js.map +1 -0
  315. package/dist/webinar/index.d.ts +5 -0
  316. package/dist/webinar/index.js +68 -0
  317. package/dist/webinar/index.js.map +1 -0
  318. package/package.json +35 -26
  319. package/src/annotation/annotation.types.ts +50 -0
  320. package/src/annotation/constants.ts +36 -0
  321. package/src/annotation/index.ts +328 -0
  322. package/src/breakouts/README.md +220 -0
  323. package/src/breakouts/breakout.ts +188 -0
  324. package/src/breakouts/collection.ts +19 -0
  325. package/src/breakouts/edit-lock-error.ts +25 -0
  326. package/src/breakouts/events.ts +56 -0
  327. package/src/breakouts/index.ts +925 -0
  328. package/src/breakouts/request.ts +55 -0
  329. package/src/breakouts/utils.ts +57 -0
  330. package/src/common/errors/no-meeting-info.ts +24 -0
  331. package/src/common/errors/reclaim-host-role-errors.ts +134 -0
  332. package/src/common/errors/webex-errors.ts +36 -12
  333. package/src/common/logs/logger-proxy.ts +1 -1
  334. package/src/common/logs/request.ts +5 -1
  335. package/src/common/queue.ts +22 -8
  336. package/src/config.ts +5 -7
  337. package/src/constants.ts +271 -93
  338. package/src/controls-options-manager/enums.ts +12 -0
  339. package/src/controls-options-manager/index.ts +116 -21
  340. package/src/controls-options-manager/types.ts +59 -0
  341. package/src/controls-options-manager/util.ts +294 -14
  342. package/src/index.ts +40 -0
  343. package/src/interpretation/README.md +60 -0
  344. package/src/interpretation/collection.ts +19 -0
  345. package/src/interpretation/index.ts +332 -0
  346. package/src/interpretation/siLanguage.ts +18 -0
  347. package/src/locus-info/controlsUtils.ts +110 -0
  348. package/src/locus-info/index.ts +449 -61
  349. package/src/locus-info/infoUtils.ts +14 -2
  350. package/src/locus-info/mediaSharesUtils.ts +64 -0
  351. package/src/locus-info/parser.ts +258 -47
  352. package/src/locus-info/selfUtils.ts +85 -2
  353. package/src/media/index.ts +153 -370
  354. package/src/media/properties.ts +106 -136
  355. package/src/media/util.ts +0 -21
  356. package/src/mediaQualityMetrics/config.ts +244 -377
  357. package/src/meeting/in-meeting-actions.ts +176 -0
  358. package/src/meeting/index.ts +3895 -2448
  359. package/src/meeting/locusMediaRequest.ts +313 -0
  360. package/src/meeting/muteState.ts +224 -138
  361. package/src/meeting/request.ts +207 -127
  362. package/src/meeting/request.type.ts +13 -0
  363. package/src/meeting/util.ts +590 -423
  364. package/src/meeting-info/index.ts +81 -8
  365. package/src/meeting-info/meeting-info-v2.ts +163 -13
  366. package/src/meeting-info/util.ts +1 -1
  367. package/src/meeting-info/utilv2.ts +28 -28
  368. package/src/meetings/collection.ts +33 -0
  369. package/src/meetings/index.ts +486 -126
  370. package/src/meetings/meetings.types.ts +12 -0
  371. package/src/meetings/request.ts +2 -0
  372. package/src/meetings/util.ts +116 -5
  373. package/src/member/index.ts +52 -1
  374. package/src/member/types.ts +38 -0
  375. package/src/member/util.ts +139 -28
  376. package/src/members/collection.ts +8 -0
  377. package/src/members/index.ts +196 -7
  378. package/src/members/request.ts +97 -17
  379. package/src/members/types.ts +29 -0
  380. package/src/members/util.ts +333 -240
  381. package/src/metrics/constants.ts +15 -6
  382. package/src/metrics/index.ts +1 -471
  383. package/src/multistream/mediaRequestManager.ts +440 -0
  384. package/src/multistream/receiveSlot.ts +184 -0
  385. package/src/multistream/receiveSlotManager.ts +166 -0
  386. package/src/multistream/remoteMedia.ts +254 -0
  387. package/src/multistream/remoteMediaGroup.ts +284 -0
  388. package/src/multistream/remoteMediaManager.ts +1145 -0
  389. package/src/multistream/sendSlotManager.ts +170 -0
  390. package/src/networkQualityMonitor/index.ts +6 -6
  391. package/src/reachability/index.ts +238 -45
  392. package/src/reachability/request.ts +17 -8
  393. package/src/reactions/constants.ts +4 -0
  394. package/src/reactions/reactions.ts +4 -4
  395. package/src/reactions/reactions.type.ts +30 -4
  396. package/src/reconnection-manager/index.ts +168 -156
  397. package/src/recording-controller/index.ts +20 -3
  398. package/src/recording-controller/util.ts +26 -9
  399. package/src/roap/index.ts +98 -241
  400. package/src/roap/request.ts +74 -148
  401. package/src/roap/turnDiscovery.ts +62 -56
  402. package/src/rtcMetrics/constants.ts +3 -0
  403. package/src/rtcMetrics/index.ts +124 -0
  404. package/src/statsAnalyzer/global.ts +1 -84
  405. package/src/statsAnalyzer/index.ts +413 -642
  406. package/src/statsAnalyzer/mqaUtil.ts +111 -114
  407. package/src/webinar/collection.ts +31 -0
  408. package/src/webinar/index.ts +62 -0
  409. package/test/integration/spec/converged-space-meetings.js +233 -0
  410. package/test/integration/spec/journey.js +320 -264
  411. package/test/integration/spec/space-meeting.js +77 -4
  412. package/test/unit/spec/annotation/index.ts +418 -0
  413. package/test/unit/spec/breakouts/breakout.ts +237 -0
  414. package/test/unit/spec/breakouts/collection.ts +15 -0
  415. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  416. package/test/unit/spec/breakouts/events.ts +89 -0
  417. package/test/unit/spec/breakouts/index.ts +1790 -0
  418. package/test/unit/spec/breakouts/request.ts +104 -0
  419. package/test/unit/spec/breakouts/utils.js +72 -0
  420. package/test/unit/spec/common/queue.js +31 -2
  421. package/test/unit/spec/controls-options-manager/index.js +163 -0
  422. package/test/unit/spec/controls-options-manager/util.js +576 -60
  423. package/test/unit/spec/fixture/locus.js +1 -0
  424. package/test/unit/spec/interpretation/collection.ts +15 -0
  425. package/test/unit/spec/interpretation/index.ts +589 -0
  426. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  427. package/test/unit/spec/locus-info/controlsUtils.js +323 -30
  428. package/test/unit/spec/locus-info/index.js +1390 -16
  429. package/test/unit/spec/locus-info/infoUtils.js +54 -16
  430. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  431. package/test/unit/spec/locus-info/lib/selfConstant.js +48 -0
  432. package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
  433. package/test/unit/spec/locus-info/parser.js +116 -35
  434. package/test/unit/spec/locus-info/selfUtils.js +275 -0
  435. package/test/unit/spec/media/index.ts +290 -0
  436. package/test/unit/spec/media/properties.ts +75 -84
  437. package/test/unit/spec/meeting/in-meeting-actions.ts +86 -0
  438. package/test/unit/spec/meeting/index.js +8181 -2770
  439. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  440. package/test/unit/spec/meeting/muteState.js +409 -213
  441. package/test/unit/spec/meeting/request.js +512 -42
  442. package/test/unit/spec/meeting/utils.js +741 -24
  443. package/test/unit/spec/meeting-info/index.js +300 -0
  444. package/test/unit/spec/meeting-info/meetinginfov2.js +527 -5
  445. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  446. package/test/unit/spec/meetings/collection.js +26 -0
  447. package/test/unit/spec/meetings/index.js +1284 -217
  448. package/test/unit/spec/meetings/utils.js +202 -2
  449. package/test/unit/spec/member/index.js +38 -8
  450. package/test/unit/spec/member/util.js +499 -29
  451. package/test/unit/spec/members/index.js +597 -3
  452. package/test/unit/spec/members/request.js +206 -27
  453. package/test/unit/spec/members/utils.js +210 -0
  454. package/test/unit/spec/metrics/index.js +1 -50
  455. package/test/unit/spec/multistream/mediaRequestManager.ts +1418 -0
  456. package/test/unit/spec/multistream/receiveSlot.ts +163 -0
  457. package/test/unit/spec/multistream/receiveSlotManager.ts +203 -0
  458. package/test/unit/spec/multistream/remoteMedia.ts +255 -0
  459. package/test/unit/spec/multistream/remoteMediaGroup.ts +662 -0
  460. package/test/unit/spec/multistream/remoteMediaManager.ts +1924 -0
  461. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  462. package/test/unit/spec/networkQualityMonitor/index.js +4 -4
  463. package/test/unit/spec/reachability/index.ts +598 -24
  464. package/test/unit/spec/reachability/request.js +68 -0
  465. package/test/unit/spec/reconnection-manager/index.js +162 -24
  466. package/test/unit/spec/recording-controller/index.js +293 -218
  467. package/test/unit/spec/recording-controller/util.js +223 -96
  468. package/test/unit/spec/roap/index.ts +200 -76
  469. package/test/unit/spec/roap/request.ts +232 -0
  470. package/test/unit/spec/roap/turnDiscovery.ts +86 -48
  471. package/test/unit/spec/rtcMetrics/index.ts +93 -0
  472. package/test/unit/spec/stats-analyzer/index.js +188 -174
  473. package/test/unit/spec/webinar/collection.ts +13 -0
  474. package/test/unit/spec/webinar/index.ts +60 -0
  475. package/test/utils/constants.js +9 -0
  476. package/test/utils/integrationTestUtils.js +46 -0
  477. package/test/utils/testUtils.js +0 -45
  478. package/test/utils/webex-config.js +4 -0
  479. package/test/utils/webex-test-users.js +7 -3
  480. package/dist/meeting/effectsState.d.ts +0 -42
  481. package/dist/meeting/effectsState.js +0 -260
  482. package/dist/meeting/effectsState.js.map +0 -1
  483. package/dist/metrics/config.d.ts +0 -169
  484. package/dist/metrics/config.js +0 -289
  485. package/dist/metrics/config.js.map +0 -1
  486. package/dist/peer-connection-manager/index.d.ts +0 -6
  487. package/dist/peer-connection-manager/index.js +0 -671
  488. package/dist/peer-connection-manager/index.js.map +0 -1
  489. package/dist/peer-connection-manager/util.d.ts +0 -6
  490. package/dist/peer-connection-manager/util.js +0 -110
  491. package/dist/peer-connection-manager/util.js.map +0 -1
  492. package/dist/roap/collection.d.ts +0 -10
  493. package/dist/roap/collection.js +0 -63
  494. package/dist/roap/collection.js.map +0 -1
  495. package/dist/roap/handler.d.ts +0 -47
  496. package/dist/roap/handler.js +0 -279
  497. package/dist/roap/handler.js.map +0 -1
  498. package/dist/roap/state.d.ts +0 -9
  499. package/dist/roap/state.js +0 -127
  500. package/dist/roap/state.js.map +0 -1
  501. package/dist/roap/util.d.ts +0 -2
  502. package/dist/roap/util.js +0 -76
  503. package/dist/roap/util.js.map +0 -1
  504. package/src/index.js +0 -15
  505. package/src/meeting/effectsState.ts +0 -209
  506. package/src/metrics/config.ts +0 -485
  507. package/src/peer-connection-manager/index.ts +0 -847
  508. package/src/peer-connection-manager/util.ts +0 -119
  509. package/src/roap/collection.ts +0 -62
  510. package/src/roap/handler.ts +0 -294
  511. package/src/roap/state.ts +0 -156
  512. package/src/roap/util.ts +0 -100
  513. package/test/unit/spec/meeting/effectsState.js +0 -281
  514. package/test/unit/spec/peerconnection-manager/index.js +0 -218
  515. package/test/unit/spec/peerconnection-manager/utils.js +0 -49
  516. package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -388
  517. package/test/unit/spec/roap/util.js +0 -30
@@ -1,18 +1,24 @@
1
1
  /* eslint-disable prefer-destructuring */
2
2
 
3
3
  import {cloneDeep} from 'lodash';
4
+ import {ConnectionState} from '@webex/internal-media-core';
4
5
 
5
6
  import EventsScope from '../common/events/events-scope';
6
7
  import {
7
8
  DEFAULT_GET_STATS_FILTER,
8
- CONNECTION_STATE,
9
9
  STATS,
10
10
  MQA_INTEVAL,
11
11
  NETWORK_TYPE,
12
12
  MEDIA_DEVICES,
13
13
  _UNKNOWN_,
14
14
  } from '../constants';
15
- import mqaData from '../mediaQualityMetrics/config';
15
+ import {
16
+ emptyAudioReceive,
17
+ emptyAudioTransmit,
18
+ emptyMqaInterval,
19
+ emptyVideoReceive,
20
+ emptyVideoTransmit,
21
+ } from '../mediaQualityMetrics/config';
16
22
  import LoggerProxy from '../common/logs/logger-proxy';
17
23
 
18
24
  import defaultStats from './global';
@@ -22,17 +28,34 @@ import {
22
28
  getVideoSenderMqa,
23
29
  getVideoReceiverMqa,
24
30
  } from './mqaUtil';
31
+ import {ReceiveSlot} from '../multistream/receiveSlot';
25
32
 
26
33
  export const EVENTS = {
27
34
  MEDIA_QUALITY: 'MEDIA_QUALITY',
28
- NO_FRAMES_SENT: 'NO_FRAMES_SENT',
29
- NO_VIDEO_ENCODED: 'NO_VIDEO_ENCODED',
30
35
  LOCAL_MEDIA_STARTED: 'LOCAL_MEDIA_STARTED',
31
36
  LOCAL_MEDIA_STOPPED: 'LOCAL_MEDIA_STOPPED',
32
37
  REMOTE_MEDIA_STARTED: 'REMOTE_MEDIA_STARTED',
33
38
  REMOTE_MEDIA_STOPPED: 'REMOTE_MEDIA_STOPPED',
34
39
  };
35
40
 
41
+ const emptySender = {
42
+ trackLabel: '',
43
+ maxPacketLossRatio: 0,
44
+ availableBandwidth: 0,
45
+ bytesSent: 0,
46
+ meanRemoteJitter: [],
47
+ meanRoundTripTime: [],
48
+ };
49
+
50
+ const emptyReceiver = {
51
+ availableBandwidth: 0,
52
+ bytesReceived: 0,
53
+ meanRtpJitter: [],
54
+ meanRoundTripTime: [],
55
+ };
56
+
57
+ type ReceiveSlotCallback = (csi: number) => ReceiveSlot | undefined;
58
+
36
59
  /**
37
60
  * Stats Analyzer class that will emit events based on detected quality
38
61
  *
@@ -46,26 +69,29 @@ export class StatsAnalyzer extends EventsScope {
46
69
  lastEmittedStartStopEvent: any;
47
70
  lastMqaDataSent: any;
48
71
  lastStatsResults: any;
49
- localMQEStats: any;
50
72
  meetingMediaStatus: any;
51
73
  mqaInterval: NodeJS.Timeout;
52
74
  mqaSentCount: any;
53
75
  networkQualityMonitor: any;
54
- peerConnection: any;
76
+ mediaConnection: any;
55
77
  statsInterval: NodeJS.Timeout;
56
78
  statsResults: any;
57
79
  statsStarted: any;
80
+ successfulCandidatePair: any;
81
+ receiveSlotCallback: ReceiveSlotCallback;
58
82
 
59
83
  /**
60
84
  * Creates a new instance of StatsAnalyzer
61
85
  * @constructor
62
86
  * @public
63
87
  * @param {Object} config SDK Configuration Object
88
+ * @param {Function} receiveSlotCallback Callback used to access receive slots.
64
89
  * @param {Object} networkQualityMonitor class for assessing network characteristics (jitter, packetLoss, latency)
65
90
  * @param {Object} statsResults Default properties for stats
66
91
  */
67
92
  constructor(
68
93
  config: any,
94
+ receiveSlotCallback: ReceiveSlotCallback = () => undefined,
69
95
  networkQualityMonitor: object = {},
70
96
  statsResults: object = defaultStats
71
97
  ) {
@@ -77,147 +103,30 @@ export class StatsAnalyzer extends EventsScope {
77
103
  this.networkQualityMonitor = networkQualityMonitor;
78
104
  this.correlationId = config.correlationId;
79
105
  this.mqaSentCount = -1;
80
- this.lastMqaDataSent = {
81
- resolutions: {
82
- video: {send: {}, recv: {}},
83
- audio: {send: {}, recv: {}},
84
- share: {send: {}, recv: {}},
85
- },
86
- video: {send: {}, recv: {}},
87
- audio: {send: {}, recv: {}},
88
- share: {send: {}, recv: {}},
89
- };
90
- this.localMQEStats = {
91
- audio: {
92
- RX: {
93
- packetsLost: [],
94
- jitter: [],
95
- latency: [],
96
- bitRate: [],
97
- },
98
- TX: {
99
- packetsLost: [],
100
- jitter: [],
101
- latency: [],
102
- bitRate: [],
103
- },
104
- },
105
- video: {
106
- RX: {
107
- packetsLost: [],
108
- jitter: [],
109
- latency: [],
110
- bitRate: [],
111
- frameRate: [],
112
- resolutionWidth: [],
113
- resolutionHeight: [],
114
- requestedKeyFrame: [],
115
- receivedKeyFrame: [],
116
- },
117
- TX: {
118
- packetsLost: [],
119
- jitter: [],
120
- latency: [],
121
- bitRate: [],
122
- frameRate: [],
123
- resolutionWidth: [],
124
- resolutionHeight: [],
125
- requestedKeyFrame: [],
126
- receivedKeyFrame: [],
127
- },
128
- },
129
- };
130
- this.lastEmittedStartStopEvent = {
131
- audio: {
132
- local: undefined,
133
- remote: undefined,
134
- },
135
- video: {
136
- local: undefined,
137
- remote: undefined,
138
- },
139
- share: {
140
- local: undefined,
141
- remote: undefined,
142
- },
143
- };
144
- }
145
-
146
- populateResults(lastMqa) {
147
- // Audio
148
-
149
- this.localMQEStats.audio.RX.packetsLost.push(lastMqa.audioReceive[0].common.mediaHopByHopLost);
150
- this.localMQEStats.audio.RX.jitter.push(lastMqa.audioReceive[0].streams[0].common.rtpJitter);
151
- this.localMQEStats.audio.RX.latency.push(lastMqa.audioReceive[0].common.roundTripTime);
152
- this.localMQEStats.audio.RX.bitRate.push(
153
- lastMqa.audioReceive[0].streams[0].common.receivedBitrate
154
- );
155
-
156
- this.localMQEStats.audio.TX.packetsLost.push(lastMqa.audioTransmit[0].common.remoteLossRate);
157
- this.localMQEStats.audio.TX.jitter.push(lastMqa.audioTransmit[0].common.remoteJitter);
158
- this.localMQEStats.audio.TX.latency.push(lastMqa.audioTransmit[0].common.roundTripTime);
159
- this.localMQEStats.audio.TX.bitRate.push(
160
- lastMqa.audioTransmit[0].streams[0].common.transmittedBitrate
161
- );
162
-
163
- // Video
164
-
165
- this.localMQEStats.video.RX.packetsLost.push(lastMqa.videoReceive[0].common.mediaHopByHopLost);
166
- this.localMQEStats.video.RX.jitter.push(lastMqa.videoReceive[0].streams[0].common.rtpJitter);
167
- this.localMQEStats.video.RX.latency.push(
168
- lastMqa.videoReceive[0].streams[0].common.roundTripTime
169
- );
170
- this.localMQEStats.video.RX.bitRate.push(
171
- lastMqa.videoReceive[0].streams[0].common.receivedBitrate
172
- );
173
- this.localMQEStats.video.RX.frameRate.push(
174
- lastMqa.videoReceive[0].streams[0].common.receivedFrameRate
175
- );
176
- this.localMQEStats.video.RX.resolutionWidth.push(
177
- lastMqa.videoReceive[0].streams[0].receivedWidth
178
- );
179
- this.localMQEStats.video.RX.resolutionHeight.push(
180
- lastMqa.videoReceive[0].streams[0].receivedHeight
181
- );
182
- this.localMQEStats.video.RX.requestedKeyFrame.push();
183
- this.localMQEStats.video.RX.receivedKeyFrame.push();
184
-
185
- this.localMQEStats.video.TX.packetsLost.push(lastMqa.videoTransmit[0].common.remoteLossRate);
186
- this.localMQEStats.video.TX.jitter.push(lastMqa.videoTransmit[0].common.remoteJitter);
187
- this.localMQEStats.video.TX.latency.push(lastMqa.videoTransmit[0].common.roundTripTime);
188
- this.localMQEStats.video.TX.bitRate.push(
189
- lastMqa.videoTransmit[0].streams[0].common.transmittedBitrate
190
- );
191
- this.localMQEStats.video.TX.frameRate.push(
192
- lastMqa.videoTransmit[0].streams[0].common.transmittedFrameRate
193
- );
194
- this.localMQEStats.video.TX.resolutionWidth.push(
195
- lastMqa.videoTransmit[0].streams[0].transmittedWidth
196
- );
197
- this.localMQEStats.video.TX.resolutionHeight.push(
198
- lastMqa.videoTransmit[0].streams[0].transmittedHeight
199
- );
200
- this.localMQEStats.video.TX.requestedKeyFrame.push(
201
- lastMqa.videoTransmit[0].streams[0].requestedKeyFrames
202
- );
203
- this.localMQEStats.video.TX.receivedKeyFrame.push();
106
+ this.lastMqaDataSent = {};
107
+ this.lastEmittedStartStopEvent = {};
108
+ this.receiveSlotCallback = receiveSlotCallback;
109
+ this.successfulCandidatePair = {};
204
110
  }
205
111
 
112
+ /**
113
+ * Resets cumulative stats arrays.
114
+ *
115
+ * @public
116
+ * @memberof StatsAnalyzer
117
+ * @returns {void}
118
+ */
206
119
  resetStatsResults() {
207
- this.statsResults.audio.send.meanRemoteJitter = [];
208
- this.statsResults.video.send.meanRemoteJitter = [];
209
- this.statsResults.share.send.meanRemoteJitter = [];
210
-
211
- this.statsResults.audio.recv.meanRtpJitter = [];
212
-
213
- // TODO: currently no values are present
214
- this.statsResults.video.recv.meanRtpJitter = [];
215
- this.statsResults.share.recv.meanRtpJitter = [];
120
+ Object.keys(this.statsResults).forEach((mediaType) => {
121
+ if (mediaType.includes('recv')) {
122
+ this.statsResults[mediaType].recv.meanRtpJitter = [];
123
+ }
216
124
 
217
- // Reset the roundTripTime
218
- this.statsResults.audio.send.meanRoundTripTime = [];
219
- this.statsResults.video.send.meanRoundTripTime = [];
220
- this.statsResults.share.send.meanRoundTripTime = [];
125
+ if (mediaType.includes('send')) {
126
+ this.statsResults[mediaType].send.meanRemoteJitter = [];
127
+ this.statsResults[mediaType].send.meanRoundTripTime = [];
128
+ }
129
+ });
221
130
  }
222
131
 
223
132
  /**
@@ -233,86 +142,101 @@ export class StatsAnalyzer extends EventsScope {
233
142
  }
234
143
 
235
144
  /**
236
- * captures MQA data from peerconnection
145
+ * captures MQA data from media connection
237
146
  *
238
147
  * @public
239
148
  * @memberof StatsAnalyzer
240
149
  * @returns {void}
241
150
  */
242
- public sendMqaData() {
243
- const audioReceiver = mqaData.intervals[0].audioReceive[0];
244
- const audioSender = mqaData.intervals[0].audioTransmit[0];
245
- const videoReceiver = mqaData.intervals[0].videoReceive[0];
246
- const videoSender = mqaData.intervals[0].videoTransmit[0];
247
- const shareSender = mqaData.intervals[0].videoTransmit[1];
248
- const shareReceiver = mqaData.intervals[0].videoReceive[1];
249
-
250
- getAudioSenderMqa({
251
- audioSender,
252
- statsResults: this.statsResults,
253
- lastMqaDataSent: this.lastMqaDataSent,
254
- });
255
- getAudioReceiverMqa({
256
- audioReceiver,
257
- statsResults: this.statsResults,
258
- lastMqaDataSent: this.lastMqaDataSent,
259
- });
151
+ sendMqaData() {
152
+ const newMqa = cloneDeep(emptyMqaInterval);
260
153
 
261
- getVideoReceiverMqa({
262
- videoReceiver,
263
- statsResults: this.statsResults,
264
- lastMqaDataSent: this.lastMqaDataSent,
265
- });
266
- getVideoSenderMqa({
267
- videoSender,
268
- statsResults: this.statsResults,
269
- lastMqaDataSent: this.lastMqaDataSent,
270
- });
154
+ Object.keys(this.statsResults).forEach((mediaType) => {
155
+ if (!this.lastMqaDataSent[mediaType]) {
156
+ this.lastMqaDataSent[mediaType] = {};
157
+ }
271
158
 
272
- // Capture mqa for share scenario
159
+ if (!this.lastMqaDataSent[mediaType].send && mediaType.includes('-send')) {
160
+ this.lastMqaDataSent[mediaType].send = {};
161
+ }
273
162
 
274
- getVideoSenderMqa({
275
- videoSender: shareSender,
276
- statsResults: this.statsResults,
277
- lastMqaDataSent: this.lastMqaDataSent,
278
- isShareStream: true,
279
- });
163
+ if (!this.lastMqaDataSent[mediaType].recv && mediaType.includes('-recv')) {
164
+ this.lastMqaDataSent[mediaType].recv = {};
165
+ }
280
166
 
281
- getVideoReceiverMqa({
282
- videoReceiver: shareReceiver,
283
- statsResults: this.statsResults,
284
- lastMqaDataSent: this.lastMqaDataSent,
285
- isShareStream: true,
286
- });
287
- mqaData.intervals[0].intervalMetadata.peerReflexiveIP =
288
- this.statsResults.connectionType.local.ipAddress[0];
167
+ if (mediaType.includes('audio-send') || mediaType.includes('audio-share-send')) {
168
+ const audioSender = cloneDeep(emptyAudioTransmit);
289
169
 
290
- // Adding peripheral information
291
- mqaData.intervals[0].intervalMetadata.peripherals = [];
292
- mqaData.intervals[0].intervalMetadata.peripherals.push({
293
- information: _UNKNOWN_,
294
- name: MEDIA_DEVICES.SPEAKER,
295
- });
296
- mqaData.intervals[0].intervalMetadata.peripherals.push({
297
- information: this.peerConnection?.audioTransceiver?.sender?.track?.label || _UNKNOWN_,
298
- name: MEDIA_DEVICES.MICROPHONE,
299
- });
300
- mqaData.intervals[0].intervalMetadata.peripherals.push({
301
- information: this.peerConnection?.videoTransceiver?.sender?.track?.label || _UNKNOWN_,
302
- name: MEDIA_DEVICES.CAMERA,
170
+ getAudioSenderMqa({
171
+ audioSender,
172
+ statsResults: this.statsResults,
173
+ lastMqaDataSent: this.lastMqaDataSent,
174
+ mediaType,
175
+ });
176
+ newMqa.audioTransmit.push(audioSender);
177
+
178
+ this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
179
+ } else if (mediaType.includes('audio-recv') || mediaType.includes('audio-share-recv')) {
180
+ const audioReceiver = cloneDeep(emptyAudioReceive);
181
+
182
+ getAudioReceiverMqa({
183
+ audioReceiver,
184
+ statsResults: this.statsResults,
185
+ lastMqaDataSent: this.lastMqaDataSent,
186
+ mediaType,
187
+ });
188
+ newMqa.audioReceive.push(audioReceiver);
189
+
190
+ this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
191
+ } else if (mediaType.includes('video-send') || mediaType.includes('video-share-send')) {
192
+ const videoSender = cloneDeep(emptyVideoTransmit);
193
+
194
+ getVideoSenderMqa({
195
+ videoSender,
196
+ statsResults: this.statsResults,
197
+ lastMqaDataSent: this.lastMqaDataSent,
198
+ mediaType,
199
+ });
200
+ newMqa.videoTransmit.push(videoSender);
201
+
202
+ this.lastMqaDataSent[mediaType].send = cloneDeep(this.statsResults[mediaType].send);
203
+ } else if (mediaType.includes('video-recv') || mediaType.includes('video-share-recv')) {
204
+ const videoReceiver = cloneDeep(emptyVideoReceive);
205
+
206
+ getVideoReceiverMqa({
207
+ videoReceiver,
208
+ statsResults: this.statsResults,
209
+ lastMqaDataSent: this.lastMqaDataSent,
210
+ mediaType,
211
+ });
212
+ newMqa.videoReceive.push(videoReceiver);
213
+
214
+ this.lastMqaDataSent[mediaType].recv = cloneDeep(this.statsResults[mediaType].recv);
215
+ }
303
216
  });
304
217
 
305
- // @ts-ignore
306
- mqaData.networkType = this.statsResults.connectionType.local.networkType;
218
+ newMqa.intervalMetadata.peerReflexiveIP = this.statsResults.connectionType.local.ipAddress;
307
219
 
308
- this.mqaSentCount += 1;
220
+ // Adding peripheral information
221
+ newMqa.intervalMetadata.peripherals.push({information: _UNKNOWN_, name: MEDIA_DEVICES.SPEAKER});
222
+ if (this.statsResults['audio-send']) {
223
+ newMqa.intervalMetadata.peripherals.push({
224
+ information: this.statsResults['audio-send'].trackLabel || _UNKNOWN_,
225
+ name: MEDIA_DEVICES.MICROPHONE,
226
+ });
227
+ }
228
+ if (this.statsResults['video-send']) {
229
+ newMqa.intervalMetadata.peripherals.push({
230
+ information: this.statsResults['video-send'].trackLabel || _UNKNOWN_,
231
+ name: MEDIA_DEVICES.CAMERA,
232
+ });
233
+ }
309
234
 
310
- mqaData.intervals[0].intervalNumber = this.mqaSentCount;
235
+ newMqa.networkType = this.statsResults.connectionType.local.networkType;
311
236
 
312
- // DO Deep copy, for some reason it takes the reference all the time rather then old value set
313
- this.lastMqaDataSent = cloneDeep(this.statsResults);
237
+ this.mqaSentCount += 1;
314
238
 
315
- this.populateResults(mqaData.intervals[0]);
239
+ newMqa.intervalNumber = this.mqaSentCount;
316
240
 
317
241
  this.resetStatsResults();
318
242
 
@@ -323,23 +247,23 @@ export class StatsAnalyzer extends EventsScope {
323
247
  },
324
248
  EVENTS.MEDIA_QUALITY,
325
249
  {
326
- data: mqaData.intervals[0],
250
+ data: newMqa,
327
251
  // @ts-ignore
328
- networkType: mqaData.networkType,
252
+ networkType: newMqa.networkType,
329
253
  }
330
254
  );
331
255
  }
332
256
 
333
257
  /**
334
- * updated the peerconnection when changed
258
+ * updated the media connection when changed
335
259
  *
336
260
  * @private
337
- * @memberof updatePeerconnection
338
- * @param {PeerConnection} peerConnection
261
+ * @memberof StatsAnalyzer
262
+ * @param {RoapMediaConnection} mediaConnection
339
263
  * @returns {void}
340
264
  */
341
- updatePeerconnection(peerConnection: any) {
342
- this.peerConnection = peerConnection;
265
+ updateMediaConnection(mediaConnection: any) {
266
+ this.mediaConnection = mediaConnection;
343
267
  }
344
268
 
345
269
  /**
@@ -347,13 +271,13 @@ export class StatsAnalyzer extends EventsScope {
347
271
  *
348
272
  * @public
349
273
  * @memberof StatsAnalyzer
350
- * @param {PeerConnection} peerConnection
274
+ * @param {RoapMediaConnection} mediaConnection
351
275
  * @returns {Promise}
352
276
  */
353
- public startAnalyzer(peerConnection: any) {
277
+ public startAnalyzer(mediaConnection: any) {
354
278
  if (!this.statsStarted) {
355
279
  this.statsStarted = true;
356
- this.peerConnection = peerConnection;
280
+ this.mediaConnection = mediaConnection;
357
281
 
358
282
  return this.getStatsAndParse().then(() => {
359
283
  this.statsInterval = setInterval(() => {
@@ -393,7 +317,7 @@ export class StatsAnalyzer extends EventsScope {
393
317
  if (sendOneLastMqa) {
394
318
  return this.getStatsAndParse().then(() => {
395
319
  this.sendMqaData();
396
- this.peerConnection = null;
320
+ this.mediaConnection = null;
397
321
  });
398
322
  }
399
323
 
@@ -415,6 +339,17 @@ export class StatsAnalyzer extends EventsScope {
415
339
  return;
416
340
  }
417
341
 
342
+ // Generate empty stats results
343
+ if (!this.statsResults[type]) {
344
+ this.statsResults[type] = {};
345
+ }
346
+
347
+ if (isSender && !this.statsResults[type].send) {
348
+ this.statsResults[type].send = cloneDeep(emptySender);
349
+ } else if (!isSender && !this.statsResults[type].recv) {
350
+ this.statsResults[type].recv = cloneDeep(emptyReceiver);
351
+ }
352
+
418
353
  switch (getStatsResult.type) {
419
354
  case 'outbound-rtp':
420
355
  this.processOutboundRTPResult(getStatsResult, type);
@@ -424,8 +359,7 @@ export class StatsAnalyzer extends EventsScope {
424
359
  break;
425
360
  case 'remote-inbound-rtp':
426
361
  case 'remote-outbound-rtp':
427
- // @ts-ignore
428
- this.compareSentAndReceived(getStatsResult, type, isSender);
362
+ this.compareSentAndReceived(getStatsResult, type);
429
363
  break;
430
364
  case 'remotecandidate':
431
365
  case 'remote-candidate':
@@ -446,23 +380,34 @@ export class StatsAnalyzer extends EventsScope {
446
380
  /**
447
381
  * Filters the get stats results for types
448
382
  * @private
449
- * @param {Array} getStatsResults
383
+ * @param {Array} statsItem
450
384
  * @param {String} type
451
385
  * @param {boolean} isSender
452
386
  * @returns {void}
453
387
  */
454
- private filterAndParseGetStatsResults(
455
- getStatsResults: Array<any>,
456
- type: string,
457
- isSender: boolean
458
- ) {
388
+ filterAndParseGetStatsResults(statsItem: any, type: string, isSender: boolean) {
459
389
  const {types} = DEFAULT_GET_STATS_FILTER;
460
390
 
461
- getStatsResults.forEach((result) => {
391
+ // get the successful candidate pair before parsing stats.
392
+ statsItem.report.forEach((report) => {
393
+ if (report.type === 'candidate-pair' && report.state === 'succeeded') {
394
+ this.successfulCandidatePair = report;
395
+ }
396
+ });
397
+
398
+ statsItem.report.forEach((result) => {
462
399
  if (types.includes(result.type)) {
463
400
  this.parseGetStatsResult(result, type, isSender);
464
401
  }
465
402
  });
403
+
404
+ if (this.statsResults[type]) {
405
+ this.statsResults[type].direction = statsItem.currentDirection;
406
+ this.statsResults[type].trackLabel = statsItem.localTrackLabel;
407
+ this.statsResults[type].csi = statsItem.csi;
408
+ // reset the successful candidate pair.
409
+ this.successfulCandidatePair = {};
410
+ }
466
411
  }
467
412
 
468
413
  /**
@@ -476,7 +421,7 @@ export class StatsAnalyzer extends EventsScope {
476
421
  return;
477
422
  }
478
423
 
479
- if (type === STATS.AUDIO_CORRELATE) {
424
+ if (type.includes('audio-send')) {
480
425
  this.statsResults[type].send.audioLevel = result.audioLevel;
481
426
  this.statsResults[type].send.totalAudioEnergy = result.totalAudioEnergy;
482
427
  }
@@ -511,6 +456,10 @@ export class StatsAnalyzer extends EventsScope {
511
456
  // eslint-disable-next-line no-param-reassign
512
457
  if (currentValue === undefined) currentValue = 0;
513
458
 
459
+ if (!this.lastEmittedStartStopEvent[mediaType]) {
460
+ this.lastEmittedStartStopEvent[mediaType] = {};
461
+ }
462
+
514
463
  const lastEmittedEvent = isLocal
515
464
  ? this.lastEmittedStartStopEvent[mediaType].local
516
465
  : this.lastEmittedStartStopEvent[mediaType].remote;
@@ -519,7 +468,7 @@ export class StatsAnalyzer extends EventsScope {
519
468
 
520
469
  if (currentValue - previousValue > 0) {
521
470
  newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STARTED : EVENTS.REMOTE_MEDIA_STARTED;
522
- } else if (currentValue === previousValue && currentValue >= 0) {
471
+ } else if (currentValue === previousValue && currentValue > 0) {
523
472
  newEvent = isLocal ? EVENTS.LOCAL_MEDIA_STOPPED : EVENTS.REMOTE_MEDIA_STOPPED;
524
473
  }
525
474
 
@@ -551,21 +500,29 @@ export class StatsAnalyzer extends EventsScope {
551
500
  */
552
501
  private compareLastStatsResult() {
553
502
  if (this.lastStatsResults !== null && this.meetingMediaStatus) {
554
- // compare audio stats sent
555
- let mediaType = STATS.AUDIO_CORRELATE;
556
- let currentStats = null;
557
- let previousStats = null;
558
-
559
- if (this.meetingMediaStatus.expected.sendAudio) {
560
- currentStats = this.statsResults[mediaType].send;
561
- previousStats = this.lastStatsResults[mediaType].send;
503
+ const getCurrentStatsTotals = (keyPrefix: string, value: string): number =>
504
+ Object.keys(this.statsResults)
505
+ .filter((key) => key.startsWith(keyPrefix))
506
+ .reduce((prev, cur) => prev + (this.statsResults[cur]?.recv[value] || 0), 0);
507
+
508
+ const getPreviousStatsTotals = (keyPrefix: string, value: string): number =>
509
+ Object.keys(this.statsResults)
510
+ .filter((key) => key.startsWith(keyPrefix))
511
+ .reduce((prev, cur) => prev + (this.lastStatsResults[cur]?.recv[value] || 0), 0);
512
+
513
+ if (this.meetingMediaStatus.expected.sendAudio && this.lastStatsResults['audio-send']) {
514
+ // compare audio stats sent
515
+ // NOTE: relies on there being only one sender.
516
+ const currentStats = this.statsResults['audio-send'].send;
517
+ const previousStats = this.lastStatsResults['audio-send'].send;
562
518
 
563
519
  if (
564
520
  currentStats.totalPacketsSent === previousStats.totalPacketsSent ||
565
521
  currentStats.totalPacketsSent === 0
566
522
  ) {
567
523
  LoggerProxy.logger.info(
568
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets sent`
524
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets sent`,
525
+ currentStats.totalPacketsSent
569
526
  );
570
527
  } else {
571
528
  if (
@@ -573,19 +530,20 @@ export class StatsAnalyzer extends EventsScope {
573
530
  currentStats.totalAudioEnergy === 0
574
531
  ) {
575
532
  LoggerProxy.logger.info(
576
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} Energy present`
533
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio Energy present`,
534
+ currentStats.totalAudioEnergy
577
535
  );
578
536
  }
579
537
 
580
538
  if (currentStats.audioLevel === 0) {
581
539
  LoggerProxy.logger.info(
582
- `StatsAnalyzer:index#compareLastStatsResult --> ${mediaType} level is 0 for the user`
540
+ `StatsAnalyzer:index#compareLastStatsResult --> audio level is 0 for the user`
583
541
  );
584
542
  }
585
543
  }
586
544
 
587
545
  this.emitStartStopEvents(
588
- mediaType,
546
+ 'audio',
589
547
  previousStats.totalPacketsSent,
590
548
  currentStats.totalPacketsSent,
591
549
  true
@@ -594,266 +552,199 @@ export class StatsAnalyzer extends EventsScope {
594
552
 
595
553
  if (this.meetingMediaStatus.expected.receiveAudio) {
596
554
  // compare audio stats received
597
- currentStats = this.statsResults[mediaType].recv;
598
- previousStats = this.lastStatsResults[mediaType].recv;
555
+ const currentPacketsReceived = getCurrentStatsTotals('audio-recv', 'totalPacketsReceived');
556
+ const previousPacketsReceived = getPreviousStatsTotals(
557
+ 'audio-recv',
558
+ 'totalPacketsReceived'
559
+ );
560
+ const currentSamplesReceived = getCurrentStatsTotals('audio-recv', 'totalSamplesReceived');
561
+ const previousSamplesReceived = getPreviousStatsTotals(
562
+ 'audio-recv',
563
+ 'totalSamplesReceived'
564
+ );
599
565
 
600
- if (
601
- currentStats.totalPacketsReceived === previousStats.totalPacketsReceived ||
602
- currentStats.totalPacketsReceived === 0
603
- ) {
566
+ if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
604
567
  LoggerProxy.logger.info(
605
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets received`
568
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio RTP packets received`,
569
+ currentPacketsReceived
606
570
  );
607
571
  } else if (
608
- currentStats.totalSamplesReceived === previousStats.totalSamplesReceived ||
609
- currentStats.totalSamplesReceived === 0
572
+ currentSamplesReceived === previousSamplesReceived ||
573
+ currentSamplesReceived === 0
610
574
  ) {
611
575
  LoggerProxy.logger.info(
612
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} samples received`
576
+ `StatsAnalyzer:index#compareLastStatsResult --> No audio samples received`,
577
+ currentSamplesReceived
613
578
  );
614
579
  }
615
580
 
616
- this.emitStartStopEvents(
617
- mediaType,
618
- previousStats.totalPacketsReceived,
619
- currentStats.totalPacketsReceived,
620
- false
621
- );
581
+ this.emitStartStopEvents('audio', previousPacketsReceived, currentPacketsReceived, false);
622
582
  }
623
583
 
624
- mediaType = STATS.VIDEO_CORRELATE;
625
- if (this.meetingMediaStatus.expected.sendVideo) {
584
+ if (this.meetingMediaStatus.expected.sendVideo && this.lastStatsResults['video-send']) {
626
585
  // compare video stats sent
627
- currentStats = this.statsResults[mediaType].send;
628
- previousStats = this.lastStatsResults[mediaType].send;
586
+ const currentStats = this.statsResults['video-send'].send;
587
+ const previousStats = this.lastStatsResults['video-send'].send;
629
588
 
630
589
  if (
631
590
  currentStats.totalPacketsSent === previousStats.totalPacketsSent ||
632
591
  currentStats.totalPacketsSent === 0
633
592
  ) {
634
593
  LoggerProxy.logger.info(
635
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets sent`
594
+ `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets sent`,
595
+ currentStats.totalPacketsSent
636
596
  );
637
- } else if (this.lastEmittedStartStopEvent[mediaType].local !== EVENTS.LOCAL_MEDIA_STOPPED) {
597
+ } else {
638
598
  if (
639
599
  currentStats.framesEncoded === previousStats.framesEncoded ||
640
600
  currentStats.framesEncoded === 0
641
- ) {
642
- this.lastEmittedStartStopEvent[mediaType].local = EVENTS.NO_VIDEO_ENCODED;
643
- LoggerProxy.logger.info(
644
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} Frames Encoded`
645
- );
646
- this.emit(
647
- {
648
- file: 'statsAnalyzer',
649
- function: 'compareLastStatsResult',
650
- },
651
- EVENTS.NO_VIDEO_ENCODED,
652
- {
653
- mediaType,
654
- }
655
- );
656
- }
657
-
658
- if (
659
- this.statsResults.resolutions[mediaType].send.framesSent ===
660
- this.lastStatsResults.resolutions[mediaType].send.framesSent ||
661
- this.statsResults.resolutions[mediaType].send.framesSent === 0
662
601
  ) {
663
602
  LoggerProxy.logger.info(
664
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} Frames sent`
603
+ `StatsAnalyzer:index#compareLastStatsResult --> No video Frames Encoded`,
604
+ currentStats.framesEncoded
665
605
  );
666
606
  }
667
607
 
668
- // Video is encoded but frames are not sent
669
608
  if (
670
- currentStats.framesEncoded !== previousStats.framesEncoded &&
671
- (currentStats.framesSent === previousStats.framesSent || currentStats.framesSent === 0)
609
+ this.statsResults['video-send'].send.framesSent ===
610
+ this.lastStatsResults['video-send'].send.framesSent ||
611
+ this.statsResults['video-send'].send.framesSent === 0
672
612
  ) {
673
- this.lastEmittedStartStopEvent[mediaType].local = EVENTS.NO_FRAMES_SENT;
674
613
  LoggerProxy.logger.info(
675
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames sent even though frames are encoded`
676
- );
677
- this.emit(
678
- {
679
- file: 'statsAnalyzer',
680
- function: 'compareLastStatsResult',
681
- },
682
- EVENTS.NO_FRAMES_SENT,
683
- {
684
- mediaType,
685
- }
614
+ `StatsAnalyzer:index#compareLastStatsResult --> No video Frames sent`,
615
+ this.statsResults['video-send'].send.framesSent
686
616
  );
687
617
  }
688
618
  }
689
- this.emitStartStopEvents(
690
- mediaType,
691
- previousStats.framesSent,
692
- currentStats.framesSent,
693
- true
694
- );
619
+
620
+ this.emitStartStopEvents('video', previousStats.framesSent, currentStats.framesSent, true);
695
621
  }
696
622
 
697
623
  if (this.meetingMediaStatus.expected.receiveVideo) {
698
- // compare video stats reveived
699
-
700
- currentStats = this.statsResults[mediaType].recv;
701
- previousStats = this.lastStatsResults[mediaType].recv;
702
-
703
- if (
704
- currentStats.totalPacketsReceived === previousStats.totalPacketsReceived ||
705
- currentStats.totalPacketsReceived === 0
706
- ) {
624
+ // compare video stats received
625
+ const currentPacketsReceived = getCurrentStatsTotals('video-recv', 'totalPacketsReceived');
626
+ const previousPacketsReceived = getPreviousStatsTotals(
627
+ 'video-recv',
628
+ 'totalPacketsReceived'
629
+ );
630
+ const currentFramesReceived = getCurrentStatsTotals('video-recv', 'framesReceived');
631
+ const previousFramesReceived = getPreviousStatsTotals('video-recv', 'framesReceived');
632
+ const currentFramesDecoded = getCurrentStatsTotals('video-recv', 'framesDecoded');
633
+ const previousFramesDecoded = getPreviousStatsTotals('video-recv', 'framesDecoded');
634
+ const currentFramesDropped = getCurrentStatsTotals('video-recv', 'framesDropped');
635
+ const previousFramesDropped = getPreviousStatsTotals('video-recv', 'framesDropped');
636
+
637
+ if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
707
638
  LoggerProxy.logger.info(
708
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets received`
639
+ `StatsAnalyzer:index#compareLastStatsResult --> No video RTP packets received`,
640
+ currentPacketsReceived
709
641
  );
710
642
  } else {
711
- if (
712
- this.statsResults.resolutions[mediaType].recv.framesReceived ===
713
- this.lastStatsResults.resolutions[mediaType].recv.framesReceived ||
714
- this.statsResults.resolutions[mediaType].recv.framesReceived === 0
715
- ) {
643
+ if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {
716
644
  LoggerProxy.logger.info(
717
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames received`
645
+ `StatsAnalyzer:index#compareLastStatsResult --> No video frames received`,
646
+ currentFramesReceived
718
647
  );
719
648
  }
720
649
 
721
- if (
722
- this.statsResults[mediaType].recv.framesDecoded ===
723
- this.lastStatsResults[mediaType].recv.framesDecoded ||
724
- this.statsResults.resolutions[mediaType].send.framesDecoded === 0
725
- ) {
650
+ if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {
726
651
  LoggerProxy.logger.info(
727
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames decoded`
652
+ `StatsAnalyzer:index#compareLastStatsResult --> No video frames decoded`,
653
+ currentFramesDecoded
728
654
  );
729
655
  }
730
656
 
731
- if (
732
- this.statsResults.resolutions[mediaType].recv.framesDropped -
733
- this.lastStatsResults.resolutions[mediaType].recv.framesDropped >
734
- 10
735
- ) {
657
+ if (currentFramesDropped - previousFramesDropped > 10) {
736
658
  LoggerProxy.logger.info(
737
- `StatsAnalyzer:index#compareLastStatsResult --> ${mediaType} frames are getting dropped`
659
+ `StatsAnalyzer:index#compareLastStatsResult --> video frames are getting dropped`,
660
+ currentFramesDropped - previousFramesDropped
738
661
  );
739
662
  }
740
663
  }
741
664
 
742
- this.emitStartStopEvents(
743
- mediaType,
744
- previousStats.framesDecoded,
745
- currentStats.framesDecoded,
746
- false
747
- );
665
+ this.emitStartStopEvents('video', previousFramesDecoded, currentFramesDecoded, false);
748
666
  }
749
667
 
750
- mediaType = STATS.SHARE_CORRELATE;
751
- if (this.meetingMediaStatus.expected.sendShare) {
668
+ if (this.meetingMediaStatus.expected.sendShare && this.lastStatsResults['video-share-send']) {
752
669
  // compare share stats sent
753
670
 
754
- currentStats = this.statsResults[mediaType].send;
755
- previousStats = this.lastStatsResults[mediaType].send;
671
+ const currentStats = this.statsResults['video-share-send'].send;
672
+ const previousStats = this.lastStatsResults['video-share-send'].send;
756
673
 
757
674
  if (
758
675
  currentStats.totalPacketsSent === previousStats.totalPacketsSent ||
759
676
  currentStats.totalPacketsSent === 0
760
677
  ) {
761
678
  LoggerProxy.logger.info(
762
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets sent`
679
+ `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets sent`,
680
+ currentStats.totalPacketsSent
763
681
  );
764
- } else if (this.lastEmittedStartStopEvent[mediaType].local !== EVENTS.LOCAL_MEDIA_STOPPED) {
682
+ } else {
765
683
  if (
766
684
  currentStats.framesEncoded === previousStats.framesEncoded ||
767
685
  currentStats.framesEncoded === 0
768
686
  ) {
769
- this.lastEmittedStartStopEvent[mediaType].local = EVENTS.NO_VIDEO_ENCODED;
770
687
  LoggerProxy.logger.info(
771
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames getting encoded`
772
- );
773
- this.emit(
774
- {
775
- file: 'statsAnalyzer',
776
- function: 'compareLastStatsResult',
777
- },
778
- EVENTS.NO_VIDEO_ENCODED,
779
- {
780
- mediaType,
781
- }
688
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames getting encoded`,
689
+ currentStats.framesEncoded
782
690
  );
783
691
  }
784
692
 
785
693
  if (
786
- this.statsResults.resolutions[mediaType].send.framesSent ===
787
- this.lastStatsResults.resolutions[mediaType].send.framesSent ||
788
- this.statsResults.resolutions[mediaType].send.framesSent === 0
694
+ this.statsResults['video-share-send'].send.framesSent ===
695
+ this.lastStatsResults['video-share-send'].send.framesSent ||
696
+ this.statsResults['video-share-send'].send.framesSent === 0
789
697
  ) {
790
698
  LoggerProxy.logger.info(
791
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames sent`
792
- );
793
- }
794
-
795
- // Share video is encoded but frames are not sent
796
- if (
797
- currentStats.framesEncoded !== previousStats.framesEncoded &&
798
- (currentStats.framesSent === previousStats.framesSent || currentStats.framesSent === 0)
799
- ) {
800
- this.lastEmittedStartStopEvent[mediaType].local = EVENTS.NO_FRAMES_SENT;
801
- LoggerProxy.logger.info(
802
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} Frames sent even though frames are being encoded`
803
- );
804
- this.emit(
805
- {
806
- file: 'statsAnalyzer',
807
- function: 'compareLastStatsResult',
808
- },
809
- EVENTS.NO_FRAMES_SENT,
810
- {
811
- mediaType,
812
- }
699
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames sent`,
700
+ this.statsResults['video-share-send'].send.framesSent
813
701
  );
814
702
  }
815
703
  }
704
+ }
816
705
 
706
+ if (this.meetingMediaStatus.expected.sendShare) {
817
707
  // TODO:need to check receive share value
818
- // compare share stats reveived
819
- currentStats = this.statsResults[mediaType].recv;
820
- previousStats = this.lastStatsResults[mediaType].recv;
821
-
822
- if (
823
- currentStats.totalPacketsReceived === previousStats.totalPacketsReceived ||
824
- currentStats.totalPacketsSent === 0
825
- ) {
708
+ // compare share stats received
709
+ const currentPacketsReceived = getCurrentStatsTotals(
710
+ 'video-share-recv',
711
+ 'totalPacketsReceived'
712
+ );
713
+ const previousPacketsReceived = getPreviousStatsTotals(
714
+ 'video-share-recv',
715
+ 'totalPacketsReceived'
716
+ );
717
+ const currentFramesReceived = getCurrentStatsTotals('video-share-recv', 'framesReceived');
718
+ const previousFramesReceived = getPreviousStatsTotals('video-share-recv', 'framesReceived');
719
+ const currentFramesDecoded = getCurrentStatsTotals('video-share-recv', 'framesDecoded');
720
+ const previousFramesDecoded = getPreviousStatsTotals('video-share-recv', 'framesDecoded');
721
+ const currentFramesDropped = getCurrentStatsTotals('video-share-recv', 'framesDropped');
722
+ const previousFramesDropped = getPreviousStatsTotals('video-share-recv', 'framesDropped');
723
+
724
+ if (currentPacketsReceived === previousPacketsReceived || currentPacketsReceived === 0) {
826
725
  LoggerProxy.logger.info(
827
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} RTP packets received`
726
+ `StatsAnalyzer:index#compareLastStatsResult --> No share RTP packets received`,
727
+ currentPacketsReceived
828
728
  );
829
729
  } else {
830
- if (
831
- this.statsResults.resolutions[mediaType].recv.framesReceived ===
832
- this.lastStatsResults.resolutions[mediaType].recv.framesReceived ||
833
- this.statsResults.resolutions[mediaType].recv.framesReceived === 0
834
- ) {
730
+ if (currentFramesReceived === previousFramesReceived || currentFramesReceived === 0) {
835
731
  LoggerProxy.logger.info(
836
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames received`
732
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames received`,
733
+ currentFramesReceived
837
734
  );
838
735
  }
839
736
 
840
- if (
841
- this.statsResults[mediaType].recv.framesDecoded ===
842
- this.lastStatsResults[mediaType].recv.framesDecoded ||
843
- this.statsResults.resolutions[mediaType].send.framesDecoded === 0
844
- ) {
737
+ if (currentFramesDecoded === previousFramesDecoded || currentFramesDecoded === 0) {
845
738
  LoggerProxy.logger.info(
846
- `StatsAnalyzer:index#compareLastStatsResult --> No ${mediaType} frames decoded`
739
+ `StatsAnalyzer:index#compareLastStatsResult --> No share frames decoded`,
740
+ currentFramesDecoded
847
741
  );
848
742
  }
849
743
 
850
- if (
851
- this.statsResults.resolutions[mediaType].recv.framesDropped -
852
- this.lastStatsResults.resolutions[mediaType].recv.framesDropped >
853
- 10
854
- ) {
744
+ if (currentFramesDropped - previousFramesDropped > 10) {
855
745
  LoggerProxy.logger.info(
856
- `StatsAnalyzer:index#compareLastStatsResult --> ${mediaType} frames are getting dropped`
746
+ `StatsAnalyzer:index#compareLastStatsResult --> share frames are getting dropped`,
747
+ currentFramesDropped - previousFramesDropped
857
748
  );
858
749
  }
859
750
  }
@@ -873,13 +764,16 @@ export class StatsAnalyzer extends EventsScope {
873
764
  * @returns {Promise}
874
765
  */
875
766
  private getStatsAndParse() {
876
- if (!this.peerConnection) {
767
+ if (!this.mediaConnection) {
877
768
  return Promise.resolve();
878
769
  }
879
770
 
880
- if (this.peerConnection && this.peerConnection.connectionState === CONNECTION_STATE.FAILED) {
771
+ if (
772
+ this.mediaConnection &&
773
+ this.mediaConnection.getConnectionState() === ConnectionState.Failed
774
+ ) {
881
775
  LoggerProxy.logger.trace(
882
- 'StatsAnalyzer:index#getStatsAndParse --> PeerConnection is in failed state'
776
+ 'StatsAnalyzer:index#getStatsAndParse --> media connection is in failed state'
883
777
  );
884
778
 
885
779
  return Promise.resolve();
@@ -887,43 +781,49 @@ export class StatsAnalyzer extends EventsScope {
887
781
 
888
782
  LoggerProxy.logger.trace('StatsAnalyzer:index#getStatsAndParse --> Collecting Stats');
889
783
 
890
- return Promise.all([
891
- this.peerConnection.videoTransceiver.sender.getStats().then((res) => {
892
- this.filterAndParseGetStatsResults(res, STATS.VIDEO_CORRELATE, true);
893
- }),
894
-
895
- this.peerConnection.videoTransceiver.receiver.getStats().then((res) => {
896
- this.filterAndParseGetStatsResults(res, STATS.VIDEO_CORRELATE, false);
897
- }),
898
-
899
- this.peerConnection.audioTransceiver.sender.getStats().then((res) => {
900
- this.filterAndParseGetStatsResults(res, STATS.AUDIO_CORRELATE, true);
901
- }),
902
-
903
- this.peerConnection.audioTransceiver.receiver.getStats().then((res) => {
904
- this.filterAndParseGetStatsResults(res, STATS.AUDIO_CORRELATE, false);
905
- }),
906
-
907
- // TODO: add checks for screen share
908
- this.peerConnection.shareTransceiver.sender.getStats().then((res) => {
909
- this.filterAndParseGetStatsResults(res, STATS.SHARE_CORRELATE, true);
910
- }),
911
-
912
- this.peerConnection.shareTransceiver.receiver.getStats().then((res) => {
913
- this.filterAndParseGetStatsResults(res, STATS.SHARE_CORRELATE, false);
914
- }),
915
- ]).then(() => {
916
- this.statsResults[STATS.AUDIO_CORRELATE].direction =
917
- this.peerConnection.audioTransceiver.currentDirection;
918
- this.statsResults[STATS.VIDEO_CORRELATE].direction =
919
- this.peerConnection.videoTransceiver.currentDirection;
920
- this.statsResults[STATS.SHARE_CORRELATE].direction =
921
- this.peerConnection.shareTransceiver.currentDirection;
922
-
923
- // Process Stats results every 5 seconds
784
+ return this.mediaConnection.getTransceiverStats().then((transceiverStats) => {
785
+ transceiverStats.video.receivers.forEach((receiver, i) =>
786
+ this.filterAndParseGetStatsResults(receiver, `video-recv-${i}`, false)
787
+ );
788
+ transceiverStats.audio.receivers.forEach((receiver, i) =>
789
+ this.filterAndParseGetStatsResults(receiver, `audio-recv-${i}`, false)
790
+ );
791
+ transceiverStats.screenShareVideo.receivers.forEach((receiver, i) =>
792
+ this.filterAndParseGetStatsResults(receiver, `video-share-recv-${i}`, false)
793
+ );
794
+ transceiverStats.screenShareAudio.receivers.forEach((receiver, i) =>
795
+ this.filterAndParseGetStatsResults(receiver, `audio-share-recv-${i}`, false)
796
+ );
797
+
798
+ transceiverStats.video.senders.forEach((sender, i) => {
799
+ if (i > 0) {
800
+ throw new Error('Stats Analyzer does not support multiple senders.');
801
+ }
802
+ this.filterAndParseGetStatsResults(sender, 'video-send', true);
803
+ });
804
+ transceiverStats.audio.senders.forEach((sender, i) => {
805
+ if (i > 0) {
806
+ throw new Error('Stats Analyzer does not support multiple senders.');
807
+ }
808
+ this.filterAndParseGetStatsResults(sender, 'audio-send', true);
809
+ });
810
+ transceiverStats.screenShareVideo.senders.forEach((sender, i) => {
811
+ if (i > 0) {
812
+ throw new Error('Stats Analyzer does not support multiple senders.');
813
+ }
814
+ this.filterAndParseGetStatsResults(sender, 'video-share-send', true);
815
+ });
816
+ transceiverStats.screenShareAudio.senders.forEach((sender, i) => {
817
+ if (i > 0) {
818
+ throw new Error('Stats Analyzer does not support multiple senders.');
819
+ }
820
+ this.filterAndParseGetStatsResults(sender, 'audio-share-send', true);
821
+ });
822
+
924
823
  this.compareLastStatsResult();
925
824
 
926
825
  // Save the last results to compare with the current
826
+ // DO Deep copy, for some reason it takes the reference all the time rather then old value set
927
827
  this.lastStatsResults = JSON.parse(JSON.stringify(this.statsResults));
928
828
 
929
829
  LoggerProxy.logger.trace(
@@ -936,51 +836,27 @@ export class StatsAnalyzer extends EventsScope {
936
836
  * Processes OutboundRTP stats result and stores
937
837
  * @private
938
838
  * @param {*} result
939
- * @param {*} type
839
+ * @param {*} mediaType
940
840
  * @returns {void}
941
841
  */
942
- private processOutboundRTPResult(result: any, type: any) {
943
- const mediaType = type || STATS.AUDIO_CORRELATE;
842
+ private processOutboundRTPResult(result: any, mediaType: any) {
944
843
  const sendrecvType = STATS.SEND_DIRECTION;
945
844
 
946
- this.processTrackResult(result, type, sendrecvType);
947
845
  if (result.bytesSent) {
948
- let kilobytes = 0;
846
+ const kilobytes = 0;
949
847
 
950
- if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesSent) {
951
- this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;
952
- }
953
- if (!this.statsResults.internal[mediaType][sendrecvType].framesEncoded) {
954
- this.statsResults.internal[mediaType][sendrecvType].framesEncoded = result.framesEncoded;
955
- }
956
- if (!this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded) {
957
- this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded =
958
- result.keyFramesEncoded;
848
+ if (result.frameWidth && result.frameHeight) {
849
+ this.statsResults[mediaType][sendrecvType].width = result.frameWidth;
850
+ this.statsResults[mediaType][sendrecvType].height = result.frameHeight;
851
+ this.statsResults[mediaType][sendrecvType].framesSent = result.framesSent;
852
+ this.statsResults[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;
959
853
  }
960
854
 
961
- const bytes =
962
- result.bytesSent - this.statsResults.internal[mediaType][sendrecvType].prevBytesSent;
963
-
964
- this.statsResults.internal[mediaType][sendrecvType].prevBytesSent = result.bytesSent;
965
-
966
- kilobytes = bytes / 1024;
967
-
968
855
  this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
969
- this.statsResults[mediaType].bytesSent = kilobytes;
970
- this.statsResults[mediaType][sendrecvType].framesEncoded =
971
- result.framesEncoded - this.statsResults.internal[mediaType][sendrecvType].framesEncoded;
972
- this.statsResults[mediaType][sendrecvType].keyFramesEncoded =
973
- result.keyFramesEncoded -
974
- this.statsResults.internal[mediaType][sendrecvType].keyFramesEncoded;
975
- this.statsResults.internal[mediaType].outboundRtpId = result.id;
976
-
977
- if (!this.statsResults.internal[mediaType][sendrecvType].packetsSent) {
978
- this.statsResults.internal[mediaType][sendrecvType].packetsSent = result.packetsSent;
979
- }
980
856
 
981
- this.statsResults[mediaType][sendrecvType].packetsSent =
982
- result.packetsSent - this.statsResults.internal[mediaType][sendrecvType].packetsSent;
983
- this.statsResults.internal[mediaType][sendrecvType].packetsSent = result.packetsSent;
857
+ this.statsResults[mediaType][sendrecvType].framesEncoded = result.framesEncoded;
858
+ this.statsResults[mediaType][sendrecvType].keyFramesEncoded = result.keyFramesEncoded;
859
+ this.statsResults[mediaType][sendrecvType].packetsSent = result.packetsSent;
984
860
 
985
861
  // Data saved to send MQA metrics
986
862
 
@@ -1010,81 +886,58 @@ export class StatsAnalyzer extends EventsScope {
1010
886
  * Processes InboundRTP stats result and stores
1011
887
  * @private
1012
888
  * @param {*} result
1013
- * @param {*} type
889
+ * @param {*} mediaType
1014
890
  * @returns {void}
1015
891
  */
1016
- private processInboundRTPResult(result: any, type: any) {
1017
- const mediaType = type || STATS.AUDIO_CORRELATE;
892
+ private processInboundRTPResult(result: any, mediaType: any) {
1018
893
  const sendrecvType = STATS.RECEIVE_DIRECTION;
1019
894
 
1020
- this.processTrackResult(result, type, sendrecvType);
1021
895
  if (result.bytesReceived) {
1022
896
  let kilobytes = 0;
1023
-
1024
- if (!this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived) {
1025
- this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived =
1026
- result.bytesReceived;
1027
- }
1028
-
1029
- if (!this.statsResults.internal[mediaType][sendrecvType].pliCount) {
1030
- this.statsResults.internal[mediaType][sendrecvType].pliCount = result.pliCount;
1031
- }
1032
-
1033
- if (!this.statsResults.internal[mediaType][sendrecvType].packetsLost) {
1034
- this.statsResults.internal[mediaType][sendrecvType].packetsLost = result.packetsLost;
1035
- }
1036
-
1037
- if (!this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived) {
1038
- this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived =
1039
- result.packetsReceived;
1040
- }
1041
-
1042
- if (!this.statsResults.internal[mediaType][sendrecvType].lastPacketReceivedTimestamp) {
1043
- this.statsResults.internal[mediaType][sendrecvType].lastPacketReceivedTimestamp =
1044
- result.lastPacketReceivedTimestamp;
897
+ const receiveSlot = this.receiveSlotCallback(result.ssrc);
898
+ const idAndCsi = receiveSlot
899
+ ? `id: "${receiveSlot.id || ''}"${receiveSlot.csi ? ` and csi: ${receiveSlot.csi}` : ''}`
900
+ : '';
901
+
902
+ if (result.frameWidth && result.frameHeight) {
903
+ this.statsResults[mediaType][sendrecvType].width = result.frameWidth;
904
+ this.statsResults[mediaType][sendrecvType].height = result.frameHeight;
905
+ this.statsResults[mediaType][sendrecvType].framesReceived = result.framesReceived;
1045
906
  }
1046
907
 
1047
908
  const bytes =
1048
- result.bytesReceived -
1049
- this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived;
1050
-
1051
- this.statsResults.internal[mediaType][sendrecvType].prevBytesReceived = result.bytesReceived;
909
+ result.bytesReceived - this.statsResults[mediaType][sendrecvType].totalBytesReceived;
1052
910
 
1053
911
  kilobytes = bytes / 1024;
1054
912
  this.statsResults[mediaType][sendrecvType].availableBandwidth = kilobytes.toFixed(1);
1055
- this.statsResults[mediaType].bytesReceived = kilobytes.toFixed(1);
1056
-
1057
- this.statsResults[mediaType][sendrecvType].pliCount =
1058
- result.pliCount - this.statsResults.internal[mediaType][sendrecvType].pliCount;
1059
- this.statsResults[mediaType][sendrecvType].currentPacketsLost =
1060
- result.packetsLost - this.statsResults.internal[mediaType][sendrecvType].packetsLost;
1061
- if (this.statsResults[mediaType][sendrecvType].currentPacketsLost < 0) {
1062
- this.statsResults[mediaType][sendrecvType].currentPacketsLost = 0;
913
+
914
+ let currentPacketsLost =
915
+ result.packetsLost - this.statsResults[mediaType][sendrecvType].totalPacketsLost;
916
+ if (currentPacketsLost < 0) {
917
+ currentPacketsLost = 0;
1063
918
  }
1064
919
 
1065
- this.statsResults[mediaType][sendrecvType].packetsReceived =
1066
- result.packetsReceived -
1067
- this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived;
1068
- this.statsResults.internal[mediaType][sendrecvType].totalPacketsReceived =
1069
- result.packetsReceived;
920
+ const currentPacketsReceived =
921
+ result.packetsReceived - this.statsResults[mediaType][sendrecvType].totalPacketsReceived;
922
+ this.statsResults[mediaType][sendrecvType].totalPacketsReceived = result.packetsReceived;
1070
923
 
1071
- if (this.statsResults[mediaType][sendrecvType].packetsReceived === 0) {
1072
- LoggerProxy.logger.info(
1073
- `StatsAnalyzer:index#processInboundRTPResult --> No packets received for ${mediaType} `,
1074
- this.statsResults[mediaType][sendrecvType].packetsReceived
1075
- );
924
+ if (currentPacketsReceived === 0) {
925
+ if (receiveSlot) {
926
+ LoggerProxy.logger.info(
927
+ `StatsAnalyzer:index#processInboundRTPResult --> No packets received for receive slot ${idAndCsi}`,
928
+ currentPacketsReceived
929
+ );
930
+ }
1076
931
  }
1077
932
 
1078
933
  // Check the over all packet Lost ratio
1079
934
  this.statsResults[mediaType][sendrecvType].currentPacketLossRatio =
1080
- this.statsResults[mediaType][sendrecvType].currentPacketsLost > 0
1081
- ? this.statsResults[mediaType][sendrecvType].currentPacketsLost /
1082
- (this.statsResults[mediaType][sendrecvType].packetsReceived +
1083
- this.statsResults[mediaType][sendrecvType].currentPacketsLost)
935
+ currentPacketsLost > 0
936
+ ? currentPacketsLost / (currentPacketsReceived + currentPacketsLost)
1084
937
  : 0;
1085
938
  if (this.statsResults[mediaType][sendrecvType].currentPacketLossRatio > 3) {
1086
939
  LoggerProxy.logger.info(
1087
- 'StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver ',
940
+ `StatsAnalyzer:index#processInboundRTPResult --> Packets getting lost from the receiver with slot ${idAndCsi}`,
1088
941
  this.statsResults[mediaType][sendrecvType].currentPacketLossRatio
1089
942
  );
1090
943
  }
@@ -1144,126 +997,48 @@ export class StatsAnalyzer extends EventsScope {
1144
997
  if (!result || !result.id) {
1145
998
  return;
1146
999
  }
1147
- const RemoteCandidateType = {};
1148
- const RemoteTransport = {};
1149
- const RemoteIpAddress = {};
1150
- const RemoteNetworkType = {};
1151
-
1152
- if (!result.id) return;
1153
-
1154
- const sendRecvType = isSender ? STATS.SEND_DIRECTION : STATS.RECEIVE_DIRECTION;
1155
- const ipType = isRemote ? STATS.REMOTE : STATS.LOCAL;
1156
-
1157
- if (!RemoteCandidateType[result.id]) {
1158
- RemoteCandidateType[result.id] = [];
1159
- }
1160
1000
 
1161
- if (!RemoteTransport[result.id]) {
1162
- RemoteTransport[result.id] = [];
1163
- }
1164
-
1165
- if (!RemoteIpAddress[result.id]) {
1166
- RemoteIpAddress[result.id] = [];
1167
- }
1168
- if (!RemoteNetworkType[result.id]) {
1169
- RemoteNetworkType[result.id] = [];
1170
- }
1171
-
1172
- if (
1173
- result.candidateType &&
1174
- RemoteCandidateType[result.id].indexOf(result.candidateType) === -1
1175
- ) {
1176
- RemoteCandidateType[result.id].push(result.candidateType);
1001
+ // We only care about the successful local candidate
1002
+ if (this.successfulCandidatePair?.localCandidateId !== result.id) {
1003
+ return;
1177
1004
  }
1178
1005
 
1179
- if (result.protocol && RemoteTransport[result.id].indexOf(result.protocol) === -1) {
1180
- RemoteTransport[result.id].push(result.protocol.toUpperCase());
1006
+ let transport;
1007
+ if (result.relayProtocol) {
1008
+ transport = result.relayProtocol.toUpperCase();
1009
+ } else if (result.protocol) {
1010
+ transport = result.protocol.toUpperCase();
1181
1011
  }
1182
1012
 
1183
- if (
1184
- result.ip &&
1185
- RemoteIpAddress[result.id].indexOf(`${result.ip}:${result.portNumber}`) === -1
1186
- ) {
1187
- RemoteIpAddress[result.id].push(`${result.ip}`); // TODO: Add ports
1188
- }
1013
+ const sendRecvType = isSender ? STATS.SEND_DIRECTION : STATS.RECEIVE_DIRECTION;
1014
+ const ipType = isRemote ? STATS.REMOTE : STATS.LOCAL;
1189
1015
 
1190
- if (result.networkType && RemoteNetworkType[result.id].indexOf(result.networkType) === -1) {
1191
- RemoteNetworkType[result.id].push(result.networkType);
1016
+ if (!this.statsResults.candidates) {
1017
+ this.statsResults.candidates = {};
1192
1018
  }
1193
1019
 
1194
- this.statsResults.internal.candidates[result.id] = {
1195
- candidateType: RemoteCandidateType[result.id],
1196
- ipAddress: RemoteIpAddress[result.id],
1020
+ this.statsResults.candidates[result.id] = {
1021
+ candidateType: result.candidateType,
1022
+ ipAddress: result.ip, // TODO: add ports
1197
1023
  portNumber: result.port,
1198
- networkType: RemoteNetworkType[result.id],
1024
+ networkType: result.networkType,
1199
1025
  priority: result.priority,
1200
- transport: RemoteTransport[result.id],
1026
+ transport,
1201
1027
  timestamp: result.time,
1202
1028
  id: result.id,
1203
1029
  type: result.type,
1204
1030
  };
1205
1031
 
1206
- this.statsResults.connectionType[ipType].candidateType = RemoteCandidateType[result.id];
1207
- this.statsResults.connectionType[ipType].ipAddress = RemoteIpAddress[result.id];
1032
+ this.statsResults.connectionType[ipType].candidateType = result.candidateType;
1033
+ this.statsResults.connectionType[ipType].ipAddress = result.ipAddress;
1208
1034
 
1209
1035
  this.statsResults.connectionType[ipType].networkType =
1210
- RemoteNetworkType[result.id][0] === NETWORK_TYPE.VPN
1211
- ? NETWORK_TYPE.UNKNOWN
1212
- : RemoteNetworkType[result.id][0];
1213
- this.statsResults.connectionType[ipType].transport = RemoteTransport[result.id];
1036
+ result.networkType === NETWORK_TYPE.VPN ? NETWORK_TYPE.UNKNOWN : result.networkType;
1037
+ this.statsResults.connectionType[ipType].transport = transport;
1214
1038
 
1215
1039
  this.statsResults[type][sendRecvType].totalRoundTripTime = result.totalRoundTripTime;
1216
1040
  };
1217
1041
 
1218
- /**
1219
- * Process Track results
1220
- *
1221
- * @private
1222
- * @param {*} result
1223
- * @param {*} mediaType
1224
- * @param {*} sendrecvType
1225
- * @returns {void}
1226
- * @memberof StatsAnalyzer
1227
- */
1228
- private processTrackResult(result: any, mediaType: any, sendrecvType: any) {
1229
- if (!result || mediaType === STATS.AUDIO_CORRELATE) {
1230
- return;
1231
- }
1232
- if (result.type !== 'inbound-rtp' && result.type !== 'outbound-rtp') {
1233
- return;
1234
- }
1235
- if (result.frameWidth && result.frameHeight) {
1236
- this.statsResults.resolutions[mediaType][sendrecvType].width = result.frameWidth;
1237
- this.statsResults.resolutions[mediaType][sendrecvType].height = result.frameHeight;
1238
- }
1239
-
1240
- if (sendrecvType === STATS.RECEIVE_DIRECTION) {
1241
- this.statsResults.resolutions[mediaType][sendrecvType].framesReceived = result.framesReceived;
1242
- this.statsResults.resolutions[mediaType][sendrecvType].framesDecoded = result.framesDecoded;
1243
- this.statsResults.resolutions[mediaType][sendrecvType].framesDropped = result.framesDropped;
1244
- } else if (sendrecvType === STATS.SEND_DIRECTION) {
1245
- this.statsResults.resolutions[mediaType][sendrecvType].framesSent = result.framesSent;
1246
- this.statsResults.resolutions[mediaType][sendrecvType].hugeFramesSent = result.hugeFramesSent;
1247
- }
1248
-
1249
- if (result.trackIdentifier && mediaType !== STATS.AUDIO_CORRELATE) {
1250
- this.statsResults.resolutions[mediaType][sendrecvType].trackIdentifier =
1251
- result.trackIdentifier;
1252
-
1253
- const jitterBufferDelay = result && result.jitterBufferDelay;
1254
- const jitterBufferEmittedCount = result && result.jitterBufferEmittedCount;
1255
-
1256
- this.statsResults.resolutions[mediaType][sendrecvType].avgJitterDelay =
1257
- jitterBufferEmittedCount && +jitterBufferDelay / +jitterBufferEmittedCount;
1258
-
1259
- // Used to calculate the jitter
1260
- this.statsResults.resolutions[mediaType][sendrecvType].jitterBufferDelay =
1261
- result.jitterBufferDelay;
1262
- this.statsResults.resolutions[mediaType][sendrecvType].jitterBufferEmittedCount =
1263
- result.jitterBufferEmittedCount;
1264
- }
1265
- }
1266
-
1267
1042
  /**
1268
1043
  *
1269
1044
  * @private
@@ -1272,21 +1047,17 @@ export class StatsAnalyzer extends EventsScope {
1272
1047
  * @returns {void}
1273
1048
  * @memberof StatsAnalyzer
1274
1049
  */
1275
- private compareSentAndReceived(result: any, type: any) {
1276
- if (!type) {
1050
+ compareSentAndReceived(result, type) {
1051
+ // Don't compare on transceivers without a sender.
1052
+ if (!type || !this.statsResults[type].send) {
1277
1053
  return;
1278
1054
  }
1279
1055
 
1280
1056
  const mediaType = type;
1281
1057
 
1282
- if (!this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver) {
1283
- this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
1284
- }
1285
-
1286
1058
  const currentPacketLoss =
1287
- result.packetsLost - this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver;
1059
+ result.packetsLost - this.statsResults[mediaType].send.totalPacketsLostOnReceiver;
1288
1060
 
1289
- this.statsResults.internal[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
1290
1061
  this.statsResults[mediaType].send.packetsLostOnReceiver = currentPacketLoss;
1291
1062
  this.statsResults[mediaType].send.totalPacketsLostOnReceiver = result.packetsLost;
1292
1063