@webex/plugin-meetings 3.0.0-beta.0 → 3.0.0-beta.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 (274) hide show
  1. package/dist/common/browser-detection.js.map +1 -1
  2. package/dist/common/collection.js.map +1 -1
  3. package/dist/common/config.js.map +1 -1
  4. package/dist/common/errors/captcha-error.js +7 -0
  5. package/dist/common/errors/captcha-error.js.map +1 -1
  6. package/dist/common/errors/intent-to-join.js +8 -0
  7. package/dist/common/errors/intent-to-join.js.map +1 -1
  8. package/dist/common/errors/join-meeting.js +8 -0
  9. package/dist/common/errors/join-meeting.js.map +1 -1
  10. package/dist/common/errors/media.js +7 -0
  11. package/dist/common/errors/media.js.map +1 -1
  12. package/dist/common/errors/parameter.js.map +1 -1
  13. package/dist/common/errors/password-error.js +7 -0
  14. package/dist/common/errors/password-error.js.map +1 -1
  15. package/dist/common/errors/permission.js +7 -0
  16. package/dist/common/errors/permission.js.map +1 -1
  17. package/dist/common/errors/reconnection-in-progress.js.map +1 -1
  18. package/dist/common/errors/reconnection.js +7 -0
  19. package/dist/common/errors/reconnection.js.map +1 -1
  20. package/dist/common/errors/stats.js +7 -0
  21. package/dist/common/errors/stats.js.map +1 -1
  22. package/dist/common/errors/webex-errors.js +5 -29
  23. package/dist/common/errors/webex-errors.js.map +1 -1
  24. package/dist/common/errors/webex-meetings-error.js +5 -2
  25. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  26. package/dist/common/events/events-scope.js.map +1 -1
  27. package/dist/common/events/events.js.map +1 -1
  28. package/dist/common/events/trigger-proxy.js.map +1 -1
  29. package/dist/common/events/util.js.map +1 -1
  30. package/dist/common/logs/logger-config.js.map +1 -1
  31. package/dist/common/logs/logger-proxy.js.map +1 -1
  32. package/dist/common/logs/request.js +3 -0
  33. package/dist/common/logs/request.js.map +1 -1
  34. package/dist/common/queue.js.map +1 -1
  35. package/dist/config.js +1 -0
  36. package/dist/config.js.map +1 -1
  37. package/dist/constants.js +15 -74
  38. package/dist/constants.js.map +1 -1
  39. package/dist/locus-info/controlsUtils.js.map +1 -1
  40. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  41. package/dist/locus-info/fullState.js.map +1 -1
  42. package/dist/locus-info/hostUtils.js.map +1 -1
  43. package/dist/locus-info/index.js +43 -5
  44. package/dist/locus-info/index.js.map +1 -1
  45. package/dist/locus-info/infoUtils.js +4 -0
  46. package/dist/locus-info/infoUtils.js.map +1 -1
  47. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  48. package/dist/locus-info/parser.js +12 -3
  49. package/dist/locus-info/parser.js.map +1 -1
  50. package/dist/locus-info/selfUtils.js.map +1 -1
  51. package/dist/media/index.js +71 -210
  52. package/dist/media/index.js.map +1 -1
  53. package/dist/media/internal-media-core-wrapper.js +22 -0
  54. package/dist/media/internal-media-core-wrapper.js.map +1 -0
  55. package/dist/media/properties.js +32 -25
  56. package/dist/media/properties.js.map +1 -1
  57. package/dist/media/util.js +0 -27
  58. package/dist/media/util.js.map +1 -1
  59. package/dist/mediaQualityMetrics/config.js.map +1 -1
  60. package/dist/meeting/effectsState.js +8 -1
  61. package/dist/meeting/effectsState.js.map +1 -1
  62. package/dist/meeting/index.js +1130 -647
  63. package/dist/meeting/index.js.map +1 -1
  64. package/dist/meeting/muteState.js +6 -0
  65. package/dist/meeting/muteState.js.map +1 -1
  66. package/dist/meeting/request.js +55 -24
  67. package/dist/meeting/request.js.map +1 -1
  68. package/dist/meeting/state.js.map +1 -1
  69. package/dist/meeting/util.js +5 -44
  70. package/dist/meeting/util.js.map +1 -1
  71. package/dist/meeting-info/collection.js +4 -1
  72. package/dist/meeting-info/collection.js.map +1 -1
  73. package/dist/meeting-info/index.js +5 -0
  74. package/dist/meeting-info/index.js.map +1 -1
  75. package/dist/meeting-info/meeting-info-v2.js +14 -2
  76. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  77. package/dist/meeting-info/request.js +3 -0
  78. package/dist/meeting-info/request.js.map +1 -1
  79. package/dist/meeting-info/util.js.map +1 -1
  80. package/dist/meeting-info/utilv2.js.map +1 -1
  81. package/dist/meetings/collection.js +4 -1
  82. package/dist/meetings/collection.js.map +1 -1
  83. package/dist/meetings/index.js +136 -25
  84. package/dist/meetings/index.js.map +1 -1
  85. package/dist/meetings/request.js +4 -0
  86. package/dist/meetings/request.js.map +1 -1
  87. package/dist/meetings/util.js +24 -1
  88. package/dist/meetings/util.js.map +1 -1
  89. package/dist/member/index.js +30 -7
  90. package/dist/member/index.js.map +1 -1
  91. package/dist/member/util.js +2 -1
  92. package/dist/member/util.js.map +1 -1
  93. package/dist/members/collection.js +1 -0
  94. package/dist/members/collection.js.map +1 -1
  95. package/dist/members/index.js +82 -1
  96. package/dist/members/index.js.map +1 -1
  97. package/dist/members/request.js +19 -9
  98. package/dist/members/request.js.map +1 -1
  99. package/dist/members/util.js.map +1 -1
  100. package/dist/metrics/config.js.map +1 -1
  101. package/dist/metrics/constants.js.map +1 -1
  102. package/dist/metrics/index.js +8 -0
  103. package/dist/metrics/index.js.map +1 -1
  104. package/dist/multistream/mediaRequestManager.js +133 -0
  105. package/dist/multistream/mediaRequestManager.js.map +1 -0
  106. package/dist/multistream/multistreamMedia.js +116 -0
  107. package/dist/multistream/multistreamMedia.js.map +1 -0
  108. package/dist/multistream/receiveSlot.js +209 -0
  109. package/dist/multistream/receiveSlot.js.map +1 -0
  110. package/dist/multistream/receiveSlotManager.js +195 -0
  111. package/dist/multistream/receiveSlotManager.js.map +1 -0
  112. package/dist/multistream/remoteMedia.js +289 -0
  113. package/dist/multistream/remoteMedia.js.map +1 -0
  114. package/dist/multistream/remoteMediaGroup.js +243 -0
  115. package/dist/multistream/remoteMediaGroup.js.map +1 -0
  116. package/dist/multistream/remoteMediaManager.js +1113 -0
  117. package/dist/multistream/remoteMediaManager.js.map +1 -0
  118. package/dist/networkQualityMonitor/index.js +10 -2
  119. package/dist/networkQualityMonitor/index.js.map +1 -1
  120. package/dist/personal-meeting-room/index.js +11 -0
  121. package/dist/personal-meeting-room/index.js.map +1 -1
  122. package/dist/personal-meeting-room/request.js +2 -1
  123. package/dist/personal-meeting-room/request.js.map +1 -1
  124. package/dist/personal-meeting-room/util.js.map +1 -1
  125. package/dist/reachability/index.js +17 -7
  126. package/dist/reachability/index.js.map +1 -1
  127. package/dist/reachability/request.js +1 -0
  128. package/dist/reachability/request.js.map +1 -1
  129. package/dist/reconnection-manager/index.js +130 -132
  130. package/dist/reconnection-manager/index.js.map +1 -1
  131. package/dist/roap/index.js +58 -231
  132. package/dist/roap/index.js.map +1 -1
  133. package/dist/roap/request.js +7 -116
  134. package/dist/roap/request.js.map +1 -1
  135. package/dist/roap/turnDiscovery.js +20 -6
  136. package/dist/roap/turnDiscovery.js.map +1 -1
  137. package/dist/statsAnalyzer/global.js +2 -0
  138. package/dist/statsAnalyzer/global.js.map +1 -1
  139. package/dist/statsAnalyzer/index.js +58 -37
  140. package/dist/statsAnalyzer/index.js.map +1 -1
  141. package/dist/statsAnalyzer/mqaUtil.js +9 -3
  142. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  143. package/dist/transcription/index.js +10 -3
  144. package/dist/transcription/index.js.map +1 -1
  145. package/package.json +21 -20
  146. package/src/common/{browser-detection.js → browser-detection.ts} +1 -1
  147. package/src/common/collection.ts +6 -6
  148. package/src/common/{config.js → config.ts} +1 -1
  149. package/src/common/errors/{captcha-error.js → captcha-error.ts} +5 -1
  150. package/src/common/errors/{intent-to-join.js → intent-to-join.ts} +6 -1
  151. package/src/common/errors/{join-meeting.js → join-meeting.ts} +6 -1
  152. package/src/common/errors/{media.js → media.ts} +5 -1
  153. package/src/common/errors/parameter.ts +3 -2
  154. package/src/common/errors/{password-error.js → password-error.ts} +5 -1
  155. package/src/common/errors/{permission.js → permission.ts} +5 -1
  156. package/src/common/errors/{reconnection-in-progress.js → reconnection-in-progress.ts} +0 -0
  157. package/src/common/errors/{reconnection.js → reconnection.ts} +5 -1
  158. package/src/common/errors/{stats.js → stats.ts} +5 -1
  159. package/src/common/errors/{webex-errors.js → webex-errors.ts} +1 -20
  160. package/src/common/errors/{webex-meetings-error.js → webex-meetings-error.ts} +3 -1
  161. package/src/common/events/{events-scope.js → events-scope.ts} +1 -1
  162. package/src/common/events/{events.js → events.ts} +0 -0
  163. package/src/common/events/{trigger-proxy.js → trigger-proxy.ts} +1 -2
  164. package/src/common/events/{util.js → util.ts} +1 -1
  165. package/src/common/logs/{logger-config.js → logger-config.ts} +1 -2
  166. package/src/common/logs/{logger-proxy.js → logger-proxy.ts} +1 -1
  167. package/src/common/logs/{request.js → request.ts} +12 -2
  168. package/src/common/queue.ts +1 -2
  169. package/src/{config.js → config.ts} +2 -0
  170. package/src/constants.ts +139 -179
  171. package/src/locus-info/{controlsUtils.js → controlsUtils.ts} +4 -4
  172. package/src/locus-info/{embeddedAppsUtils.js → embeddedAppsUtils.ts} +5 -6
  173. package/src/locus-info/{fullState.js → fullState.ts} +1 -1
  174. package/src/locus-info/{hostUtils.js → hostUtils.ts} +5 -5
  175. package/src/locus-info/{index.js → index.ts} +67 -32
  176. package/src/locus-info/{infoUtils.js → infoUtils.ts} +7 -4
  177. package/src/locus-info/{mediaSharesUtils.js → mediaSharesUtils.ts} +13 -13
  178. package/src/locus-info/{parser.js → parser.ts} +22 -12
  179. package/src/locus-info/{selfUtils.js → selfUtils.ts} +17 -19
  180. package/src/media/{index.js → index.ts} +130 -205
  181. package/src/media/internal-media-core-wrapper.ts +9 -0
  182. package/src/media/{properties.js → properties.ts} +35 -29
  183. package/src/media/util.ts +16 -0
  184. package/src/mediaQualityMetrics/{config.js → config.ts} +1 -1
  185. package/src/meeting/{effectsState.js → effectsState.ts} +12 -6
  186. package/src/meeting/{index.js → index.ts} +1016 -550
  187. package/src/meeting/{muteState.js → muteState.ts} +16 -11
  188. package/src/meeting/{request.js → request.ts} +125 -36
  189. package/src/meeting/{state.js → state.ts} +6 -6
  190. package/src/meeting/{util.js → util.ts} +9 -51
  191. package/src/meeting-info/{collection.js → collection.ts} +4 -1
  192. package/src/meeting-info/{index.js → index.ts} +10 -6
  193. package/src/meeting-info/{meeting-info-v2.js → meeting-info-v2.ts} +28 -10
  194. package/src/meeting-info/{request.js → request.ts} +6 -2
  195. package/src/meeting-info/{util.js → util.ts} +6 -5
  196. package/src/meeting-info/{utilv2.js → utilv2.ts} +8 -7
  197. package/src/meetings/{collection.js → collection.ts} +5 -2
  198. package/src/meetings/{index.js → index.ts} +118 -22
  199. package/src/meetings/{request.js → request.ts} +6 -1
  200. package/src/meetings/{util.js → util.ts} +28 -5
  201. package/src/member/{index.js → index.ts} +46 -15
  202. package/src/member/{util.js → util.ts} +17 -16
  203. package/src/members/{collection.js → collection.ts} +2 -1
  204. package/src/members/{index.js → index.ts} +94 -26
  205. package/src/members/{request.js → request.ts} +16 -5
  206. package/src/members/{util.js → util.ts} +7 -7
  207. package/src/metrics/{config.js → config.ts} +0 -2
  208. package/src/metrics/{constants.js → constants.ts} +0 -0
  209. package/src/metrics/{index.js → index.ts} +27 -8
  210. package/src/multistream/mediaRequestManager.ts +166 -0
  211. package/src/multistream/multistreamMedia.ts +92 -0
  212. package/src/multistream/receiveSlot.ts +141 -0
  213. package/src/multistream/receiveSlotManager.ts +142 -0
  214. package/src/multistream/remoteMedia.ts +228 -0
  215. package/src/multistream/remoteMediaGroup.ts +224 -0
  216. package/src/multistream/remoteMediaManager.ts +911 -0
  217. package/src/networkQualityMonitor/{index.js → index.ts} +18 -3
  218. package/src/personal-meeting-room/{index.js → index.ts} +17 -4
  219. package/src/personal-meeting-room/{request.js → request.ts} +3 -1
  220. package/src/personal-meeting-room/{util.js → util.ts} +1 -1
  221. package/src/reachability/{index.js → index.ts} +28 -17
  222. package/src/reachability/request.ts +4 -2
  223. package/src/reconnection-manager/{index.js → index.ts} +81 -65
  224. package/src/roap/index.ts +229 -0
  225. package/src/roap/{request.js → request.ts} +15 -74
  226. package/src/roap/turnDiscovery.ts +26 -11
  227. package/src/statsAnalyzer/{global.js → global.ts} +2 -0
  228. package/src/statsAnalyzer/{index.js → index.ts} +66 -61
  229. package/src/statsAnalyzer/{mqaUtil.js → mqaUtil.ts} +6 -1
  230. package/src/transcription/{index.js → index.ts} +16 -11
  231. package/test/integration/spec/journey.js +1 -1
  232. package/test/integration/spec/space-meeting.js +1 -2
  233. package/test/unit/spec/locus-info/infoUtils.js +17 -1
  234. package/test/unit/spec/media/index.ts +207 -0
  235. package/test/unit/spec/media/properties.ts +73 -82
  236. package/test/unit/spec/meeting/effectsState.js +1 -3
  237. package/test/unit/spec/meeting/index.js +585 -245
  238. package/test/unit/spec/meeting/muteState.js +7 -0
  239. package/test/unit/spec/meeting/utils.js +63 -2
  240. package/test/unit/spec/meetings/index.js +0 -4
  241. package/test/unit/spec/members/index.js +164 -2
  242. package/test/unit/spec/multistream/mediaRequestManager.ts +515 -0
  243. package/test/unit/spec/multistream/receiveSlot.ts +104 -0
  244. package/test/unit/spec/multistream/receiveSlotManager.ts +173 -0
  245. package/test/unit/spec/multistream/remoteMedia.ts +225 -0
  246. package/test/unit/spec/multistream/remoteMediaGroup.ts +396 -0
  247. package/test/unit/spec/multistream/remoteMediaManager.ts +1309 -0
  248. package/test/unit/spec/reconnection-manager/index.js +68 -2
  249. package/test/unit/spec/roap/index.ts +63 -35
  250. package/test/unit/spec/stats-analyzer/index.js +19 -22
  251. package/dist/peer-connection-manager/index.js +0 -794
  252. package/dist/peer-connection-manager/index.js.map +0 -1
  253. package/dist/peer-connection-manager/util.js +0 -124
  254. package/dist/peer-connection-manager/util.js.map +0 -1
  255. package/dist/roap/collection.js +0 -73
  256. package/dist/roap/collection.js.map +0 -1
  257. package/dist/roap/handler.js +0 -337
  258. package/dist/roap/handler.js.map +0 -1
  259. package/dist/roap/state.js +0 -164
  260. package/dist/roap/state.js.map +0 -1
  261. package/dist/roap/util.js +0 -102
  262. package/dist/roap/util.js.map +0 -1
  263. package/src/media/util.js +0 -38
  264. package/src/peer-connection-manager/index.js +0 -723
  265. package/src/peer-connection-manager/util.ts +0 -117
  266. package/src/roap/collection.js +0 -63
  267. package/src/roap/handler.js +0 -252
  268. package/src/roap/index.js +0 -380
  269. package/src/roap/state.js +0 -149
  270. package/src/roap/util.js +0 -93
  271. package/test/unit/spec/peerconnection-manager/index.js +0 -188
  272. package/test/unit/spec/peerconnection-manager/utils.js +0 -48
  273. package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -389
  274. package/test/unit/spec/roap/util.js +0 -30
