3 <script type="text/javascript" src="webrtc_test_utilities.js"></script>
4 <script type="text/javascript">
6 return document.getElementById(id);
9 setAllEventsOccuredHandler(function() {
13 function getSources() {
14 MediaStreamTrack.getSources(function(devices) {
15 document.title = 'Media devices available';
16 sendValueToTest(JSON.stringify(devices));
20 // Creates a MediaStream and renders it locally. When the video is detected to
21 // be rolling, the stream should be stopped.
22 function getUserMediaAndStop(constraints) {
23 console.log('Calling getUserMediaAndStop.');
24 navigator.webkitGetUserMedia(
27 detectVideoInLocalView1(stream, function() {
28 stream.getVideoTracks()[0].stop();
29 waitForVideoToStop('local-view-1');
35 // Requests getusermedia and expects it to fail. The error name is returned
37 function getUserMediaAndExpectFailure(constraints) {
38 console.log('Calling getUserMediaAndExpectFailure.');
39 navigator.webkitGetUserMedia(
41 function(stream) { failTest('Unexpectedly succeeded getUserMedia.'); },
42 function(error) { sendValueToTest(error.name); });
45 function renderClonedMediastreamAndStop(constraints, waitTimeInSeconds) {
46 console.log('Calling renderClonedMediastreamAndStop.');
47 navigator.webkitGetUserMedia(
50 var duplicate = stream.clone();
51 assertEquals(stream.getVideoTracks().length, 1);
52 assertEquals(duplicate.getVideoTracks().length, 1);
53 assertNotEquals(stream.getVideoTracks()[0].id,
54 duplicate.getVideoTracks()[0].id);
55 detectVideoInLocalView1(
64 function renderDuplicatedMediastreamAndStop(constraints, waitTimeInSeconds) {
65 console.log('Calling renderDuplicateMediastreamAndStop.');
66 navigator.webkitGetUserMedia(
69 var duplicate = new webkitMediaStream(stream);
70 assertEquals(stream.getVideoTracks().length, 1);
71 assertEquals(duplicate.getVideoTracks().length, 1);
72 assertEquals(stream.getVideoTracks()[0].id,
73 duplicate.getVideoTracks()[0].id);
74 detectVideoInLocalView1(
83 function renderSameTrackMediastreamAndStop(constraints, waitTimeInSeconds) {
84 console.log('Calling renderSameTrackMediastreamAndStop.');
85 navigator.webkitGetUserMedia(
88 var duplicate = new webkitMediaStream();
89 duplicate.addTrack(stream.getVideoTracks()[0]);
90 assertEquals(duplicate.getVideoTracks().length, 1);
91 assertEquals(duplicate.getVideoTracks().length, 1);
92 assertEquals(stream.getVideoTracks()[0].id,
93 duplicate.getVideoTracks()[0].id);
94 detectVideoInLocalView1(
103 function renderClonedTrackMediastreamAndStop(constraints, waitTimeInSeconds) {
104 console.log('Calling renderClonedTrackMediastreamAndStop.');
105 navigator.webkitGetUserMedia(
108 var duplicate = new webkitMediaStream();
109 duplicate.addTrack(stream.getVideoTracks()[0].clone());
110 assertEquals(duplicate.getVideoTracks().length, 1);
111 assertEquals(duplicate.getVideoTracks().length, 1);
112 assertNotEquals(stream.getVideoTracks()[0].id,
113 duplicate.getVideoTracks()[0].id)
114 detectVideoInLocalView1(
123 // Creates a MediaStream and renders it locally. When the video is detected to
124 // be rolling we report success. The acquired stream is stored in window
125 // under the name |streamName|.
126 function getUserMediaAndGetStreamUp(constraints, streamName) {
127 console.log('Calling getUserMediaAndGetStreamUp.');
128 navigator.webkitGetUserMedia(
131 window[streamName] = stream;
132 detectVideoInLocalView1(
141 function getUserMediaAndRenderInSeveralVideoTags() {
142 navigator.webkitGetUserMedia(
144 createMultipleVideoRenderersAndPause,
145 function(error) { failedCallback(); });
148 // Gets a video stream up, analyses it and returns the aspect ratio to the
149 // test through the automation controller.
150 function getUserMediaAndAnalyseAndStop(constraints) {
151 console.log('Calling getUserMediaAndAnalyseAndStop.');
152 navigator.webkitGetUserMedia(
153 constraints, displayDetectAndAnalyzeVideo, failedCallback);
156 // This test that a MediaStream can be cloned and that the clone can
158 function getUserMediaAndClone() {
159 console.log('Calling getUserMediaAndClone.');
160 navigator.webkitGetUserMedia({video: true, audio: true},
161 createAndRenderClone, failedCallback);
164 // Creates two MediaStream and renders them locally. When the video of both
165 // streams are detected to be rolling, we stop the local video tracks one at
166 // the time. In particular, we verify that stopping one track does not stop
168 function twoGetUserMediaAndStop(constraints) {
171 navigator.webkitGetUserMedia(
175 attachMediaStream(stream, 'local-view-1');
176 requestSecondGetUserMedia();
179 var requestSecondGetUserMedia = function() {
180 navigator.webkitGetUserMedia(
184 attachMediaStream(stream, 'local-view-2');
185 stopBothVideoTracksAndVerify();
190 var stopBothVideoTracksAndVerify = function() {
191 // Stop track 2, ensure track 2 stops but not track 1, then stop track 1.
192 stream2.getVideoTracks()[0].stop();
193 detectVideoStopped('local-view-2', function() {
194 detectVideoInLocalView1(stream1, function() {
195 stream1.getVideoTracks()[0].stop();
196 waitForVideoToStop('local-view-1');
202 function twoGetUserMedia(constraints1, constraints2) {
204 navigator.webkitGetUserMedia(
207 displayDetectAndAnalyzeVideoInElement(
209 function(aspectRatio) {
210 result = aspectRatio;
211 requestSecondGetUserMedia();
216 var requestSecondGetUserMedia = function() {
217 navigator.webkitGetUserMedia(
220 displayDetectAndAnalyzeVideoInElement(
222 function(aspectRatio) {
223 result = result + '-' + aspectRatio;
224 sendValueToTest(result);
232 // Calls GetUserMedia twice and verify that the frame rate is as expected for
234 function twoGetUserMediaAndVerifyFrameRate(constraints1,
236 expected_frame_rate1,
237 expected_frame_rate2) {
240 var validateFrameRateCallback = function (success) {
242 failTest("Failed to validate frameRate.");
246 navigator.webkitGetUserMedia(
249 requestSecondGetUserMedia();
250 attachMediaStream(stream, 'local-view-1');
254 validateFrameRate('local-view-1', expected_frame_rate1,
255 validateFrameRateCallback);
259 var requestSecondGetUserMedia = function() {
260 navigator.webkitGetUserMedia(
263 attachMediaStream(stream, 'local-view-2');
267 validateFrameRate('local-view-2', expected_frame_rate2,
268 validateFrameRateCallback);
275 function failedCallback(error) {
276 failTest('GetUserMedia call failed with code ' + error.code);
279 function attachMediaStream(stream, videoElement) {
280 var localStreamUrl = URL.createObjectURL(stream);
281 $(videoElement).src = localStreamUrl;
284 function detectVideoInLocalView1(stream, callback) {
285 attachMediaStream(stream, 'local-view-1');
286 detectVideoPlaying('local-view-1', callback);
289 function displayDetectAndAnalyzeVideo(stream) {
290 displayDetectAndAnalyzeVideoInElement(stream,
291 function(aspectRatio) {
292 sendValueToTest(aspectRatio);
297 function displayDetectAndAnalyzeVideoInElement(
298 stream, callback, videoElement) {
299 attachMediaStream(stream, videoElement);
300 detectAspectRatio(callback, videoElement);
303 function createAndRenderClone(stream) {
304 // TODO(perkj): --use-fake-device-for-media-stream do not currently
305 // work with audio devices and not all bots has a microphone.
306 newStream = new webkitMediaStream();
307 newStream.addTrack(stream.getVideoTracks()[0]);
308 assertEquals(newStream.getVideoTracks().length, 1);
309 if (stream.getAudioTracks().length > 0) {
310 newStream.addTrack(stream.getAudioTracks()[0]);
311 assertEquals(newStream.getAudioTracks().length, 1);
312 newStream.removeTrack(newStream.getAudioTracks()[0]);
313 assertEquals(newStream.getAudioTracks().length, 0);
316 detectVideoInLocalView1(newStream, reportTestSuccess);
319 // Calls stop on |stream|'s video track after a delay and reports success.
320 function waitAndStopVideoTrack(stream, waitTimeInSeconds) {
321 setTimeout(function() {
322 stream.getVideoTracks()[0].stop();
324 }, waitTimeInSeconds * 1000);
327 // This test make sure multiple video renderers can be created for the same
328 // local video track and make sure a renderer can still render if other
329 // renderers are paused. See http://crbug/352619.
330 function createMultipleVideoRenderersAndPause(stream) {
331 function createDetectableRenderer(stream, id) {
332 var video = document.createElement('video');
333 document.body.appendChild(video);
334 var localStreamUrl = URL.createObjectURL(stream);
336 video.src = localStreamUrl;
337 video.autoplay = true;
339 // The detector needs a canvas.
340 var canvas = document.createElement('canvas');
341 canvas.id = video.id + "-canvas";
342 document.body.appendChild(canvas);
345 // Once 3 renderers are created and paused, create one last renderer and
346 // make sure it can play video.
347 setAllEventsOccuredHandler(function() {
348 var id = "lastVideoTag";
349 createDetectableRenderer(stream, id);
350 detectVideoPlaying(id, function () { reportTestSuccess(); });
353 // Create 3 video renderers and pause them once video is playing.
354 for (var i = 0; i < 3; ++i) {
355 var id = "video" + i;
356 createDetectableRenderer(stream, id);
358 // |video_detected_function| creates a new function that pause the video
360 var video_detected_function =
363 console.log("pause " + j);
368 // Detect video id |id| and trigger the function returned by
369 // |video_detected_function| when video is playing.
370 detectVideoPlaying(id, video_detected_function(id));
374 // This function tries to calculate the aspect ratio shown by the fake capture
375 // device in the video tag. For this, we count the amount of light green
376 // pixels along |aperture| pixels on the positive X and Y axis starting from
377 // the center of the image. In this very center there should be a time-varying
378 // pacman; the algorithm counts for a couple of iterations and keeps the
379 // maximum amount of light green pixels on both directions. From this data
380 // the aspect ratio is calculated and the test fails if the number of green
381 // pixels are not the same along the X and Y axis.
382 // The result of the analysis is sent back to the test as a string on the
383 // format "w=xxx:h=yyy".
384 function detectAspectRatio(callback, videoElementName) {
385 var videoElement = $(videoElementName);
386 var canvas = $(videoElementName + '-canvas');
388 var maxLightGreenPixelsX = 0;
389 var maxLightGreenPixelsY = 0;
392 var maxAttempts = 10;
394 var detectorFunction = function() {
395 var width = videoElement.videoWidth;
396 var height = videoElement.videoHeight;
397 if (width == 0 || height == 0)
400 canvas.width = width;
401 canvas.height = height;
402 var aperture = Math.min(width, height) / 2;
403 var context = canvas.getContext('2d');
404 context.drawImage(videoElement, 0, 0, width, height);
406 // We are interested in a window starting from the center of the image
407 // where we expect the circle from the fake video capture to be rolling.
408 var pixels = context.getImageData(width / 2, height / 2,
411 var lightGreenPixelsX = 0;
412 var lightGreenPixelsY = 0;
414 // Walk horizontally counting light green pixels.
415 for (var x = 0; x < aperture; ++x) {
416 if (pixels.data[4 * x + 1] != COLOR_BACKGROUND_GREEN)
419 // Walk vertically counting light green pixels.
420 for (var y = 0; y < aperture; ++y) {
421 if (pixels.data[4 * y * aperture + 1] != COLOR_BACKGROUND_GREEN)
424 if (lightGreenPixelsX > maxLightGreenPixelsX)
425 maxLightGreenPixelsX = lightGreenPixelsX;
426 if (lightGreenPixelsY > maxLightGreenPixelsY)
427 maxLightGreenPixelsY = lightGreenPixelsY;
429 // Allow maxLightGreenPixelsY = maxLightGreenPixelsX +-1 due to
430 // possible subpixel rendering on Mac and Android.
431 if (maxLightGreenPixelsY > maxLightGreenPixelsX + 1 ||
432 maxLightGreenPixelsY < maxLightGreenPixelsX -1 ||
433 maxLightGreenPixelsY == 0 ||
434 maxLightGreenPixelsX == width / 2 ||
435 maxLightGreenPixelsY == height / 2) {
436 if (++attempt > maxAttempts) {
437 clearInterval(detectorInterval);
438 failTest("Aspect ratio corrupted. X " + maxLightGreenPixelsX +
439 " Y " + maxLightGreenPixelsY);
442 // We have a bad aspect ratio now; give a chance to shape up.
447 clearInterval(detectorInterval);
448 var result = "w=" + width + ":h=" + height;
451 var detectorInterval = setInterval(detectorFunction, 50);
457 <!-- Canvases are named after their corresponding video elements. -->
459 <td><video id="local-view-1" width="320" height="240" autoplay
460 style="display:none"></video></td>
461 <td><canvas id="local-view-1-canvas" width="320" height="240"
462 style="display:none"></canvas></td>
465 <td><video id="local-view-2" width="320" height="240" autoplay
466 style="display:none"></video></td>
467 <td><canvas id="local-view-2-canvas" width="320" height="240"
468 style="display:none"></canvas></td>