This repository has been archived by the owner on May 13, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
util.js
216 lines (194 loc) · 6.35 KB
/
util.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree.
*/
/* More information about these options at jshint.com/docs/options */
/* exported calculateFps, setUpFullScreen, fullScreenElement, isFullScreen,
requestIceServers, sendAsyncUrlRequest, sendSyncUrlRequest,
randomString, trace, $, queryStringToDictionary */
'use strict';
function $(selector) {
return document.querySelector(selector);
}
// Returns the URL query key-value pairs as a dictionary object.
function queryStringToDictionary(queryString) {
var pairs = queryString.slice(1).split('&');
var result = {};
pairs.forEach(function(pair) {
if (pair) {
pair = pair.split('=');
if (pair[0]) {
result[pair[0]] = decodeURIComponent(pair[1] || '');
}
}
});
return result;
}
// Sends the URL request and returns a Promise as the result.
function sendAsyncUrlRequest(method, url, body) {
return sendUrlRequest(method, url, true, body);
}
// If async is true, returns a Promise and executes the xhr request
// async. If async is false, the xhr will be executed sync and a
// resolved promise is returned.
function sendUrlRequest(method, url, async, body) {
return new Promise(function(resolve, reject) {
var xhr;
var reportResults = function() {
if (xhr.status !== 200) {
reject(
Error('Status=' + xhr.status + ', response=' +
xhr.responseText));
return;
}
resolve(xhr.responseText);
};
xhr = new XMLHttpRequest();
if (async) {
xhr.onreadystatechange = function() {
if (xhr.readyState !== 4) {
return;
}
reportResults();
};
}
xhr.open(method, url, async);
xhr.send(body);
if (!async) {
reportResults();
}
});
}
// Returns a list of ICE servers after requesting it from the ICE server
// provider.
// Example response (iceServerRequestResponse) from the ICE server provider
// containing two TURN servers and one STUN server:
// {
// lifetimeDuration: '43200.000s',
// iceServers: [
// {
// urls: ['turn:1.2.3.4:19305', 'turn:1.2.3.5:19305'],
// username: 'username',
// credential: 'credential'
// },
// {
// urls: ['stun:stun.example.com:19302']
// }
// ]
// }
function requestIceServers(iceServerRequestUrl, iceTransports) {
return new Promise(function(resolve, reject) {
sendAsyncUrlRequest('POST', iceServerRequestUrl).then(function(response) {
var iceServerRequestResponse = parseJSON(response);
if (!iceServerRequestResponse) {
reject(Error('Error parsing response JSON: ' + response));
return;
}
if (iceTransports !== '') {
filterIceServersUrls(iceServerRequestResponse, iceTransports);
}
trace('Retrieved ICE server information.');
resolve(iceServerRequestResponse.iceServers);
}).catch(function(error) {
reject(Error('ICE server request error: ' + error.message));
return;
});
});
}
// Parse the supplied JSON, or return null if parsing fails.
function parseJSON(json) {
try {
return JSON.parse(json);
} catch (e) {
trace('Error parsing json: ' + json);
}
return null;
}
// Filter a peerConnection config to only contain ice servers with
// transport=|protocol|.
function filterIceServersUrls(config, protocol) {
var transport = 'transport=' + protocol;
var newIceServers = [];
for (var i = 0; i < config.iceServers.length; ++i) {
var iceServer = config.iceServers[i];
var newUrls = [];
for (var j = 0; j < iceServer.urls.length; ++j) {
var url = iceServer.urls[j];
if (url.indexOf(transport) !== -1) {
newUrls.push(url);
} else if (
url.indexOf('?transport=') === -1) {
newUrls.push(url + '?' + transport);
}
}
if (newUrls.length !== 0) {
iceServer.urls = newUrls;
newIceServers.push(iceServer);
}
}
config.iceServers = newIceServers;
}
// Start shims for fullscreen
function setUpFullScreen() {
document.cancelFullScreen = document.webkitCancelFullScreen ||
document.mozCancelFullScreen || document.cancelFullScreen;
document.body.requestFullScreen = document.body.webkitRequestFullScreen ||
document.body.mozRequestFullScreen || document.body.requestFullScreen;
document.onfullscreenchange = document.onfullscreenchange ||
document.onwebkitfullscreenchange || document.onmozfullscreenchange;
}
function isFullScreen() {
return !!(document.webkitIsFullScreen || document.mozFullScreen ||
document.isFullScreen); // if any defined and true
}
function fullScreenElement() {
return document.webkitFullScreenElement ||
document.webkitCurrentFullScreenElement ||
document.mozFullScreenElement ||
document.fullScreenElement;
}
// End shims for fullscreen
// Return a random numerical string.
function randomString(strLength) {
var result = [];
strLength = strLength || 5;
var charSet = '0123456789';
while (strLength--) {
result.push(charSet.charAt(Math.floor(Math.random() * charSet.length)));
}
return result.join('');
}
// Calculcates FPS for the provided video elements and calls on a callback which
// is used to update the necessary stats for either remote or local videos.
// Adapted from https://cs.chromium.org/chromium/src/chrome/test/data/media/html/media_stat_perf.html
function calculateFps(videoElement, decodedFrames, startTime, remoteOrLocal,
callback) {
var fps = 0;
if (videoElement &&
typeof videoElement.webkitDecodedFrameCount !== undefined) {
if (videoElement.readyState >= videoElement.HAVE_CURRENT_DATA) {
var currentTime = new Date().getTime();
var deltaTime = (currentTime - startTime) / 1000;
var startTimeToReturn = currentTime;
fps = (videoElement.webkitDecodedFrameCount - decodedFrames) / deltaTime;
callback(videoElement.webkitDecodedFrameCount, startTimeToReturn,
remoteOrLocal);
}
}
return parseInt(fps);
}
function trace(text) {
// This function is used for logging.
if (text[text.length - 1] === '\n') {
text = text.substring(0, text.length - 1);
}
if (window.performance) {
var now = (window.performance.now() / 1000).toFixed(3);
console.log(now + ': ' + text);
} else {
console.log(text);
}
}