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