@webex/plugin-meetings 3.0.0-beta.154 → 3.0.0-beta.155

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.
@@ -5,7 +5,6 @@ import {assert} from '@webex/test-helper-chai';
5
5
  import {getMaxFs} from '@webex/plugin-meetings/src/multistream/remoteMedia';
6
6
  import FakeTimers from '@sinonjs/fake-timers';
7
7
  import * as mediaCore from '@webex/internal-media-core';
8
- import { assertFunction } from '@babel/types';
9
8
  import { expect } from 'chai';
10
9
 
11
10
  type ExpectedActiveSpeaker = {
@@ -33,7 +32,6 @@ const degradationPreferences = {
33
32
  describe('MediaRequestManager', () => {
34
33
  const CROSS_PRIORITY_DUPLICATION = true;
35
34
  const CROSS_POLICY_DUPLICATION = true;
36
- const PREFER_LIVE_VIDEO = true;
37
35
  const MAX_FPS = 3000;
38
36
  const MAX_FS_360p = 920;
39
37
  const MAX_FS_720p = 3600;
@@ -45,7 +43,7 @@ describe('MediaRequestManager', () => {
45
43
  const MAX_PAYLOADBITSPS_720p = 2500000;
46
44
  const MAX_PAYLOADBITSPS_1080p = 4000000;
47
45
 
48
- const NUM_SLOTS = 10;
46
+ const NUM_SLOTS = 15;
49
47
 
50
48
  let mediaRequestManager: MediaRequestManager;
51
49
  let sendMediaRequestsCallback;
@@ -57,6 +55,7 @@ describe('MediaRequestManager', () => {
57
55
  mediaRequestManager = new MediaRequestManager(sendMediaRequestsCallback, {
58
56
  degradationPreferences,
59
57
  kind: 'video',
58
+ trimRequestsToNumOfSources: false,
60
59
  });
61
60
 
62
61
  // create some fake receive slots used by the tests
@@ -81,7 +80,7 @@ describe('MediaRequestManager', () => {
81
80
  });
82
81
 
83
82
  // helper function for adding an active speaker request
84
- const addActiveSpeakerRequest = (priority, receiveSlots, maxFs, commit = false) =>
83
+ const addActiveSpeakerRequest = (priority, receiveSlots, maxFs, commit = false, preferLiveVideo = true) =>
85
84
  mediaRequestManager.addRequest(
86
85
  {
87
86
  policyInfo: {
@@ -89,7 +88,7 @@ describe('MediaRequestManager', () => {
89
88
  priority,
90
89
  crossPriorityDuplication: CROSS_PRIORITY_DUPLICATION,
91
90
  crossPolicyDuplication: CROSS_POLICY_DUPLICATION,
92
- preferLiveVideo: PREFER_LIVE_VIDEO,
91
+ preferLiveVideo,
93
92
  },
94
93
  receiveSlots,
95
94
  codecInfo: {
@@ -123,8 +122,10 @@ describe('MediaRequestManager', () => {
123
122
  // addActiveSpeakerRequest() or addReceiverSelectedRequest(), because of some
124
123
  // hardcoded values used in them
125
124
  const checkMediaRequestsSent = (
126
- expectedRequests: ExpectedRequest[],
127
- isCodecInfoDefined: boolean = true
125
+ expectedRequests: ExpectedRequest[], {
126
+ isCodecInfoDefined = true,
127
+ preferLiveVideo = true,
128
+ } = {}
128
129
  ) => {
129
130
  assert.calledOnce(sendMediaRequestsCallback);
130
131
  assert.calledWith(
@@ -137,7 +138,7 @@ describe('MediaRequestManager', () => {
137
138
  priority: expectedRequest.priority,
138
139
  crossPriorityDuplication: CROSS_PRIORITY_DUPLICATION,
139
140
  crossPolicyDuplication: CROSS_POLICY_DUPLICATION,
140
- preferLiveVideo: PREFER_LIVE_VIDEO,
141
+ preferLiveVideo,
141
142
  }),
142
143
  receiveSlots: expectedRequest.receiveSlots,
143
144
  maxPayloadBitsPerSecond: expectedRequest.maxPayloadBitsPerSecond,
@@ -971,7 +972,11 @@ describe('MediaRequestManager', () => {
971
972
  const mediaRequestManagerAudio = new MediaRequestManager(sendMediaRequestsCallback, {
972
973
  degradationPreferences,
973
974
  kind: 'audio',
975
+ trimRequestsToNumOfSources: false,
974
976
  });
977
+ mediaRequestManagerAudio.setNumCurrentSources(100, 100);
978
+ sendMediaRequestsCallback.resetHistory();
979
+
975
980
  mediaRequestManagerAudio.addRequest(
976
981
  {
977
982
  policyInfo: {
@@ -997,7 +1002,7 @@ describe('MediaRequestManager', () => {
997
1002
  },
998
1003
  // set isCodecInfoDefined to false, since we don't pass in a codec info when audio:
999
1004
  ],
1000
- false
1005
+ {isCodecInfoDefined: false}
1001
1006
  );
1002
1007
 
1003
1008
  assert.notCalled(getRecommendedMaxBitrateForFrameSizeSpy);
@@ -1079,6 +1084,333 @@ describe('MediaRequestManager', () => {
1079
1084
  ]);
1080
1085
  });
1081
1086
  });
1087
+
1088
+ describe('trimming of requested receive slots', () => {
1089
+ beforeEach(() => {
1090
+ mediaRequestManager = new MediaRequestManager(sendMediaRequestsCallback, {
1091
+ degradationPreferences,
1092
+ kind: 'video',
1093
+ trimRequestsToNumOfSources: true,
1094
+ });
1095
+ });
1096
+
1097
+ const limitNumAvailableStreams = (preferLiveVideo, limit) => {
1098
+ if (preferLiveVideo) {
1099
+ mediaRequestManager.setNumCurrentSources(100, limit);
1100
+ } else {
1101
+ mediaRequestManager.setNumCurrentSources(limit, 1);
1102
+ }
1103
+ };
1104
+
1105
+ [true, false].forEach((preferLiveVideo) =>
1106
+ describe(`preferLiveVideo=${preferLiveVideo}`, () => {
1107
+ it(`trims the active speaker request with lowest priority first and maintains slot order`, () => {
1108
+ // add some receiver-selected and active-speaker requests, in a mixed up order
1109
+ addReceiverSelectedRequest(100, fakeReceiveSlots[0], MAX_FS_360p, false);
1110
+ addActiveSpeakerRequest( // AS request 1 - it will get 1 slot trimmed
1111
+ 254,
1112
+ [fakeReceiveSlots[1], fakeReceiveSlots[2], fakeReceiveSlots[3]],
1113
+ MAX_FS_360p,
1114
+ false,
1115
+ preferLiveVideo
1116
+ );
1117
+ addActiveSpeakerRequest( // AS request 2 - lowest priority, it will have all slots trimmed
1118
+ 253,
1119
+ [fakeReceiveSlots[7], fakeReceiveSlots[8], fakeReceiveSlots[9]],
1120
+ MAX_FS_360p,
1121
+ false,
1122
+ preferLiveVideo
1123
+ );
1124
+ addActiveSpeakerRequest( // AS request 3 - highest priority, nothing will be trimmed
1125
+ 255,
1126
+ [fakeReceiveSlots[4], fakeReceiveSlots[5], fakeReceiveSlots[6]],
1127
+ MAX_FS_360p,
1128
+ false,
1129
+ preferLiveVideo
1130
+ );
1131
+ addReceiverSelectedRequest(101, fakeReceiveSlots[10], MAX_FS_360p, false);
1132
+
1133
+ /* Set number of available streams to 7 so that there will be enough sources only for
1134
+ the 2 RS requests and 2 of the 3 AS requests. The lowest priority AS request will
1135
+ have all the slots trimmed, the second lowest priority AS request will have 1 slot trimmed */
1136
+ limitNumAvailableStreams(preferLiveVideo, 7);
1137
+
1138
+ // check what got trimmed
1139
+ checkMediaRequestsSent([
1140
+ {
1141
+ policy: 'receiver-selected',
1142
+ csi: 100,
1143
+ receiveSlot: fakeWcmeSlots[0],
1144
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1145
+ maxFs: MAX_FS_360p,
1146
+ maxMbps: MAX_MBPS_360p,
1147
+ },
1148
+ {
1149
+ policy: 'active-speaker',
1150
+ priority: 254,
1151
+ receiveSlots: [fakeWcmeSlots[1], fakeWcmeSlots[2]], // fakeWcmeSlots[3] got trimmed
1152
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1153
+ maxFs: MAX_FS_360p,
1154
+ maxMbps: MAX_MBPS_360p,
1155
+ },
1156
+ // AS request with priority 253 is missing, because all of its slots got trimmed
1157
+ {
1158
+ policy: 'active-speaker',
1159
+ priority: 255,
1160
+ receiveSlots: [fakeWcmeSlots[4], fakeWcmeSlots[5], fakeWcmeSlots[6]],
1161
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1162
+ maxFs: MAX_FS_360p,
1163
+ maxMbps: MAX_MBPS_360p,
1164
+ },
1165
+ {
1166
+ policy: 'receiver-selected',
1167
+ csi: 101,
1168
+ receiveSlot: fakeWcmeSlots[10],
1169
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1170
+ maxFs: MAX_FS_360p,
1171
+ maxMbps: MAX_MBPS_360p,
1172
+ },
1173
+ ], {preferLiveVideo});
1174
+
1175
+ // now increase the number of available streams so only the last AS request is trimmed by 1
1176
+ limitNumAvailableStreams(preferLiveVideo, 10);
1177
+
1178
+ checkMediaRequestsSent([
1179
+ {
1180
+ policy: 'receiver-selected',
1181
+ csi: 100,
1182
+ receiveSlot: fakeWcmeSlots[0],
1183
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1184
+ maxFs: MAX_FS_360p,
1185
+ maxMbps: MAX_MBPS_360p,
1186
+ },
1187
+ {
1188
+ policy: 'active-speaker',
1189
+ priority: 254,
1190
+ receiveSlots: [fakeWcmeSlots[1], fakeWcmeSlots[2], fakeWcmeSlots[3]], // all slots are used, nothing trimmed
1191
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1192
+ maxFs: MAX_FS_360p,
1193
+ maxMbps: MAX_MBPS_360p,
1194
+ },
1195
+ {
1196
+ policy: 'active-speaker',
1197
+ priority: 253,
1198
+ receiveSlots: [fakeWcmeSlots[7], fakeWcmeSlots[8]], // only 1 slot is trimmed
1199
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1200
+ maxFs: MAX_FS_360p,
1201
+ maxMbps: MAX_MBPS_360p,
1202
+ },
1203
+ {
1204
+ policy: 'active-speaker',
1205
+ priority: 255,
1206
+ receiveSlots: [fakeWcmeSlots[4], fakeWcmeSlots[5], fakeWcmeSlots[6]], // all slots are used, nothing trimmed
1207
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1208
+ maxFs: MAX_FS_360p,
1209
+ maxMbps: MAX_MBPS_360p,
1210
+ },
1211
+ {
1212
+ policy: 'receiver-selected',
1213
+ csi: 101,
1214
+ receiveSlot: fakeWcmeSlots[10],
1215
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1216
+ maxFs: MAX_FS_360p,
1217
+ maxMbps: MAX_MBPS_360p,
1218
+ },
1219
+ ], {preferLiveVideo});
1220
+ })
1221
+
1222
+ it('does not trim the receiver selected requests', async () => {
1223
+ // add some receiver-selected and active-speaker requests, in a mixed up order
1224
+ addReceiverSelectedRequest(200, fakeReceiveSlots[0], MAX_FS_360p, false);
1225
+ addActiveSpeakerRequest(
1226
+ 255,
1227
+ [fakeReceiveSlots[1], fakeReceiveSlots[2], fakeReceiveSlots[3]],
1228
+ MAX_FS_360p,
1229
+ false,
1230
+ preferLiveVideo
1231
+ );
1232
+ addReceiverSelectedRequest(201, fakeReceiveSlots[4], MAX_FS_720p, false);
1233
+ addActiveSpeakerRequest(
1234
+ 254,
1235
+ [fakeReceiveSlots[5], fakeReceiveSlots[6], fakeReceiveSlots[7]],
1236
+ MAX_FS_720p,
1237
+ false,
1238
+ preferLiveVideo
1239
+ );
1240
+
1241
+ /* Set number of available streams to 1, which is lower than the number of RS requests,
1242
+ so all AS requests will be trimmed to 0 but RS requests should be unaltered */
1243
+ limitNumAvailableStreams(preferLiveVideo, 1);
1244
+
1245
+ // check what got trimmed - only RS requests should remain
1246
+ checkMediaRequestsSent([
1247
+ {
1248
+ policy: 'receiver-selected',
1249
+ csi: 200,
1250
+ receiveSlot: fakeWcmeSlots[0],
1251
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1252
+ maxFs: MAX_FS_360p,
1253
+ maxMbps: MAX_MBPS_360p,
1254
+ },
1255
+ {
1256
+ policy: 'receiver-selected',
1257
+ csi: 201,
1258
+ receiveSlot: fakeWcmeSlots[4],
1259
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_720p,
1260
+ maxFs: MAX_FS_720p,
1261
+ maxMbps: MAX_MBPS_720p,
1262
+ },
1263
+ ], {preferLiveVideo});
1264
+ });
1265
+
1266
+ it('does trimming first and applies degradationPreferences after that', async () => {
1267
+ // add some receiver-selected and active-speaker requests
1268
+ addReceiverSelectedRequest(200, fakeReceiveSlots[0], MAX_FS_360p, false);
1269
+ addActiveSpeakerRequest(
1270
+ 255,
1271
+ [fakeReceiveSlots[1], fakeReceiveSlots[2], fakeReceiveSlots[3]],
1272
+ MAX_FS_360p,
1273
+ false,
1274
+ preferLiveVideo
1275
+ );
1276
+ addReceiverSelectedRequest(201, fakeReceiveSlots[4], MAX_FS_720p, false);
1277
+ addActiveSpeakerRequest(
1278
+ 254,
1279
+ [fakeReceiveSlots[5], fakeReceiveSlots[6], fakeReceiveSlots[7]],
1280
+ MAX_FS_720p,
1281
+ false,
1282
+ preferLiveVideo
1283
+ );
1284
+
1285
+ // Set maxMacroblocksLimit to a value that's big enough just for the 2 RS requests and 1 AS with 1 slot of 360p.
1286
+ // but not big enough for all of the RS and AS requests. If maxMacroblocksLimit
1287
+ // was applied first, the resolution of all requests (including RS ones) would be degraded
1288
+ // This test verifies that it's not happening and the resolutions are not affected.
1289
+ mediaRequestManager.setDegradationPreferences({maxMacroblocksLimit: MAX_FS_360p + MAX_FS_720p + MAX_FS_360p});
1290
+ sendMediaRequestsCallback.resetHistory();
1291
+
1292
+ /* Limit the num of streams so that only 2 RS requests and 1 AS with 1 slot can be sent out */
1293
+ limitNumAvailableStreams(preferLiveVideo, 3);
1294
+
1295
+ // check what got trimmed - the remaining requests should have unchanged resolutions
1296
+ checkMediaRequestsSent([
1297
+ {
1298
+ policy: 'receiver-selected',
1299
+ csi: 200,
1300
+ receiveSlot: fakeWcmeSlots[0],
1301
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1302
+ maxFs: MAX_FS_360p,
1303
+ maxMbps: MAX_MBPS_360p,
1304
+ },
1305
+ {
1306
+ policy: 'active-speaker',
1307
+ priority: 255,
1308
+ receiveSlots: [fakeWcmeSlots[1]],
1309
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1310
+ maxFs: MAX_FS_360p,
1311
+ maxMbps: MAX_MBPS_360p,
1312
+ },
1313
+ {
1314
+ policy: 'receiver-selected',
1315
+ csi: 201,
1316
+ receiveSlot: fakeWcmeSlots[4],
1317
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_720p,
1318
+ maxFs: MAX_FS_720p,
1319
+ maxMbps: MAX_MBPS_720p,
1320
+ },
1321
+ ], {preferLiveVideo});
1322
+ });
1323
+
1324
+ it('trims all AS requests completely until setNumCurrentSources() is called with non-zero values', async () => {
1325
+ // add some receiver-selected and active-speaker requests
1326
+ addReceiverSelectedRequest(200, fakeReceiveSlots[0], MAX_FS_360p, false);
1327
+ addActiveSpeakerRequest(
1328
+ 255,
1329
+ [fakeReceiveSlots[1], fakeReceiveSlots[2], fakeReceiveSlots[3]],
1330
+ MAX_FS_360p,
1331
+ false,
1332
+ preferLiveVideo
1333
+ );
1334
+ addActiveSpeakerRequest(
1335
+ 254,
1336
+ [fakeReceiveSlots[5]],
1337
+ MAX_FS_360p,
1338
+ false,
1339
+ preferLiveVideo
1340
+ );
1341
+
1342
+ mediaRequestManager.commit();
1343
+
1344
+ // we're not calling setNumCurrentSources(), so it should use the initial values of 0 for sources count
1345
+ // and completely trim all AS requests to 0
1346
+ checkMediaRequestsSent([
1347
+ {
1348
+ policy: 'receiver-selected',
1349
+ csi: 200,
1350
+ receiveSlot: fakeWcmeSlots[0],
1351
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1352
+ maxFs: MAX_FS_360p,
1353
+ maxMbps: MAX_MBPS_360p,
1354
+ },
1355
+ ], {preferLiveVideo});
1356
+ });
1357
+
1358
+ it('resets num of sources to 0 when reset() is called', async () => {
1359
+ // set available streams to non-zero value
1360
+ limitNumAvailableStreams(preferLiveVideo, 4);
1361
+ sendMediaRequestsCallback.resetHistory();
1362
+
1363
+ // do the reset
1364
+ mediaRequestManager.reset();
1365
+
1366
+ // add some receiver-selected and active-speaker requests
1367
+ addReceiverSelectedRequest(200, fakeReceiveSlots[0], MAX_FS_360p, false);
1368
+ addActiveSpeakerRequest(
1369
+ 255,
1370
+ [fakeReceiveSlots[1], fakeReceiveSlots[2], fakeReceiveSlots[3]],
1371
+ MAX_FS_360p,
1372
+ false,
1373
+ preferLiveVideo
1374
+ );
1375
+
1376
+ mediaRequestManager.commit();
1377
+
1378
+ // verify that AS request was trimmed to 0, because we've reset mediaRequestManager so available streams count is 0 now
1379
+ checkMediaRequestsSent([
1380
+ {
1381
+ policy: 'receiver-selected',
1382
+ csi: 200,
1383
+ receiveSlot: fakeWcmeSlots[0],
1384
+ maxPayloadBitsPerSecond: MAX_PAYLOADBITSPS_360p,
1385
+ maxFs: MAX_FS_360p,
1386
+ maxMbps: MAX_MBPS_360p,
1387
+ },
1388
+ ], {preferLiveVideo});
1389
+ });
1390
+ })
1391
+ );
1392
+
1393
+
1394
+ it('throws if there are 2 active-speaker requests with different preferLiveVideo values', () => {
1395
+ addActiveSpeakerRequest(
1396
+ 255,
1397
+ [fakeReceiveSlots[0]],
1398
+ MAX_FS_360p,
1399
+ false,
1400
+ true
1401
+ );
1402
+ addReceiverSelectedRequest(201, fakeReceiveSlots[4], MAX_FS_720p, false);
1403
+ addActiveSpeakerRequest(
1404
+ 254,
1405
+ [fakeReceiveSlots[2]],
1406
+ MAX_FS_360p,
1407
+ false,
1408
+ false
1409
+ );
1410
+
1411
+ assert.throws(() => mediaRequestManager.commit(), 'a mix of active-speaker groups with different values for preferLiveVideo is not supported');
1412
+ })
1413
+ })
1082
1414
  });
1083
1415
  function assertEqual(arg0: any, arg1: string) {
1084
1416
  throw new Error('Function not implemented.');