|
@@ -69,6 +69,14 @@ const MAX_TARGET_BITRATE = 2500;
|
69
|
69
|
*/
|
70
|
70
|
let startBitrate = 800;
|
71
|
71
|
|
|
72
|
+
|
|
73
|
+/**
|
|
74
|
+ * The current cap (in kbps) put on the video stream (or null if there isn't
|
|
75
|
+ * a cap). If there is a cap, we'll take it into account when calculating
|
|
76
|
+ * the current quality.
|
|
77
|
+ */
|
|
78
|
+let videoBitrateCap = null;
|
|
79
|
+
|
72
|
80
|
/**
|
73
|
81
|
* Gets the expected bitrate (in kbps) in perfect network conditions.
|
74
|
82
|
* @param simulcast {boolean} whether simulcast is enabled or not.
|
|
@@ -196,6 +204,12 @@ export default class ConnectionQuality {
|
196
|
204
|
*/
|
197
|
205
|
this._timeVideoUnmuted = -1;
|
198
|
206
|
|
|
207
|
+ /**
|
|
208
|
+ * The time at which a video bitrate cap was last removed. We use
|
|
209
|
+ * this to calculate how much time we, as a sender, have had to
|
|
210
|
+ * ramp-up
|
|
211
|
+ */
|
|
212
|
+ this._timeLastBwCapRemoved = -1;
|
199
|
213
|
|
200
|
214
|
// We assume a global startBitrate value for the sake of simplicity.
|
201
|
215
|
if (options.startBitrate && options.startBitrate > 0) {
|
|
@@ -343,21 +357,42 @@ export default class ConnectionQuality {
|
343
|
357
|
} else {
|
344
|
358
|
// Calculate a value based on the sending bitrate.
|
345
|
359
|
|
346
|
|
- // time since sending of video was enabled.
|
347
|
|
- const millisSinceStart = window.performance.now()
|
348
|
|
- - Math.max(this._timeVideoUnmuted, this._timeIceConnected);
|
349
|
|
-
|
350
|
360
|
// Figure out if simulcast is in use
|
351
|
361
|
const activeTPC = this._conference.getActivePeerConnection();
|
352
|
362
|
const isSimulcastOn
|
353
|
363
|
= Boolean(activeTPC && activeTPC.isSimulcastOn());
|
354
|
364
|
|
|
365
|
+ const newVideoBitrateCap
|
|
366
|
+ = activeTPC && activeTPC.bandwidthLimiter
|
|
367
|
+ && activeTPC.bandwidthLimiter.getBandwidthLimit('video');
|
|
368
|
+
|
|
369
|
+ // If we had a cap set but there isn't one now, then it has
|
|
370
|
+ // just been 'lifted', so we should treat this like a new
|
|
371
|
+ // ramp up.
|
|
372
|
+ if (!newVideoBitrateCap && videoBitrateCap) {
|
|
373
|
+ this._timeLastBwCapRemoved = window.performance.now();
|
|
374
|
+
|
|
375
|
+ // Set the start bitrate to whatever we were just capped to
|
|
376
|
+ startBitrate = videoBitrateCap;
|
|
377
|
+ }
|
|
378
|
+ videoBitrateCap = newVideoBitrateCap;
|
|
379
|
+
|
|
380
|
+ // time since sending of video was enabled.
|
|
381
|
+ const millisSinceStart = window.performance.now()
|
|
382
|
+ - Math.max(this._timeVideoUnmuted,
|
|
383
|
+ this._timeIceConnected,
|
|
384
|
+ this._timeLastBwCapRemoved);
|
|
385
|
+
|
355
|
386
|
// expected sending bitrate in perfect conditions
|
356
|
387
|
let target
|
357
|
388
|
= getTarget(isSimulcastOn, resolution, millisSinceStart);
|
358
|
389
|
|
359
|
390
|
target = Math.min(0.9 * target, MAX_TARGET_BITRATE);
|
360
|
391
|
|
|
392
|
+ if (videoBitrateCap) {
|
|
393
|
+ target = Math.min(target, videoBitrateCap);
|
|
394
|
+ }
|
|
395
|
+
|
361
|
396
|
quality = 100 * this._localStats.bitrate.upload / target;
|
362
|
397
|
|
363
|
398
|
// Whatever the bitrate, drop early if there is significant loss
|