Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / test / data / media / getusermedia.html
1 <html>
2 <head>
3   <script type="text/javascript" src="webrtc_test_utilities.js"></script>
4   <script type="text/javascript">
5   $ = function(id) {
6     return document.getElementById(id);
7   };
8
9   setAllEventsOccuredHandler(function() {
10     reportTestSuccess();
11   });
12
13   function getSources() {
14     MediaStreamTrack.getSources(function(devices) {
15       document.title = 'Media devices available';
16       sendValueToTest(JSON.stringify(devices));
17     });
18   }
19
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(
25         constraints,
26         function(stream) {
27           detectVideoInLocalView1(stream, function() {
28             stream.getVideoTracks()[0].stop();
29             waitForVideoToStop('local-view-1');
30           });
31         },
32         failedCallback);
33   }
34
35   // Requests getusermedia and expects it to fail. The error name is returned
36   // to the test.
37   function getUserMediaAndExpectFailure(constraints) {
38     console.log('Calling getUserMediaAndExpectFailure.');
39     navigator.webkitGetUserMedia(
40         constraints,
41         function(stream) { failTest('Unexpectedly succeeded getUserMedia.'); },
42         function(error) { sendValueToTest(error.name); });
43   }
44
45   function renderClonedMediastreamAndStop(constraints, waitTimeInSeconds) {
46     console.log('Calling renderClonedMediastreamAndStop.');
47     navigator.webkitGetUserMedia(
48         constraints,
49         function(stream) {
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(
56             stream,
57             function() {
58               reportTestSuccess();
59             });
60         },
61         failedCallback);
62   }
63
64   function renderDuplicatedMediastreamAndStop(constraints, waitTimeInSeconds) {
65     console.log('Calling renderDuplicateMediastreamAndStop.');
66     navigator.webkitGetUserMedia(
67         constraints,
68         function(stream) {
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(
75             duplicate,
76             function() {
77               reportTestSuccess();
78             });
79         },
80         failedCallback);
81   }
82
83   function renderSameTrackMediastreamAndStop(constraints, waitTimeInSeconds) {
84     console.log('Calling renderSameTrackMediastreamAndStop.');
85     navigator.webkitGetUserMedia(
86         constraints,
87         function(stream) {
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(
95             duplicate,
96             function() {
97               reportTestSuccess();
98             });
99         },
100         failedCallback);
101   }
102
103   function renderClonedTrackMediastreamAndStop(constraints, waitTimeInSeconds) {
104     console.log('Calling renderClonedTrackMediastreamAndStop.');
105     navigator.webkitGetUserMedia(
106         constraints,
107         function(stream) {
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(
115             duplicate,
116             function() {
117               reportTestSuccess();
118             });
119         },
120         failedCallback);
121   }
122
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(
129         constraints,
130         function(stream) {
131           window[streamName] = stream;
132           detectVideoInLocalView1(
133             stream,
134             function() {
135               reportTestSuccess();
136             });
137         },
138         failedCallback);
139   }
140
141   function getUserMediaAndRenderInSeveralVideoTags() {
142     navigator.webkitGetUserMedia(
143         {video: true},
144         createMultipleVideoRenderersAndPause,
145         function(error) { failedCallback(); });
146   }
147
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);
154   }
155
156   // This test that a MediaStream can be cloned and that the clone can
157   // be rendered.
158   function getUserMediaAndClone() {
159     console.log('Calling getUserMediaAndClone.');
160     navigator.webkitGetUserMedia({video: true, audio: true},
161         createAndRenderClone, failedCallback);
162   }
163
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
167   // the other.
168   function twoGetUserMediaAndStop(constraints) {
169     var stream1 = null;
170     var stream2 = null;
171     navigator.webkitGetUserMedia(
172         constraints,
173         function(stream) {
174           stream1 = stream;
175           attachMediaStream(stream, 'local-view-1');
176           requestSecondGetUserMedia();
177         },
178         failedCallback);
179     var requestSecondGetUserMedia = function() {
180       navigator.webkitGetUserMedia(
181           constraints,
182           function(stream) {
183             stream2 = stream;
184             attachMediaStream(stream, 'local-view-2');
185             stopBothVideoTracksAndVerify();
186           },
187           failedCallback);
188     };
189
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');
197         });
198       });
199     };
200   }
201
202   function twoGetUserMedia(constraints1, constraints2) {
203     var result="";
204     navigator.webkitGetUserMedia(
205         constraints1,
206         function(stream) {
207           displayDetectAndAnalyzeVideoInElement(
208               stream,
209               function(aspectRatio) {
210                 result = aspectRatio;
211                 requestSecondGetUserMedia();
212               },
213               'local-view-1');
214         },
215         failedCallback);
216     var requestSecondGetUserMedia = function() {
217       navigator.webkitGetUserMedia(
218           constraints2,
219           function(stream) {
220             displayDetectAndAnalyzeVideoInElement(
221                 stream,
222                 function(aspectRatio) {
223                   result = result + '-' + aspectRatio;
224                   sendValueToTest(result);
225                 },
226                 'local-view-2');
227           },
228           failedCallback);
229     }
230   }
231
232   // Calls GetUserMedia twice and verify that the frame rate is as expected for
233   // both streams.
234   function twoGetUserMediaAndVerifyFrameRate(constraints1,
235                                              constraints2,
236                                              expected_frame_rate1,
237                                              expected_frame_rate2) {
238     addExpectedEvent();
239     addExpectedEvent();
240     var validateFrameRateCallback = function (success) {
241       if (!success)
242         failTest("Failed to validate frameRate.");
243       eventOccured();
244     };
245
246     navigator.webkitGetUserMedia(
247         constraints1,
248         function(stream) {
249           requestSecondGetUserMedia();
250           attachMediaStream(stream, 'local-view-1');
251           detectVideoPlaying(
252               'local-view-1',
253               function() {
254                 validateFrameRate('local-view-1', expected_frame_rate1,
255                                   validateFrameRateCallback);
256               });
257         },
258         failedCallback);
259     var requestSecondGetUserMedia = function() {
260       navigator.webkitGetUserMedia(
261           constraints2,
262           function(stream) {
263             attachMediaStream(stream, 'local-view-2');
264             detectVideoPlaying(
265                 'local-view-2',
266                 function() {
267                   validateFrameRate('local-view-2', expected_frame_rate2,
268                                     validateFrameRateCallback);
269                 });
270           },
271           failedCallback);
272     }
273   }
274
275   function failedCallback(error) {
276     failTest('GetUserMedia call failed with code ' + error.code);
277   }
278
279   function attachMediaStream(stream, videoElement) {
280     var localStreamUrl = URL.createObjectURL(stream);
281     $(videoElement).src = localStreamUrl;
282   }
283
284   function detectVideoInLocalView1(stream, callback) {
285     attachMediaStream(stream, 'local-view-1');
286     detectVideoPlaying('local-view-1', callback);
287   }
288
289   function displayDetectAndAnalyzeVideo(stream) {
290     displayDetectAndAnalyzeVideoInElement(stream,
291         function(aspectRatio) {
292           sendValueToTest(aspectRatio);
293         },
294         'local-view-1');
295   }
296
297   function displayDetectAndAnalyzeVideoInElement(
298       stream, callback, videoElement) {
299     attachMediaStream(stream, videoElement);
300     detectAspectRatio(callback, videoElement);
301   }
302
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);
314     }
315
316     detectVideoInLocalView1(newStream, reportTestSuccess);
317   }
318
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();
323       reportTestSuccess();
324     }, waitTimeInSeconds * 1000);
325   }
326
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);
335       video.id = id;
336       video.src = localStreamUrl;
337       video.autoplay = true;
338       video.play();
339       // The detector needs a canvas.
340       var canvas = document.createElement('canvas');
341       canvas.id = video.id + "-canvas";
342       document.body.appendChild(canvas);
343     };
344
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(); });
351     });
352
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);
357       addExpectedEvent();
358       // |video_detected_function| creates a new function that pause the video
359       // tag |id|.
360       var video_detected_function =
361           function (j) {
362             return function () {
363               console.log("pause " + j);
364               $(j).pause();
365               eventOccured();
366            };
367           };
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));
371      }
372    }
373
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');
387
388     var maxLightGreenPixelsX = 0;
389     var maxLightGreenPixelsY = 0;
390
391     var attempt = 0;
392     var maxAttempts = 10;
393
394     var detectorFunction = function() {
395       var width = videoElement.videoWidth;
396       var height = videoElement.videoHeight;
397       if (width == 0 || height == 0)
398         return;
399
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);
405
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,
409                                         aperture, aperture);
410
411       var lightGreenPixelsX = 0;
412       var lightGreenPixelsY = 0;
413
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)
417           lightGreenPixelsX++;
418       }
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)
422           lightGreenPixelsY++;
423       }
424       if (lightGreenPixelsX > maxLightGreenPixelsX)
425         maxLightGreenPixelsX = lightGreenPixelsX;
426       if (lightGreenPixelsY > maxLightGreenPixelsY)
427         maxLightGreenPixelsY = lightGreenPixelsY;
428
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);
440         }
441         else {
442           // We have a bad aspect ratio now; give a chance to shape up.
443           return;
444         }
445       }
446
447       clearInterval(detectorInterval);
448       var result = "w=" + width + ":h=" + height;
449       callback(result);
450     }
451     var detectorInterval = setInterval(detectorFunction, 50);
452   }
453   </script>
454 </head>
455 <body>
456   <table border="0">
457     <!-- Canvases are named after their corresponding video elements. -->
458     <tr>
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>
463     </tr>
464     <tr>
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>
469     </tr>
470   </table>
471 </body>
472 </html>