|
@@ -83,6 +83,11 @@ const devices = {
|
83
|
83
|
video: false
|
84
|
84
|
};
|
85
|
85
|
|
|
86
|
+/**
|
|
87
|
+ * The default frame rate for Screen Sharing.
|
|
88
|
+ */
|
|
89
|
+const SS_DEFAULT_FRAME_RATE = 5;
|
|
90
|
+
|
86
|
91
|
// Currently audio output device change is supported only in Chrome and
|
87
|
92
|
// default output always has 'default' device ID
|
88
|
93
|
let audioOutputDeviceId = 'default'; // default device
|
|
@@ -203,10 +208,15 @@ function setResolutionConstraints(
|
203
|
208
|
* @param {string} options.micDeviceId
|
204
|
209
|
* @param {CameraFacingMode} options.facingMode
|
205
|
210
|
* @param {bool} firefox_fake_device
|
|
211
|
+ * @param {Object} options.frameRate - used only for dekstop sharing.
|
|
212
|
+ * @param {Object} options.frameRate.min - Minimum fps
|
|
213
|
+ * @param {Object} options.frameRate.max - Maximum fps
|
206
|
214
|
*/
|
207
|
|
-function getConstraints(um, options) {
|
208
|
|
- const constraints = { audio: false,
|
209
|
|
- video: false };
|
|
215
|
+function getConstraints(um, options = {}) {
|
|
216
|
+ const constraints = {
|
|
217
|
+ audio: false,
|
|
218
|
+ video: false
|
|
219
|
+ };
|
210
|
220
|
|
211
|
221
|
// Don't mix new and old style settings for Chromium as this leads
|
212
|
222
|
// to TypeError in new Chromium versions. @see
|
|
@@ -316,14 +326,13 @@ function getConstraints(um, options) {
|
316
|
326
|
if (um.indexOf('screen') >= 0) {
|
317
|
327
|
if (browser.isChrome()) {
|
318
|
328
|
constraints.video = {
|
319
|
|
- mandatory: {
|
320
|
|
- chromeMediaSource: 'screen',
|
321
|
|
- maxWidth: window.screen.width,
|
322
|
|
- maxHeight: window.screen.height,
|
323
|
|
- maxFrameRate: 3
|
324
|
|
- },
|
|
329
|
+ mandatory: getSSConstraints({
|
|
330
|
+ ...options,
|
|
331
|
+ source: 'screen'
|
|
332
|
+ }),
|
325
|
333
|
optional: []
|
326
|
334
|
};
|
|
335
|
+
|
327
|
336
|
} else if (browser.isTemasysPluginUsed()) {
|
328
|
337
|
constraints.video = {
|
329
|
338
|
optional: [
|
|
@@ -335,7 +344,11 @@ function getConstraints(um, options) {
|
335
|
344
|
} else if (browser.isFirefox()) {
|
336
|
345
|
constraints.video = {
|
337
|
346
|
mozMediaSource: 'window',
|
338
|
|
- mediaSource: 'window'
|
|
347
|
+ mediaSource: 'window',
|
|
348
|
+ frameRate: options.frameRate || {
|
|
349
|
+ min: SS_DEFAULT_FRAME_RATE,
|
|
350
|
+ max: SS_DEFAULT_FRAME_RATE
|
|
351
|
+ }
|
339
|
352
|
};
|
340
|
353
|
|
341
|
354
|
} else {
|
|
@@ -349,13 +362,10 @@ function getConstraints(um, options) {
|
349
|
362
|
}
|
350
|
363
|
if (um.indexOf('desktop') >= 0) {
|
351
|
364
|
constraints.video = {
|
352
|
|
- mandatory: {
|
353
|
|
- chromeMediaSource: 'desktop',
|
354
|
|
- chromeMediaSourceId: options.desktopStream,
|
355
|
|
- maxWidth: window.screen.width,
|
356
|
|
- maxHeight: window.screen.height,
|
357
|
|
- maxFrameRate: 3
|
358
|
|
- },
|
|
365
|
+ mandatory: getSSConstraints({
|
|
366
|
+ ...options,
|
|
367
|
+ source: 'desktop'
|
|
368
|
+ }),
|
359
|
369
|
optional: []
|
360
|
370
|
};
|
361
|
371
|
}
|
|
@@ -399,6 +409,9 @@ function getConstraints(um, options) {
|
399
|
409
|
* pointing to.
|
400
|
410
|
* @param {string} options.micDeviceId - The device id for the audio capture
|
401
|
411
|
* device to get audio from.
|
|
412
|
+ * @param {Object} options.frameRate - used only for dekstop sharing.
|
|
413
|
+ * @param {Object} options.frameRate.min - Minimum fps
|
|
414
|
+ * @param {Object} options.frameRate.max - Maximum fps
|
402
|
415
|
* @private
|
403
|
416
|
* @returns {Object}
|
404
|
417
|
*/
|
|
@@ -460,19 +473,57 @@ function newGetConstraints(um = [], options = {}) {
|
460
|
473
|
}
|
461
|
474
|
|
462
|
475
|
constraints.video = {
|
463
|
|
- mandatory: {
|
464
|
|
- chromeMediaSource: 'desktop',
|
465
|
|
- chromeMediaSourceId: options.desktopStream,
|
466
|
|
- maxWidth: window.screen.width,
|
467
|
|
- maxHeight: window.screen.height,
|
468
|
|
- maxFrameRate: 3
|
469
|
|
- }
|
|
476
|
+ mandatory: getSSConstraints({
|
|
477
|
+ ...options,
|
|
478
|
+ source: 'desktop'
|
|
479
|
+ })
|
470
|
480
|
};
|
471
|
481
|
}
|
472
|
482
|
|
473
|
483
|
return constraints;
|
474
|
484
|
}
|
475
|
485
|
|
|
486
|
+/**
|
|
487
|
+ * Generates GUM constraints for screen sharing.
|
|
488
|
+ *
|
|
489
|
+ * @param {Object} options - The options passed to
|
|
490
|
+ * <tt>obtainAudioAndVideoPermissions</tt>.
|
|
491
|
+ * @returns {Object} - GUM constraints.
|
|
492
|
+ *
|
|
493
|
+ * TODO: Currently only the new GUM flow and Chrome is using the method. We
|
|
494
|
+ * should make it work for all use cases.
|
|
495
|
+ */
|
|
496
|
+function getSSConstraints(options = {}) {
|
|
497
|
+ const {
|
|
498
|
+ desktopStream,
|
|
499
|
+ frameRate = {
|
|
500
|
+ min: SS_DEFAULT_FRAME_RATE,
|
|
501
|
+ max: SS_DEFAULT_FRAME_RATE
|
|
502
|
+ }
|
|
503
|
+ } = options;
|
|
504
|
+ const { max, min } = frameRate;
|
|
505
|
+
|
|
506
|
+ const constraints = {
|
|
507
|
+ chromeMediaSource: options.source,
|
|
508
|
+ maxWidth: window.screen.width,
|
|
509
|
+ maxHeight: window.screen.height
|
|
510
|
+ };
|
|
511
|
+
|
|
512
|
+ if (typeof min === 'number') {
|
|
513
|
+ constraints.minFrameRate = min;
|
|
514
|
+ }
|
|
515
|
+
|
|
516
|
+ if (typeof max === 'number') {
|
|
517
|
+ constraints.maxFrameRate = max;
|
|
518
|
+ }
|
|
519
|
+
|
|
520
|
+ if (typeof desktopStream !== 'undefined') {
|
|
521
|
+ constraints.chromeMediaSourceId = desktopStream;
|
|
522
|
+ }
|
|
523
|
+
|
|
524
|
+ return constraints;
|
|
525
|
+}
|
|
526
|
+
|
476
|
527
|
/**
|
477
|
528
|
* Sets the availbale devices based on the options we requested and the
|
478
|
529
|
* streams we received.
|
|
@@ -1172,6 +1223,9 @@ class RTCUtils extends Listenable {
|
1172
|
1223
|
* @param {string} options.desktopStream
|
1173
|
1224
|
* @param {string} options.cameraDeviceId
|
1174
|
1225
|
* @param {string} options.micDeviceId
|
|
1226
|
+ * @param {Object} options.frameRate - used only for dekstop sharing.
|
|
1227
|
+ * @param {Object} options.frameRate.min - Minimum fps
|
|
1228
|
+ * @param {Object} options.frameRate.max - Maximum fps
|
1175
|
1229
|
* @returns {Promise} Returns a media stream on success or a JitsiTrackError
|
1176
|
1230
|
* on failure.
|
1177
|
1231
|
**/
|
|
@@ -1271,28 +1325,35 @@ class RTCUtils extends Listenable {
|
1271
|
1325
|
* logic compared to use screenObtainer versus normal device capture logic
|
1272
|
1326
|
* in RTCUtils#_newGetUserMediaWithConstraints.
|
1273
|
1327
|
*
|
1274
|
|
- * @param {Object} desktopSharingExtensionExternalInstallation
|
1275
|
|
- * @param {string[]} desktopSharingSources
|
|
1328
|
+ * @param {Object} options
|
|
1329
|
+ * @param {Object} options.desktopSharingExtensionExternalInstallation
|
|
1330
|
+ * @param {string[]} options.desktopSharingSources
|
|
1331
|
+ * @param {Object} options.gumOptions.frameRate
|
|
1332
|
+ * @param {Object} options.gumOptions.frameRate.min - Minimum fps
|
|
1333
|
+ * @param {Object} options.gumOptions.frameRate.max - Maximum fps
|
1276
|
1334
|
* @returns {Promise} A promise which will be resolved with an object whic
|
1277
|
1335
|
* contains the acquired display stream. If desktop sharing is not supported
|
1278
|
1336
|
* then a rejected promise will be returned.
|
1279
|
1337
|
*/
|
1280
|
|
- _newGetDesktopMedia(
|
1281
|
|
- desktopSharingExtensionExternalInstallation,
|
1282
|
|
- desktopSharingSources) {
|
|
1338
|
+ _newGetDesktopMedia(options) {
|
1283
|
1339
|
if (!screenObtainer.isSupported() || !browser.supportsVideo()) {
|
1284
|
1340
|
return Promise.reject(
|
1285
|
1341
|
new Error('Desktop sharing is not supported!'));
|
1286
|
1342
|
}
|
1287
|
1343
|
|
1288
|
|
- const desktopSharingOptions = {
|
1289
|
|
- ...desktopSharingExtensionExternalInstallation,
|
1290
|
|
- desktopSharingSources
|
1291
|
|
- };
|
|
1344
|
+ const {
|
|
1345
|
+ desktopSharingExtensionExternalInstallation,
|
|
1346
|
+ desktopSharingSources,
|
|
1347
|
+ gumOptions
|
|
1348
|
+ } = options;
|
1292
|
1349
|
|
1293
|
1350
|
return new Promise((resolve, reject) => {
|
1294
|
1351
|
screenObtainer.obtainStream(
|
1295
|
|
- desktopSharingOptions,
|
|
1352
|
+ {
|
|
1353
|
+ ...desktopSharingExtensionExternalInstallation,
|
|
1354
|
+ desktopSharingSources,
|
|
1355
|
+ gumOptions
|
|
1356
|
+ },
|
1296
|
1357
|
stream => {
|
1297
|
1358
|
resolve(stream);
|
1298
|
1359
|
},
|
|
@@ -1315,6 +1376,9 @@ class RTCUtils extends Listenable {
|
1315
|
1376
|
* Promise, otherwise JitsiTrack objects will be returned.
|
1316
|
1377
|
* @param {string} options.cameraDeviceId
|
1317
|
1378
|
* @param {string} options.micDeviceId
|
|
1379
|
+ * @param {Object} options.desktopSharingFrameRate
|
|
1380
|
+ * @param {Object} options.desktopSharingFrameRate.min - Minimum fps
|
|
1381
|
+ * @param {Object} options.desktopSharingFrameRate.max - Maximum fps
|
1318
|
1382
|
* @returns {*} Promise object that will receive the new JitsiTracks
|
1319
|
1383
|
*/
|
1320
|
1384
|
obtainAudioAndVideoPermissions(options = {}) {
|
|
@@ -1483,7 +1547,10 @@ class RTCUtils extends Listenable {
|
1483
|
1547
|
_parseDesktopSharingOptions(options) {
|
1484
|
1548
|
return {
|
1485
|
1549
|
...options.desktopSharingExtensionExternalInstallation,
|
1486
|
|
- desktopSharingSources: options.desktopSharingSources
|
|
1550
|
+ desktopSharingSources: options.desktopSharingSources,
|
|
1551
|
+ gumOptions: {
|
|
1552
|
+ frameRate: options.desktopSharingFrameRate
|
|
1553
|
+ }
|
1487
|
1554
|
};
|
1488
|
1555
|
}
|
1489
|
1556
|
|
|
@@ -1495,6 +1562,9 @@ class RTCUtils extends Listenable {
|
1495
|
1562
|
* relevant constraints.
|
1496
|
1563
|
* @param {string[]} options.devices - The types of media to capture. Valid
|
1497
|
1564
|
* values are "desktop", "audio", and "video".
|
|
1565
|
+ * @param {Object} options.desktopSharingFrameRate
|
|
1566
|
+ * @param {Object} options.desktopSharingFrameRate.min - Minimum fps
|
|
1567
|
+ * @param {Object} options.desktopSharingFrameRate.max - Maximum fps
|
1498
|
1568
|
* @returns {Promise} The promise, when successful, will return an array of
|
1499
|
1569
|
* meta data for the requested device type, which includes the stream and
|
1500
|
1570
|
* track. If an error occurs, it will be deferred to the caller for
|
|
@@ -1519,10 +1589,21 @@ class RTCUtils extends Listenable {
|
1519
|
1589
|
const umDevices = options.devices || [];
|
1520
|
1590
|
const isDesktopDeviceRequsted = umDevices.indexOf('desktop') !== -1;
|
1521
|
1591
|
|
|
1592
|
+ const {
|
|
1593
|
+ desktopSharingExtensionExternalInstallation,
|
|
1594
|
+ desktopSharingSources,
|
|
1595
|
+ desktopSharingFrameRate
|
|
1596
|
+ } = options;
|
|
1597
|
+
|
1522
|
1598
|
return isDesktopDeviceRequsted
|
1523
|
1599
|
? this._newGetDesktopMedia(
|
1524
|
|
- options.desktopSharingExtensionExternalInstallation,
|
1525
|
|
- options.desktopSharingSources)
|
|
1600
|
+ {
|
|
1601
|
+ desktopSharingExtensionExternalInstallation,
|
|
1602
|
+ desktopSharingSources,
|
|
1603
|
+ gumOptions: {
|
|
1604
|
+ frameRate: desktopSharingFrameRate
|
|
1605
|
+ }
|
|
1606
|
+ })
|
1526
|
1607
|
: Promise.resolve();
|
1527
|
1608
|
}.bind(this);
|
1528
|
1609
|
|