|
|
@@ -56,6 +56,18 @@ KEYS_BY_BROWSER_TYPE[browsers.CHROME] = {
|
|
56
|
56
|
'port': 'port',
|
|
57
|
57
|
'protocol': 'protocol'
|
|
58
|
58
|
};
|
|
|
59
|
+KEYS_BY_BROWSER_TYPE[browsers.REACT_NATIVE] = {
|
|
|
60
|
+ 'packetsReceived': 'packetsReceived',
|
|
|
61
|
+ 'packetsSent': 'packetsSent',
|
|
|
62
|
+ 'bytesReceived': 'bytesReceived',
|
|
|
63
|
+ 'bytesSent': 'bytesSent',
|
|
|
64
|
+ 'frameWidth': 'frameWidth',
|
|
|
65
|
+ 'frameHeight': 'frameHeight',
|
|
|
66
|
+ 'framesPerSecond': 'framesPerSecond',
|
|
|
67
|
+ 'ip': 'ip',
|
|
|
68
|
+ 'port': 'port',
|
|
|
69
|
+ 'protocol': 'protocol'
|
|
|
70
|
+};
|
|
59
|
71
|
KEYS_BY_BROWSER_TYPE[browsers.OPERA]
|
|
60
|
72
|
= KEYS_BY_BROWSER_TYPE[browsers.CHROME];
|
|
61
|
73
|
KEYS_BY_BROWSER_TYPE[browsers.NWJS]
|
|
|
@@ -64,8 +76,6 @@ KEYS_BY_BROWSER_TYPE[browsers.ELECTRON]
|
|
64
|
76
|
= KEYS_BY_BROWSER_TYPE[browsers.CHROME];
|
|
65
|
77
|
KEYS_BY_BROWSER_TYPE[browsers.SAFARI]
|
|
66
|
78
|
= KEYS_BY_BROWSER_TYPE[browsers.CHROME];
|
|
67
|
|
-KEYS_BY_BROWSER_TYPE[browsers.REACT_NATIVE]
|
|
68
|
|
- = KEYS_BY_BROWSER_TYPE[browsers.CHROME];
|
|
69
|
79
|
|
|
70
|
80
|
/**
|
|
71
|
81
|
* Calculates packet lost percent using the number of lost packets and the
|
|
|
@@ -214,8 +224,7 @@ export default function StatsCollector(
|
|
214
|
224
|
const keys = KEYS_BY_BROWSER_TYPE[this._browserType];
|
|
215
|
225
|
|
|
216
|
226
|
if (!keys) {
|
|
217
|
|
- // eslint-disable-next-line no-throw-literal
|
|
218
|
|
- throw `The browser type '${this._browserType}' isn't supported!`;
|
|
|
227
|
+ throw new Error(`The browser type '${this._browserType}' isn't supported!`);
|
|
219
|
228
|
}
|
|
220
|
229
|
|
|
221
|
230
|
/**
|
|
|
@@ -223,7 +232,7 @@ export default function StatsCollector(
|
|
223
|
232
|
* @type {boolean}
|
|
224
|
233
|
*/
|
|
225
|
234
|
this._usesPromiseGetStats
|
|
226
|
|
- = browser.isSafari() || browser.isFirefox();
|
|
|
235
|
+ = browser.isSafari() || browser.isFirefox() || browser.isReactNative();
|
|
227
|
236
|
|
|
228
|
237
|
/**
|
|
229
|
238
|
* The function which is to be used to retrieve the value associated in a
|
|
|
@@ -401,8 +410,7 @@ StatsCollector.prototype._defineGetStatValueMethod = function(keys) {
|
|
401
|
410
|
return key;
|
|
402
|
411
|
}
|
|
403
|
412
|
|
|
404
|
|
- // eslint-disable-next-line no-throw-literal
|
|
405
|
|
- throw `The property '${name}' isn't supported!`;
|
|
|
413
|
+ throw new Error(`The property '${name}' isn't supported!`);
|
|
406
|
414
|
};
|
|
407
|
415
|
|
|
408
|
416
|
// Define the function which retrieves the value from a specific report
|
|
|
@@ -424,27 +432,6 @@ StatsCollector.prototype._defineGetStatValueMethod = function(keys) {
|
|
424
|
432
|
// retrieve the value associated with a specific key.
|
|
425
|
433
|
itemStatByKey = (item, key) => item.stat(key);
|
|
426
|
434
|
break;
|
|
427
|
|
- case browsers.REACT_NATIVE:
|
|
428
|
|
- // The implementation provided by react-native-webrtc follows the
|
|
429
|
|
- // Objective-C WebRTC API: RTCStatsReport has a values property of type
|
|
430
|
|
- // Array in which each element is a key-value pair.
|
|
431
|
|
- itemStatByKey = function(item, key) {
|
|
432
|
|
- let value;
|
|
433
|
|
-
|
|
434
|
|
- item.values.some(pair => {
|
|
435
|
|
- if (pair.hasOwnProperty(key)) {
|
|
436
|
|
- value = pair[key];
|
|
437
|
|
-
|
|
438
|
|
- return true;
|
|
439
|
|
- }
|
|
440
|
|
-
|
|
441
|
|
- return false;
|
|
442
|
|
-
|
|
443
|
|
- });
|
|
444
|
|
-
|
|
445
|
|
- return value;
|
|
446
|
|
- };
|
|
447
|
|
- break;
|
|
448
|
435
|
default:
|
|
449
|
436
|
itemStatByKey = (item, key) => item[key];
|
|
450
|
437
|
}
|
|
|
@@ -759,10 +746,10 @@ StatsCollector.prototype._processAndEmitReport = function() {
|
|
759
|
746
|
const codecs = {};
|
|
760
|
747
|
let audioBitrateDownload = 0;
|
|
761
|
748
|
let audioBitrateUpload = 0;
|
|
762
|
|
- let audioCodec = '';
|
|
|
749
|
+ let audioCodec;
|
|
763
|
750
|
let videoBitrateDownload = 0;
|
|
764
|
751
|
let videoBitrateUpload = 0;
|
|
765
|
|
- let videoCodec = '';
|
|
|
752
|
+ let videoCodec;
|
|
766
|
753
|
|
|
767
|
754
|
for (const [ ssrc, ssrcStats ] of this.ssrc2stats) {
|
|
768
|
755
|
// process packet loss stats
|
|
|
@@ -810,7 +797,7 @@ StatsCollector.prototype._processAndEmitReport = function() {
|
|
810
|
797
|
userFramerates[ssrc] = ssrcStats.framerate;
|
|
811
|
798
|
framerates[participantId] = userFramerates;
|
|
812
|
799
|
}
|
|
813
|
|
- if (audioCodec.length && videoCodec.length) {
|
|
|
800
|
+ if (audioCodec && videoCodec) {
|
|
814
|
801
|
const codecDesc = {
|
|
815
|
802
|
'audio': audioCodec,
|
|
816
|
803
|
'video': videoCodec
|
|
|
@@ -1016,8 +1003,7 @@ StatsCollector.prototype._defineNewGetStatValueMethod = function(keys) {
|
|
1016
|
1003
|
return key;
|
|
1017
|
1004
|
}
|
|
1018
|
1005
|
|
|
1019
|
|
- // eslint-disable-next-line no-throw-literal
|
|
1020
|
|
- throw `The property '${name}' isn't supported!`;
|
|
|
1006
|
+ throw new Error(`The property '${name}' isn't supported!`);
|
|
1021
|
1007
|
};
|
|
1022
|
1008
|
|
|
1023
|
1009
|
// Compose the 2 functions defined above to get a function which retrieves
|
|
|
@@ -1191,6 +1177,31 @@ StatsCollector.prototype.processNewStatsReport = function() {
|
|
1191
|
1177
|
isDownloadStream
|
|
1192
|
1178
|
});
|
|
1193
|
1179
|
|
|
|
1180
|
+ const resolution = {
|
|
|
1181
|
+ height: null,
|
|
|
1182
|
+ width: null
|
|
|
1183
|
+ };
|
|
|
1184
|
+
|
|
|
1185
|
+ try {
|
|
|
1186
|
+ resolution.height = getStatValue(now, 'frameHeight');
|
|
|
1187
|
+ resolution.width = getStatValue(now, 'frameWidth');
|
|
|
1188
|
+ } catch (e) { /* not supported*/ }
|
|
|
1189
|
+
|
|
|
1190
|
+ // Tries to get frame rate
|
|
|
1191
|
+ let frameRate;
|
|
|
1192
|
+
|
|
|
1193
|
+ try {
|
|
|
1194
|
+ frameRate = getStatValue(now, 'framesPerSecond');
|
|
|
1195
|
+ } catch (err) { /* not supported*/ }
|
|
|
1196
|
+
|
|
|
1197
|
+ ssrcStats.setFramerate(Math.round(frameRate || 0));
|
|
|
1198
|
+
|
|
|
1199
|
+ if (resolution.height && resolution.width) {
|
|
|
1200
|
+ ssrcStats.setResolution(resolution);
|
|
|
1201
|
+ } else {
|
|
|
1202
|
+ ssrcStats.setResolution(null);
|
|
|
1203
|
+ }
|
|
|
1204
|
+
|
|
1194
|
1205
|
if (now.type === 'inbound-rtp') {
|
|
1195
|
1206
|
|
|
1196
|
1207
|
ssrcStats.addBitrate({
|
|
|
@@ -1224,6 +1235,23 @@ StatsCollector.prototype.processNewStatsReport = function() {
|
|
1224
|
1235
|
ssrcStats.setFramerate(Math.round(framerateMean || 0));
|
|
1225
|
1236
|
}
|
|
1226
|
1237
|
|
|
|
1238
|
+
|
|
|
1239
|
+ let codec;
|
|
|
1240
|
+
|
|
|
1241
|
+ // Try to get the codec for later reporting.
|
|
|
1242
|
+ try {
|
|
|
1243
|
+ codec = this.currentStatsReport.get(now.codecId);
|
|
|
1244
|
+ } catch (e) { /* not supported*/ }
|
|
|
1245
|
+
|
|
|
1246
|
+ /*
|
|
|
1247
|
+ The mime type has the following form: video/VP8 or audio/ISAC,
|
|
|
1248
|
+ so we what to keep just the type after the '/', audio and video
|
|
|
1249
|
+ keys will be added on the processing side.
|
|
|
1250
|
+ */
|
|
|
1251
|
+ const codecShortType = codec.mimeType.split('/')[1];
|
|
|
1252
|
+
|
|
|
1253
|
+ ssrcStats.setCodec(codecShortType);
|
|
|
1254
|
+
|
|
1227
|
1255
|
// track for resolution
|
|
1228
|
1256
|
// RTCVideoHandlerStats
|
|
1229
|
1257
|
// https://w3c.github.io/webrtc-stats/#vststats-dict*
|