blob: ea305a1f6a0e22254ebc06fb50a1356a10d69eaf [file] [log] [blame]
vikasmarwaha@webrtc.org98fce152013-02-27 23:22:10 +00001<html>
2<head>
3<title>Constraints and Statistics</title>
hta@webrtc.orgdb3f4272013-03-05 15:23:40 +00004<!-- Load the polyfill to switch-hit between Chrome and Firefox -->
5<script src="../../base/adapter.js"></script>
6
vikasmarwaha@webrtc.org98fce152013-02-27 23:22:10 +00007<script>
8var mystream;
9var pc1;
10var pc2;
11
12$ = function(id) {
13 return document.getElementById(id);
14}
15
16function log(txt) {
17 console.log(txt);
18}
19
20function openCamera() {
21 if (mystream) {
22 mystream.stop();
23 }
24 navigator.webkitGetUserMedia(cameraConstraints(), gotStream, function() {
25 log("GetUserMedia failed");
26 });
27}
28
29function gotStream(stream) {
30 log("GetUserMedia succeeded");
31 mystream = stream;
32 $("local-video").src = webkitURL.createObjectURL(stream);
33}
34
35function cameraConstraints() {
36 var constraints = {};
37 constraints.audio = true;
38 constraints.video = { mandatory: {}, optional: [] };
39 if ($("minwidth").value != "0") {
40 constraints.video.mandatory.minWidth = $("minwidth").value;
41 }
42 if ($("maxwidth").value != "0") {
43 constraints.video.mandatory.maxWidth = $("maxwidth").value;
44 }
45 if ($("minheight").value != "0") {
46 constraints.video.mandatory.minHeight = $("minheight").value;
47 }
48 if ($("maxheight").value != "0") {
49 constraints.video.mandatory.maxHeight = $("maxheight").value;
50 }
51 if ($("frameRate").value != "0") {
52 constraints.video.mandatory.minFrameRate = $("frameRate").value;
53 }
54 log('Camera constraints are ' + JSON.stringify(constraints));
55 $("cameraConstraints").innerHTML = JSON.stringify(constraints, null, ' ');
56 return constraints;
57}
58
59function streamConstraints() {
60 var constraints = { mandatory: {}, optional: [] };
61 if ($("bandwidth").value != "0") {
62 constraints.optional[0] = { 'bandwidth' : $('bandwidth').value };
63 }
64 log('Constraints are ' + JSON.stringify(constraints));
65 $("addStreamConstraints").innerHTML = JSON.stringify(constraints, null, ' ');
66 return constraints;
67}
68
69
70
71function connect() {
72 pc1 = new webkitRTCPeerConnection(null);
73 pc2 = new webkitRTCPeerConnection(null);
74 pc1.addStream(mystream, streamConstraints());
75 log('PC1 creating offer');
76 pc1.onnegotiationeeded = function() {
77 log('Negotiation needed - PC1');
78 }
79 pc2.onnegotiationeeded = function() {
80 log('Negotiation needed - PC2');
81 }
82 pc1.onicecandidate = function(e) {
83 log('Candidate PC1');
84 if (e.candidate) {
85 pc2.addIceCandidate(new RTCIceCandidate(e.candidate));
86 }
87 }
88 pc2.onicecandidate = function(e) {
89 log('Candidate PC2');
90 if (e.candidate) {
91 pc1.addIceCandidate(new RTCIceCandidate(e.candidate));
92 }
93 }
94 pc2.onaddstream = function(e) {
95 log('PC2 got stream');
96 $('remote-video').src = webkitURL.createObjectURL(e.stream);
97 log('Remote video is ' + $('remote-video').src);
98 }
99 pc1.createOffer(function(desc) {
100 log('PC1 offering');
101 pc1.setLocalDescription(desc);
102 pc2.setRemoteDescription(desc);
103 pc2.createAnswer(function(desc2) {
104 log('PC2 answering');
105 pc2.setLocalDescription(desc2);
106 pc1.setRemoteDescription(desc2);
107 });
108 });
109}
110
111// Display statistics
112var statCollector = setInterval(function() {
113 var display = function(str) {
114 $('bitrate').innerHTML = str;
115 }
116
117 display("No stream");
hta@webrtc.orgdb3f4272013-03-05 15:23:40 +0000118 if (pc2 && pc2.getRemoteStreams()[0]) {
vikasmarwaha@webrtc.org98fce152013-02-27 23:22:10 +0000119 if (pc2.getStats) {
120 display('No stats callback');
121 pc2.getStats(function(stats) {
122 log('Raw stats ' + stats);
123 var statsString = '';
124 var results = stats.result();
125 log('Raw results ' + results);
126 for (var i = 0; i < results.length; ++i) {
127 var res = results[i];
128 log(i + ': ' + JSON.stringify(res));
129 statsString += '<h3>Report ';
130 statsString += i;
131 statsString += '</h3>';
132 if (res.local) {
133 statsString += "<p>Local ";
134 statsString += dumpStats(res.local);
135 }
136 if (res.remote) {
137 statsString += "<p>Remote ";
138 statsString += dumpStats(res.remote);
139 }
140 }
141 $('stats').innerHTML = statsString;
142 display('No bitrate stats');
143 });
144 } else {
145 display('No stats function. Use at least Chrome 24.0.1285');
146 }
147 } else {
148 log('Not connected yet');
149 }
150 // Collect some stats from the video tags.
151 local_video = $('local-video');
152 if (local_video) {
153 $('local-video-stats').innerHTML = local_video.videoWidth +
154 'x' + local_video.videoHeight;
155 }
156 remote_video = $('remote-video');
157 if (remote_video) {
158 $('remote-video-stats').innerHTML = remote_video.videoWidth +
159 'x' + remote_video.videoHeight;
160 }
161}, 1000);
162
163// Dumping a stats variable as a string.
164// might be named toString?
165function dumpStats(obj) {
166 var statsString = 'Timestamp:';
167 statsString += obj.timestamp;
168 if (obj.names) {
169 log('Have names function');
170 names = obj.names();
171 for (var i = 0; i < names.length; ++i) {
172 statsString += '<br>';
173 statsString += names[i];
174 statsString += ':';
175 statsString += obj.stat(names[i]);
176 }
177 } else {
178 log('No names function');
179 if (obj.stat('audioOutputLevel')) {
180 statsString += "audioOutputLevel: ";
181 statsString += obj.stat('audioOutputLevel');
182 statsString += "<br>";
183 }
184 }
185 return statsString;
186}
187
188
189// Utility to show the value of a field in a span called name+Display
190function showValue(name, value) {
191 $(name + 'Display').innerHTML = value;
192}
193</script>
194</head>
195<body>
196<h1>Constraints and Statistics</h1>
197This page is meant to give some hints on how one can use constraints and statistics in WebRTC applications.
198<p>
199The form to the left gives constraints you can set on the getUserMedia call.
200When you hit "open", it will (re)open the camera with these constraints.
201<p>
202The left picture is the local preview. The right picture is the picture
203after being passed through the PeerConnection (locally).
204<p>
205Underneath the picture you will see a running display of how many Kbits/sec
206the video feed uses for transmission.
207<hr>
208<table>
209<tr>
210<td align="top">
211<h2>getUserMedia constraints</h2>
212<table>
213<tr><td><td>Min<td>Max
214<tr><td>Horizontal
215<td><input type="range" id="minwidth" min="0" max="1280" value="300"
216 onchange="showValue(this.id, this.value)">
217<td><input type="range" id="maxwidth" min="0" max="1280" value="640"
218 onchange="showValue(this.id, this.value)">
219<td><span id="minwidthDisplay">300</span>-<span id="maxwidthDisplay">640</span>
220<tr><td>Vertical
221<td><input type="range" id="minheight" min="0" max="1280" value="200"
222 onchange="showValue(this.id, this.value)">
223<td><input type="range" id="maxheight" min="0" max="1280" value="480"
224 onchange="showValue(this.id, this.value)">
225<td><span id="minheightDisplay">200</span>-<span id="maxheightDisplay">480</span>
226<tr><td>
227FrameRate
228<td colspan=2><input type="range" id="frameRate" min="0" max="60" value="30"
229 onchange="showValue(this.id, this.value)">
230<td><span id="frameRateDisplay">30</span>
231</table>
232<input type="submit" name="capture" value="Capture!" onclick="openCamera()">
233</td>
234<td align="top">
235<h2>addStream constraints</h2>
236Maximum bitrate
237<input type="range" id="bandwidth" min="0" max="2000" value="1000"
238 onchange="showValue(this.id, this.value)">
239<span id="bandwidthDisplay">1000</span>
240<br>
241<input type="submit" name="connect" value="Connect!" onclick="connect()">
242</td>
243</tr>
244<tr>
245<td>
vikasmarwaha@webrtc.orgda0f7082013-03-11 16:58:07 +0000246<video id="local-video" autoplay width=400 muted="true"></video>
vikasmarwaha@webrtc.org98fce152013-02-27 23:22:10 +0000247</td>
248<td>
249<video id="remote-video" autoplay width=400></video>
250</td>
251<tr>
252<td><span id="local-video-stats"></span>
253<td><span id="remote-video-stats"></span>
254<br>
255<span id="bitrate">Bitrate unknown</span>
256</td>
257</tr>
258<tr>
259<td><pre><span id="cameraConstraints"></span></pre>
260<td><pre><span id="addStreamConstraints"></span></pre>
261</table>
262<h2>Statistics report display</h2>
263<div id="stats">Stats will appear here.</div>
264</body>
265</html>