3 <script type=
"text/javascript" src=
"webrtc_test_utilities.js"></script>
4 <script type=
"text/javascript">
6 return document
.getElementById(id
);
9 var gLocalStream
= null;
11 setAllEventsOccuredHandler(function() {
16 function getSources() {
17 MediaStreamTrack
.getSources(function(devices
) {
18 document
.title
= 'Media devices available';
19 sendValueToTest(JSON
.stringify(devices
));
23 // Creates a MediaStream and renders it locally. When the video is detected to
24 // be rolling, the stream should be stopped.
25 function getUserMediaAndStop(constraints
) {
26 console
.log('Calling getUserMediaAndStop.');
27 navigator
.webkitGetUserMedia(
29 function(stream
) { displayAndDetectVideo(stream
, stopVideoTrack
); },
33 // Requests getusermedia and expects it to fail. The error name is returned
35 function getUserMediaAndExpectFailure(constraints
) {
36 console
.log('Calling getUserMediaAndExpectFailure.');
37 navigator
.webkitGetUserMedia(
39 function(stream
) { failTest('Unexpectedly succeeded getUserMedia.'); },
40 function(error
) { sendValueToTest(error
.name
); });
43 function renderClonedMediastreamAndStop(constraints
, waitTimeInSeconds
) {
44 console
.log('Calling renderClonedMediastreamAndStop.');
45 navigator
.webkitGetUserMedia(
48 var s
= stream
.clone();
49 assertEquals(stream
.getVideoTracks().length
, 1);
50 assertEquals(s
.getVideoTracks().length
, 1);
51 assertNotEquals(stream
.getVideoTracks()[0].id
,
52 s
.getVideoTracks()[0].id
);
53 displayAndDetectVideo(
62 function renderDuplicatedMediastreamAndStop(constraints
, waitTimeInSeconds
) {
63 console
.log('Calling renderDuplicateMediastreamAndStop.');
64 navigator
.webkitGetUserMedia(
67 s
= new webkitMediaStream(stream
);
68 assertEquals(stream
.getVideoTracks().length
, 1);
69 assertEquals(s
.getVideoTracks().length
, 1);
70 assertEquals(stream
.getVideoTracks()[0].id
,
71 s
.getVideoTracks()[0].id
);
72 displayAndDetectVideo(
81 function renderSameTrackMediastreamAndStop(constraints
, waitTimeInSeconds
) {
82 console
.log('Calling renderSameTrackMediastreamAndStop.');
83 navigator
.webkitGetUserMedia(
86 s
= new webkitMediaStream();
87 s
.addTrack(stream
.getVideoTracks()[0]);
88 assertEquals(s
.getVideoTracks().length
, 1);
89 assertEquals(s
.getVideoTracks().length
, 1);
90 assertEquals(stream
.getVideoTracks()[0].id
, s
.getVideoTracks()[0].id
);
91 displayAndDetectVideo(
100 function renderClonedTrackMediastreamAndStop(constraints
, waitTimeInSeconds
) {
101 console
.log('Calling renderClonedTrackMediastreamAndStop.');
102 navigator
.webkitGetUserMedia(
105 s
= new webkitMediaStream();
106 s
.addTrack(stream
.getVideoTracks()[0].clone());
107 assertEquals(s
.getVideoTracks().length
, 1);
108 assertEquals(s
.getVideoTracks().length
, 1);
109 assertNotEquals(stream
.getVideoTracks()[0].id
,
110 s
.getVideoTracks()[0].id
)
111 displayAndDetectVideo(
120 // Creates a MediaStream and renders it locally. When the video is detected to
121 // be rolling we return ok-stream-running through the automation controller.
122 function getUserMediaAndGetStreamUp(constraints
, waitTimeInSeconds
) {
123 console
.log('Calling getUserMediaAndGetStreamUp.');
124 navigator
.webkitGetUserMedia(
127 displayAndDetectVideo(
136 function getUserMediaAndRenderInSeveralVideoTags() {
137 navigator
.webkitGetUserMedia(
139 createMultipleVideoRenderersAndPause
,
140 function(error
) { failedCallback(); });
143 // Gets a video stream up, analyses it and returns the aspect ratio to the
144 // test through the automation controller.
145 function getUserMediaAndAnalyseAndStop(constraints
) {
146 console
.log('Calling getUserMediaAndAnalyseAndStop.');
147 navigator
.webkitGetUserMedia(
148 constraints
, displayDetectAndAnalyzeVideo
, failedCallback
);
151 // This test that a MediaStream can be cloned and that the clone can
153 function getUserMediaAndClone() {
154 console
.log('Calling getUserMediaAndClone.');
155 navigator
.webkitGetUserMedia({video
: true, audio
: true},
156 createAndRenderClone
, failedCallback
);
159 // Creates two MediaStream and renders them locally. When the video of both
160 // streams are detected to be rolling, we stop the local video tracks one at
162 function twoGetUserMediaAndStop(constraints
) {
163 console
.log('Calling Two GetUserMedia');
164 navigator
.webkitGetUserMedia(
167 displayAndDetectVideo(stream
, requestSecondGetUserMedia
);
170 var requestSecondGetUserMedia = function() {
171 navigator
.webkitGetUserMedia(
174 displayIntoVideoElement(stream
,
176 stopBothVideoTracksAndVerify(stream
);
183 var stopBothVideoTracksAndVerify = function(streamPlayingInLocalView2
) {
184 streamPlayingInLocalView2
.getVideoTracks()[0].stop();
185 waitForVideoToStop('local-view-2');
186 // Make sure the video track in gLocalStream is still playing in
187 // 'local-view1' and then stop it.
188 displayAndDetectVideo(gLocalStream
, stopVideoTrack
);
192 function twoGetUserMedia(constraints1
,
195 navigator
.webkitGetUserMedia(
198 displayDetectAndAnalyzeVideoInElement(
200 function(aspectRatio
) {
201 result
= aspectRatio
;
202 requestSecondGetUserMedia();
207 var requestSecondGetUserMedia = function() {
208 navigator
.webkitGetUserMedia(
211 displayDetectAndAnalyzeVideoInElement(
213 function(aspectRatio
) {
214 result
= result
+ '-' + aspectRatio
;
215 sendValueToTest(result
);
223 // Calls GetUserMedia twice and verify that the frame rate is as expected for
225 function twoGetUserMediaAndVerifyFrameRate(constraints1
,
227 expected_frame_rate1
,
228 expected_frame_rate2
) {
231 var validateFrameRateCallback = function (success
) {
233 failTest("Failed to validate frameRate.");
237 navigator
.webkitGetUserMedia(
240 requestSecondGetUserMedia();
241 plugStreamIntoVideoElement(stream
, 'local-view');
242 detectVideoPlaying('local-view',
244 validateFrameRate('local-view', expected_frame_rate1
,
245 validateFrameRateCallback
);
249 var requestSecondGetUserMedia = function() {
250 navigator
.webkitGetUserMedia(
253 plugStreamIntoVideoElement(stream
, 'local-view-2');
254 detectVideoPlaying('local-view-2',
256 validateFrameRate('local-view-2', expected_frame_rate2
,
257 validateFrameRateCallback
);
264 function failedCallback(error
) {
265 failTest('GetUserMedia call failed with code ' + error
.code
);
268 function plugStreamIntoVideoElement(stream
, videoElement
) {
269 gLocalStream
= stream
;
270 var localStreamUrl
= URL
.createObjectURL(stream
);
271 $(videoElement
).src
= localStreamUrl
;
274 function displayIntoVideoElement(stream
, callback
, videoElement
) {
275 plugStreamIntoVideoElement(stream
, videoElement
);
276 detectVideoPlaying(videoElement
, callback
);
279 function displayAndDetectVideo(stream
, callback
) {
280 displayIntoVideoElement(stream
, callback
, 'local-view');
283 function displayDetectAndAnalyzeVideo(stream
) {
284 displayDetectAndAnalyzeVideoInElement(stream
,
285 function(aspectRatio
) {
286 sendValueToTest(aspectRatio
);
291 function displayDetectAndAnalyzeVideoInElement(
292 stream
, callback
, videoElement
) {
293 plugStreamIntoVideoElement(stream
, videoElement
);
294 detectAspectRatio(callback
, videoElement
);
297 function createAndRenderClone(stream
) {
298 gLocalStream
= stream
;
299 // TODO(perkj): --use-fake-device-for-media-stream do not currently
300 // work with audio devices and not all bots has a microphone.
301 new_stream
= new webkitMediaStream();
302 new_stream
.addTrack(stream
.getVideoTracks()[0]);
303 assertEquals(new_stream
.getVideoTracks().length
, 1);
304 if (stream
.getAudioTracks().length
> 0) {
305 new_stream
.addTrack(stream
.getAudioTracks()[0]);
306 assertEquals(new_stream
.getAudioTracks().length
, 1);
307 new_stream
.removeTrack(new_stream
.getAudioTracks()[0]);
308 assertEquals(new_stream
.getAudioTracks().length
, 0);
311 var newStreamUrl
= URL
.createObjectURL(new_stream
);
312 $('local-view').src
= newStreamUrl
;
313 waitForVideo('local-view');
316 function stopVideoTrack() {
317 gLocalStream
.getVideoTracks()[0].stop();
318 waitForVideoToStop('local-view');
321 function waitAndStopVideoTrack(waitTimeInSeconds
) {
322 setTimeout(stopVideoTrack
, waitTimeInSeconds
* 1000);
325 // This test make sure multiple video renderers can be created for the same
326 // local video track and make sure a renderer can still render if other
327 // renderers are paused. See http://crbug/352619.
328 function createMultipleVideoRenderersAndPause(stream
) {
329 function createDetectableRenderer(stream
, id
) {
330 var video
= document
.createElement('video');
331 document
.body
.appendChild(video
);
332 var localStreamUrl
= URL
.createObjectURL(stream
);
334 video
.src
= localStreamUrl
;
335 video
.autoplay
= true;
337 // The detector needs a canvas.
338 var canvas
= document
.createElement('canvas');
339 canvas
.id
= video
.id
+ "-canvas";
340 document
.body
.appendChild(canvas
);
343 // Once 3 renderers are created and paused, create one last renderer and
344 // make sure it can play video.
345 setAllEventsOccuredHandler(function() {
346 var id
= "lastVideoTag";
347 createDetectableRenderer(stream
, id
);
348 detectVideoPlaying(id
, function () { reportTestSuccess(); });
351 // Create 3 video renderers and pause them once video is playing.
352 for (var i
= 0; i
< 3; ++i
) {
353 var id
= "video" + i
;
354 createDetectableRenderer(stream
, id
);
356 // |video_detected_function| creates a new function that pause the video
358 var video_detected_function
=
361 console
.log("pause " + j
);
366 // Detect video id |id| and trigger the function returned by
367 // |video_detected_function| when video is playing.
368 detectVideoPlaying(id
, video_detected_function(id
));
372 // This function tries to calculate the aspect ratio shown by the fake capture
373 // device in the video tag. For this, we count the amount of light green
374 // pixels along |aperture| pixels on the positive X and Y axis starting from
375 // the center of the image. In this very center there should be a time-varying
376 // pacman; the algorithm counts for a couple of iterations and keeps the
377 // maximum amount of light green pixels on both directions. From this data
378 // the aspect ratio is calculated and the test fails if the number of green
379 // pixels are not the same along the X and Y axis.
380 // The result of the analysis is sent back to the test as a string on the
381 // format "w=xxx:h=yyy".
382 function detectAspectRatio(callback
, videoElementName
) {
383 var videoElement
= $(videoElementName
);
384 var canvas
= $(videoElementName
+ '-canvas');
386 var maxLightGreenPixelsX
= 0;
387 var maxLightGreenPixelsY
= 0;
390 var maxIterations
= 10;
392 var detectorFunction = function() {
393 var width
= videoElement
.videoWidth
;
394 var height
= videoElement
.videoHeight
;
395 if (width
== 0 || height
== 0)
398 canvas
.width
= width
;
399 canvas
.height
= height
;
400 var aperture
= Math
.min(width
, height
) / 2;
401 var context
= canvas
.getContext('2d');
402 context
.drawImage(videoElement
, 0, 0, width
, height
);
404 // We are interested in a window starting from the center of the image
405 // where we expect the circle from the fake video capture to be rolling.
406 var pixels
= context
.getImageData(width
/ 2, height
/ 2,
409 var lightGreenPixelsX
= 0;
410 var lightGreenPixelsY
= 0;
412 // Walk horizontally counting light green pixels.
413 for (var x
= 0; x
< aperture
; ++x
) {
414 if (pixels
.data
[4 * x
+ 1] != COLOR_BACKGROUND_GREEN
)
417 // Walk vertically counting light green pixels.
418 for (var y
= 0; y
< aperture
; ++y
) {
419 if (pixels
.data
[4 * y
* aperture
+ 1] != COLOR_BACKGROUND_GREEN
)
422 if (lightGreenPixelsX
> maxLightGreenPixelsX
)
423 maxLightGreenPixelsX
= lightGreenPixelsX
;
424 if (lightGreenPixelsY
> maxLightGreenPixelsY
)
425 maxLightGreenPixelsY
= lightGreenPixelsY
;
427 if (++iterations
> maxIterations
) {
428 clearInterval(detectorInterval
);
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 failTest("Aspect ratio corrupted. X " + maxLightGreenPixelsX
+
437 " Y " + maxLightGreenPixelsY
);
440 var result
= "w=" + width
+ ":h=" + height
;
445 var detectorInterval
= setInterval(detectorFunction
, 50);
452 <td>Local Preview
</td>
455 <td><video width=
"320" height=
"240" id=
"local-view"
456 autoplay=
"autoplay"></video></td>
457 <td><canvas id=
"local-view-canvas"
458 style=
"display:none"></canvas></td>
461 <td>Local Preview
2</td>
464 <td><video width=
"320" height=
"240" id=
"local-view-2"
465 autoplay=
"autoplay"></video></td>
466 <!-- Canvases are named after their corresponding video elements. -->
467 <td><canvas width=
"320" height=
"240" id=
"local-view-2-canvas"
468 style=
"display:none"></canvas></td>