@@ -0,0 +1,515 @@
1
+ import {MediaRequestManager} from '@webex/plugin-meetings/src/multistream/mediaRequestManager';
2
+ import {ReceiveSlot} from '@webex/plugin-meetings/src/multistream/receiveSlot';
3
+ import sinon from 'sinon';
4
+ import {assert} from '@webex/test-helper-chai';
5
+
6
+ type ExpectedActiveSpeaker = {
7
+ policy: 'active-speaker';
8
+ priority: number;
9
+ receiveSlots: Array<ReceiveSlot>;
10
+ };
11
+ type ExpectedReceiverSelected = {
12
+ policy: 'receiver-selected';
13
+ csi: number;
14
+ receiveSlot: ReceiveSlot;
15
+ };
16
+ type ExpectedRequest = ExpectedActiveSpeaker | ExpectedReceiverSelected;
17
+
18
+ const maxPayloadBitsPerSecond = 10 * 1000 * 1000; // for now we always send this fixed constant
19
+
20
+ describe('MediaRequestManager', () => {
21
+ const CROSS_PRIORITY_DUPLICATION = true;
22
+ const CROSS_POLICY_DUPLICATION = true;
23
+ const PREFER_LIVE_VIDEO = true;
24
+ const ACTIVE_SPEAKER_MAX_FS = 3600;
25
+ const RECEIVER_SELECTED_MAX_FS = 8190;
26
+
27
+ const NUM_SLOTS = 10;
28
+
29
+ let mediaRequestManager: MediaRequestManager;
30
+ let sendMediaRequestsCallback;
31
+ let fakeWcmeSlots;
32
+ let fakeReceiveSlots;
33
+
34
+ beforeEach(() => {
35
+ sendMediaRequestsCallback = sinon.stub();
36
+ mediaRequestManager = new MediaRequestManager(sendMediaRequestsCallback);
37
+
38
+ // create some fake receive slots used by the tests
39
+ fakeWcmeSlots = Array(NUM_SLOTS)
40
+ .fill(null)
41
+ .map((_, index) => ({
42
+ id: `fake WCME slot ${index}`,
43
+ }));
44
+
45
+ fakeReceiveSlots = Array(NUM_SLOTS)
46
+ .fill(null)
47
+ .map(
48
+ (_, index) =>
49
+ ({
50
+ id: `fake receive slot ${index}`,
51
+ wcmeReceiveSlot: fakeWcmeSlots[index],
52
+ resetSourceState: sinon.stub(),
53
+ } as unknown as ReceiveSlot)
54
+ );
55
+ });
56
+
57
+ // helper function for adding an active speaker request
58
+ const addActiveSpeakerRequest = (priority, receiveSlots, commit = false) =>
59
+ mediaRequestManager.addRequest(
60
+ {
61
+ policyInfo: {
62
+ policy: 'active-speaker',
63
+ priority,
64
+ crossPriorityDuplication: CROSS_PRIORITY_DUPLICATION,
65
+ crossPolicyDuplication: CROSS_POLICY_DUPLICATION,
66
+ preferLiveVideo: PREFER_LIVE_VIDEO,
67
+ },
68
+ receiveSlots,
69
+ codecInfo: {
70
+ codec: 'h264',
71
+ maxFs: ACTIVE_SPEAKER_MAX_FS,
72
+ },
73
+ },
74
+ commit
75
+ );
76
+
77
+ // helper function for adding a receiver selected request
78
+ const addReceiverSelectedRequest = (csi, receiveSlot, commit = false) =>
79
+ mediaRequestManager.addRequest(
80
+ {
81
+ policyInfo: {
82
+ policy: 'receiver-selected',
83
+ csi,
84
+ },
85
+ receiveSlots: [receiveSlot],
86
+ codecInfo: {
87
+ codec: 'h264',
88
+ maxFs: RECEIVER_SELECTED_MAX_FS,
89
+ },
90
+ },
91
+ commit
92
+ );
93
+
94
+ // helper function for verifying that the right active speaker and receiver selected
95
+ // requests have been sent out
96
+ // It should be used only for verifying requests created with
97
+ // addActiveSpeakerRequest() or addReceiverSelectedRequest(), because of some
98
+ // hardcoded values used in them
99
+ const checkMediaRequestsSent = (expectedRequests: ExpectedRequest[]) => {
100
+ assert.calledOnce(sendMediaRequestsCallback);
101
+ assert.calledWith(
102
+ sendMediaRequestsCallback,
103
+ expectedRequests.map((expectedRequest) => {
104
+ if (expectedRequest.policy === 'active-speaker') {
105
+ return sinon.match({
106
+ policy: 'active-speaker',
107
+ policySpecificInfo: sinon.match({
108
+ priority: expectedRequest.priority,
109
+ crossPriorityDuplication: CROSS_PRIORITY_DUPLICATION,
110
+ crossPolicyDuplication: CROSS_POLICY_DUPLICATION,
111
+ preferLiveVideo: PREFER_LIVE_VIDEO,
112
+ }),
113
+ receiveSlots: expectedRequest.receiveSlots,
114
+ maxPayloadBitsPerSecond,
115
+ codecInfos: [
116
+ sinon.match({
117
+ payloadType: 0x80,
118
+ h264: sinon.match({
119
+ maxFs: ACTIVE_SPEAKER_MAX_FS,
120
+ }),
121
+ }),
122
+ ],
123
+ });
124
+ }
125
+ if (expectedRequest.policy === 'receiver-selected') {
126
+ return sinon.match({
127
+ policy: 'receiver-selected',
128
+ policySpecificInfo: sinon.match({
129
+ csi: expectedRequest.csi,
130
+ }),
131
+ receiveSlots: [expectedRequest.receiveSlot],
132
+ maxPayloadBitsPerSecond,
133
+ codecInfos: [
134
+ sinon.match({
135
+ payloadType: 0x80,
136
+ h264: sinon.match({
137
+ maxFs: RECEIVER_SELECTED_MAX_FS,
138
+ }),
139
+ }),
140
+ ],
141
+ });
142
+ }
143
+
144
+ return undefined;
145
+ })
146
+ );
147
+ sendMediaRequestsCallback.resetHistory();
148
+ };
149
+
150
+ it('starts with no requests', () => {
151
+ mediaRequestManager.commit();
152
+
153
+ assert.calledOnce(sendMediaRequestsCallback);
154
+ assert.calledWith(sendMediaRequestsCallback, []);
155
+ });
156
+
157
+ it('sends correct wcme media requests when addRequest() is called with commit=true', () => {
158
+ // this is the only test that doesn't use the helper addActiveSpeakerRequest(), addReceiverSelectedRequest() methods
159
+ // because it tests other values for some of the parameters that are otherwise always fixed by those helpers
160
+
161
+ // first call addRequest a couple of times with commit=false
162
+ mediaRequestManager.addRequest(
163
+ {
164
+ policyInfo: {
165
+ policy: 'active-speaker',
166
+ priority: 255,
167
+ crossPriorityDuplication: true,
168
+ crossPolicyDuplication: false,
169
+ preferLiveVideo: false,
170
+ },
171
+ receiveSlots: [fakeReceiveSlots[0], fakeReceiveSlots[1], fakeReceiveSlots[2]],
172
+ codecInfo: {
173
+ codec: 'h264',
174
+ maxFs: 1620,
175
+ maxFps: 1500,
176
+ },
177
+ },
178
+ false
179
+ );
180
+ mediaRequestManager.addRequest(
181
+ {
182
+ policyInfo: {
183
+ policy: 'receiver-selected',
184
+ csi: 123,
185
+ },
186
+ receiveSlots: [fakeReceiveSlots[3]],
187
+ codecInfo: {
188
+ codec: 'h264',
189
+ maxFs: 3600,
190
+ maxFps: 2500,
191
+ maxMbps: 90000,
192
+ },
193
+ },
194
+ false
195
+ );
196
+
197
+ // finally call it with commit=true
198
+ mediaRequestManager.addRequest(
199
+ {
200
+ policyInfo: {
201
+ policy: 'receiver-selected',
202
+ csi: 123,
203
+ },
204
+ receiveSlots: [fakeReceiveSlots[4]],
205
+ codecInfo: {
206
+ codec: 'h264',
207
+ maxFs: 8192,
208
+ maxFps: 2500,
209
+ maxMbps: 204800,
210
+ },
211
+ },
212
+ true
213
+ );
214
+
215
+ // all 3 requests should be sent out together
216
+ assert.calledOnce(sendMediaRequestsCallback);
217
+ assert.calledWith(sendMediaRequestsCallback, [
218
+ sinon.match({
219
+ policy: 'active-speaker',
220
+ policySpecificInfo: sinon.match({
221
+ priority: 255,
222
+ crossPriorityDuplication: true,
223
+ crossPolicyDuplication: false,
224
+ preferLiveVideo: false,
225
+ }),
226
+ receiveSlots: [fakeWcmeSlots[0], fakeWcmeSlots[1], fakeWcmeSlots[2]],
227
+ codecInfos: [
228
+ sinon.match({
229
+ payloadType: 0x80,
230
+ h264: sinon.match({
231
+ maxFs: 1620,
232
+ maxFps: 1500,
233
+ maxMbps: 245760,
234
+ }),
235
+ }),
236
+ ],
237
+ }),
238
+ sinon.match({
239
+ policy: 'receiver-selected',
240
+ policySpecificInfo: sinon.match({
241
+ csi: 123,
242
+ }),
243
+ receiveSlots: [fakeWcmeSlots[3]],
244
+ codecInfos: [
245
+ sinon.match({
246
+ payloadType: 0x80,
247
+ h264: sinon.match({
248
+ maxFs: 3600,
249
+ maxFps: 2500,
250
+ maxMbps: 90000,
251
+ }),
252
+ }),
253
+ ],
254
+ }),
255
+ sinon.match({
256
+ policy: 'receiver-selected',
257
+ policySpecificInfo: sinon.match({
258
+ csi: 123,
259
+ }),
260
+ receiveSlots: [fakeWcmeSlots[4]],
261
+ codecInfos: [
262
+ sinon.match({
263
+ payloadType: 0x80,
264
+ h264: sinon.match({
265
+ maxFs: 8192,
266
+ maxFps: 2500,
267
+ maxMbps: 204800,
268
+ }),
269
+ }),
270
+ ],
271
+ }),
272
+ ]);
273
+ });
274
+
275
+ it('keeps adding requests with every call to addRequest()', () => {
276
+ // start with 1 request
277
+ addReceiverSelectedRequest(100, fakeReceiveSlots[0], true);
278
+
279
+ checkMediaRequestsSent([
280
+ {policy: 'receiver-selected', csi: 100, receiveSlot: fakeWcmeSlots[0]},
281
+ ]);
282
+
283
+ // now add another one
284
+ addReceiverSelectedRequest(101, fakeReceiveSlots[1], true);
285
+
286
+ checkMediaRequestsSent([
287
+ {policy: 'receiver-selected', csi: 100, receiveSlot: fakeWcmeSlots[0]},
288
+ {policy: 'receiver-selected', csi: 101, receiveSlot: fakeWcmeSlots[1]},
289
+ ]);
290
+
291
+ // and one more
292
+ addActiveSpeakerRequest(
293
+ 1,
294
+ [fakeReceiveSlots[2], fakeReceiveSlots[3], fakeReceiveSlots[4]],
295
+ true
296
+ );
297
+
298
+ checkMediaRequestsSent([
299
+ {policy: 'receiver-selected', csi: 100, receiveSlot: fakeWcmeSlots[0]},
300
+ {policy: 'receiver-selected', csi: 101, receiveSlot: fakeWcmeSlots[1]},
301
+ {
302
+ policy: 'active-speaker',
303
+ priority: 1,
304
+ receiveSlots: [fakeWcmeSlots[2], fakeWcmeSlots[3], fakeWcmeSlots[4]],
305
+ },
306
+ ]);
307
+ });
308
+
309
+ it('cancels the requests correctly when cancelRequest() is called with commit=true', () => {
310
+ const requestIds = [
311
+ addActiveSpeakerRequest(255, [fakeReceiveSlots[0], fakeReceiveSlots[1]]),
312
+ addActiveSpeakerRequest(255, [fakeReceiveSlots[2], fakeReceiveSlots[3]]),
313
+ addReceiverSelectedRequest(100, fakeReceiveSlots[4]),
314
+ addReceiverSelectedRequest(200, fakeReceiveSlots[5]),
315
+ ];
316
+
317
+ // cancel one of the active speaker requests
318
+ mediaRequestManager.cancelRequest(requestIds[1], true);
319
+
320
+ // expect only the 3 remaining requests to be sent out
321
+ checkMediaRequestsSent([
322
+ {policy: 'active-speaker', priority: 255, receiveSlots: [fakeWcmeSlots[0], fakeWcmeSlots[1]]},
323
+ {policy: 'receiver-selected', csi: 100, receiveSlot: fakeWcmeSlots[4]},
324
+ {policy: 'receiver-selected', csi: 200, receiveSlot: fakeWcmeSlots[5]},
325
+ ]);
326
+
327
+ // cancel one of the receiver selected requests
328
+ mediaRequestManager.cancelRequest(requestIds[3], true);
329
+
330
+ // expect only the 2 remaining requests to be sent out
331
+ checkMediaRequestsSent([
332
+ {policy: 'active-speaker', priority: 255, receiveSlots: [fakeWcmeSlots[0], fakeWcmeSlots[1]]},
333
+ {policy: 'receiver-selected', csi: 100, receiveSlot: fakeWcmeSlots[4]},
334
+ ]);
335
+ });
336
+
337
+ it('does not send out anything if addRequest() is called with commit=false', () => {
338
+ addActiveSpeakerRequest(
339
+ 10,
340
+ [fakeReceiveSlots[0], fakeReceiveSlots[1], fakeReceiveSlots[2]],
341
+ false
342
+ );
343
+ addReceiverSelectedRequest(123, fakeReceiveSlots[3], false);
344
+
345
+ // nothing should be sent out as we didn't commit the requests
346
+ assert.notCalled(sendMediaRequestsCallback);
347
+
348
+ // now do the commit
349
+ mediaRequestManager.commit();
350
+
351
+ // check that the 2 requests have been sent out
352
+ checkMediaRequestsSent([
353
+ {
354
+ policy: 'active-speaker',
355
+ priority: 10,
356
+ receiveSlots: [fakeWcmeSlots[0], fakeWcmeSlots[1], fakeWcmeSlots[2]],
357
+ },
358
+ {policy: 'receiver-selected', csi: 123, receiveSlot: fakeWcmeSlots[3]},
359
+ ]);
360
+ });
361
+
362
+ it('does not send out anything if cancelRequest() is called with commit=false', () => {
363
+ // send 4 requests
364
+ const requestIds = [
365
+ addActiveSpeakerRequest(
366
+ 250,
367
+ [fakeReceiveSlots[0], fakeReceiveSlots[1], fakeReceiveSlots[2]],
368
+ false
369
+ ),
370
+ addReceiverSelectedRequest(98765, fakeReceiveSlots[3], false),
371
+ addReceiverSelectedRequest(99999, fakeReceiveSlots[4], false),
372
+ addReceiverSelectedRequest(88888, fakeReceiveSlots[5], true),
373
+ ];
374
+
375
+ checkMediaRequestsSent([
376
+ {
377
+ policy: 'active-speaker',
378
+ priority: 250,
379
+ receiveSlots: [fakeWcmeSlots[0], fakeWcmeSlots[1], fakeWcmeSlots[2]],
380
+ },
381
+ {policy: 'receiver-selected', csi: 98765, receiveSlot: fakeWcmeSlots[3]},
382
+ {policy: 'receiver-selected', csi: 99999, receiveSlot: fakeWcmeSlots[4]},
383
+ {policy: 'receiver-selected', csi: 88888, receiveSlot: fakeWcmeSlots[5]},
384
+ ]);
385
+
386
+ // now cancel 3 of them, but with commit=false => nothing should happen
387
+ mediaRequestManager.cancelRequest(requestIds[0], false);
388
+ mediaRequestManager.cancelRequest(requestIds[2], false);
389
+ mediaRequestManager.cancelRequest(requestIds[3], false);
390
+
391
+ assert.notCalled(sendMediaRequestsCallback);
392
+
393
+ // now do the commit
394
+ mediaRequestManager.commit();
395
+
396
+ checkMediaRequestsSent([
397
+ {policy: 'receiver-selected', csi: 98765, receiveSlot: fakeWcmeSlots[3]},
398
+ ]);
399
+ });
400
+
401
+ it('sends the wcme media requests when commit() is called', () => {
402
+ // send some requests, all of them with commit=false
403
+ addReceiverSelectedRequest(123000, fakeReceiveSlots[0], false);
404
+ addReceiverSelectedRequest(456000, fakeReceiveSlots[1], false);
405
+ addActiveSpeakerRequest(
406
+ 255,
407
+ [fakeReceiveSlots[2], fakeReceiveSlots[3], fakeReceiveSlots[4]],
408
+ false
409
+ );
410
+ addActiveSpeakerRequest(
411
+ 254,
412
+ [fakeReceiveSlots[5], fakeReceiveSlots[6], fakeReceiveSlots[7]],
413
+ false
414
+ );
415
+
416
+ // nothing should be sent out as we didn't commit the requests
417
+ assert.notCalled(sendMediaRequestsCallback);
418
+
419
+ // now do the commit
420
+ mediaRequestManager.commit();
421
+
422
+ // check that all requests have been sent out
423
+ checkMediaRequestsSent([
424
+ {policy: 'receiver-selected', csi: 123000, receiveSlot: fakeWcmeSlots[0]},
425
+ {policy: 'receiver-selected', csi: 456000, receiveSlot: fakeWcmeSlots[1]},
426
+ {
427
+ policy: 'active-speaker',
428
+ priority: 255,
429
+ receiveSlots: [fakeWcmeSlots[2], fakeWcmeSlots[3], fakeWcmeSlots[4]],
430
+ },
431
+ {
432
+ policy: 'active-speaker',
433
+ priority: 254,
434
+ receiveSlots: [fakeWcmeSlots[5], fakeWcmeSlots[6], fakeWcmeSlots[7]],
435
+ },
436
+ ]);
437
+ });
438
+
439
+ it('clears all the requests on reset()', () => {
440
+ // send some requests and commit them one by one
441
+ addReceiverSelectedRequest(1500, fakeReceiveSlots[0], true);
442
+ addReceiverSelectedRequest(1501, fakeReceiveSlots[1], true);
443
+ addActiveSpeakerRequest(
444
+ 255,
445
+ [fakeReceiveSlots[2], fakeReceiveSlots[3], fakeReceiveSlots[4]],
446
+ true
447
+ );
448
+ addActiveSpeakerRequest(
449
+ 254,
450
+ [fakeReceiveSlots[5], fakeReceiveSlots[6], fakeReceiveSlots[7]],
451
+ true
452
+ );
453
+
454
+ sendMediaRequestsCallback.resetHistory();
455
+
456
+ // check that when calling commit() all requests are re-sent again
457
+ mediaRequestManager.commit();
458
+
459
+ checkMediaRequestsSent([
460
+ {policy: 'receiver-selected', csi: 1500, receiveSlot: fakeWcmeSlots[0]},
461
+ {policy: 'receiver-selected', csi: 1501, receiveSlot: fakeWcmeSlots[1]},
462
+ {
463
+ policy: 'active-speaker',
464
+ priority: 255,
465
+ receiveSlots: [fakeWcmeSlots[2], fakeWcmeSlots[3], fakeWcmeSlots[4]],
466
+ },
467
+ {
468
+ policy: 'active-speaker',
469
+ priority: 254,
470
+ receiveSlots: [fakeWcmeSlots[5], fakeWcmeSlots[6], fakeWcmeSlots[7]],
471
+ },
472
+ ]);
473
+
474
+ // now reset everything
475
+ mediaRequestManager.reset();
476
+
477
+ // calling commit now should not cause any requests to be sent out
478
+ mediaRequestManager.commit();
479
+ checkMediaRequestsSent([]);
480
+ });
481
+
482
+ it('calls resetSourceState() on slots that are stopped being used', () => {
483
+ const requestIds = [
484
+ addActiveSpeakerRequest(255, [fakeReceiveSlots[0], fakeReceiveSlots[1]]),
485
+ addActiveSpeakerRequest(255, [fakeReceiveSlots[2], fakeReceiveSlots[3]]),
486
+ addReceiverSelectedRequest(100, fakeReceiveSlots[4]),
487
+ addReceiverSelectedRequest(200, fakeReceiveSlots[5]),
488
+ ];
489
+
490
+ mediaRequestManager.commit();
491
+ checkMediaRequestsSent([
492
+ {policy: 'active-speaker', priority: 255, receiveSlots: [fakeWcmeSlots[0], fakeWcmeSlots[1]]},
493
+ {policy: 'active-speaker', priority: 255, receiveSlots: [fakeWcmeSlots[2], fakeWcmeSlots[3]]},
494
+ {policy: 'receiver-selected', csi: 100, receiveSlot: fakeWcmeSlots[4]},
495
+ {policy: 'receiver-selected', csi: 200, receiveSlot: fakeWcmeSlots[5]},
496
+ ]);
497
+
498
+ // cancel 2 of the requests
499
+ mediaRequestManager.cancelRequest(requestIds[1], false);
500
+ mediaRequestManager.cancelRequest(requestIds[3], false);
501
+
502
+ mediaRequestManager.commit();
503
+
504
+ // expect only the 2 remaining requests to be sent out
505
+ checkMediaRequestsSent([
506
+ {policy: 'active-speaker', priority: 255, receiveSlots: [fakeWcmeSlots[0], fakeWcmeSlots[1]]},
507
+ {policy: 'receiver-selected', csi: 100, receiveSlot: fakeWcmeSlots[4]},
508
+ ]);
509
+
510
+ // and that the receive slots of the 2 cancelled ones had resetSourceState() called
511
+ assert.calledOnce(fakeReceiveSlots[2].resetSourceState);
512
+ assert.calledOnce(fakeReceiveSlots[3].resetSourceState);
513
+ assert.calledOnce(fakeReceiveSlots[5].resetSourceState);
514
+ });
515
+ });
@@ -0,0 +1,104 @@
1
+ /* eslint-disable require-jsdoc */
2
+ import EventEmitter from 'events';
3
+
4
+ import {MediaConnection as MC} from '@webex/internal-media-core';
5
+ import {ReceiveSlot, ReceiveSlotEvents} from '@webex/plugin-meetings/src/multistream/receiveSlot';
6
+ import sinon from 'sinon';
7
+ import {assert} from '@webex/test-helper-chai';
8
+
9
+ class FakeWcmeSlot extends EventEmitter {
10
+ public stream;
11
+
12
+ constructor(stream) {
13
+ super();
14
+ this.stream = stream;
15
+ }
16
+ }
17
+
18
+ describe('ReceiveSlot', () => {
19
+ let receiveSlot;
20
+ let fakeWcmeSlot;
21
+ let findMemberIdCallbackStub;
22
+ let fakeStream;
23
+
24
+ beforeEach(() => {
25
+ fakeStream = {id: 'fake stream'};
26
+ fakeWcmeSlot = new FakeWcmeSlot(fakeStream);
27
+ findMemberIdCallbackStub = sinon.stub();
28
+ receiveSlot = new ReceiveSlot(MC.MediaType.VideoMain, fakeWcmeSlot, findMemberIdCallbackStub);
29
+ });
30
+
31
+ describe('forwards events from underlying wcme receive slot', () => {
32
+ it('forwards SourceUpdate', () => {
33
+ let eventEmitted = false;
34
+ let eventData;
35
+
36
+ const csi = 10203040;
37
+ const fakeMemberId = '12345678-1234-5678-9012-345678901234';
38
+
39
+ findMemberIdCallbackStub.returns(fakeMemberId);
40
+
41
+ receiveSlot.on(ReceiveSlotEvents.SourceUpdate, (data) => {
42
+ eventEmitted = true;
43
+ eventData = data;
44
+ });
45
+
46
+ fakeWcmeSlot.emit(MC.ReceiveSlotEvents.SourceUpdate, 'live', csi);
47
+
48
+ assert.strictEqual(eventEmitted, true);
49
+ assert.deepEqual(eventData, {
50
+ state: 'live',
51
+ csi,
52
+ memberId: fakeMemberId,
53
+ });
54
+ assert.calledOnce(findMemberIdCallbackStub);
55
+ assert.calledWith(findMemberIdCallbackStub, csi);
56
+ });
57
+ });
58
+
59
+ it('has public properties', () => {
60
+ assert.strictEqual(receiveSlot.id, 'r1');
61
+ assert.strictEqual(receiveSlot.mediaType, MC.MediaType.VideoMain);
62
+ });
63
+
64
+ it("exposes underlying wcme receive slot's properties", () => {
65
+ assert.strictEqual(receiveSlot.stream, fakeStream);
66
+ assert.strictEqual(receiveSlot.wcmeReceiveSlot, fakeWcmeSlot);
67
+ });
68
+
69
+ it("caches some underlying wcme receive slot's properties", () => {
70
+ assert.strictEqual(receiveSlot.memberId, undefined);
71
+ assert.strictEqual(receiveSlot.csi, undefined);
72
+ assert.strictEqual(receiveSlot.sourceState, 'no source');
73
+
74
+ const csi = 987654321;
75
+ const fakeMemberId = '00000001-1234-5678-9012-345678901234';
76
+
77
+ findMemberIdCallbackStub.returns(fakeMemberId);
78
+
79
+ fakeWcmeSlot.emit(MC.ReceiveSlotEvents.SourceUpdate, 'live', csi);
80
+
81
+ assert.strictEqual(receiveSlot.memberId, fakeMemberId);
82
+ assert.strictEqual(receiveSlot.csi, csi);
83
+ assert.strictEqual(receiveSlot.sourceState, 'live');
84
+ });
85
+
86
+ it('resets source related properties when resetSourceState() is called', () => {
87
+ const csi = 123456;
88
+ const fakeMemberId = '00000001-5555-6666-9012-345678901234';
89
+
90
+ findMemberIdCallbackStub.returns(fakeMemberId);
91
+
92
+ fakeWcmeSlot.emit(MC.ReceiveSlotEvents.SourceUpdate, 'live', csi);
93
+
94
+ assert.strictEqual(receiveSlot.memberId, fakeMemberId);
95
+ assert.strictEqual(receiveSlot.csi, csi);
96
+ assert.strictEqual(receiveSlot.sourceState, 'live');
97
+
98
+ receiveSlot.resetSourceState();
99
+
100
+ assert.strictEqual(receiveSlot.memberId, undefined);
101
+ assert.strictEqual(receiveSlot.csi, undefined);
102
+ assert.strictEqual(receiveSlot.sourceState, 'no source');
103
+ });
104
+ });