Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / chrome / test / data / webrtc / video_extraction.js
blob0436673f52837dcf85b3d96f8b678192b83f4bf2
1 /**
2  * Copyright (c) 2012 The Chromium Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
7 /**
8  * The gStartedAt when the capturing begins. Used for timeout adjustments.
9  * @private
10  */
11 var gStartedAt = 0;
13 /**
14  * The duration of the all frame capture in milliseconds.
15  * @private
16  */
17 var gCaptureDuration = 0;
19 /**
20  * The time interval at which the video is sampled.
21  * @private
22  */
23 var gFrameCaptureInterval = 0;
25 /**
26  * The global array of frames. Frames are pushed, i.e. this should be treated as
27  * a queue and we should read from the start.
28  * @private
29  */
30 var gFrames = [];
32 /**
33  * We need to skip the first two frames due to timing issues.
34  * @private
35  */
36 var gHasThrownAwayFirstTwoFrames = false;
38 /**
39  * We need this global variable to synchronize with the test how long to run the
40  * call between the two peers.
41  */
42 var gDoneFrameCapturing = false;
44 /**
45  * Starts the frame capturing.
46  *
47  * @param {!Object} The video tag from which the height and width parameters are
48                     to be extracted.
49  * @param {Number} The frame rate at which we would like to capture frames.
50  * @param {Number} The duration of the frame capture in seconds.
51  */
52 function startFrameCapture(videoTag, frameRate, duration) {
53   gFrameCaptureInterval = 1000 / frameRate;
54   gCaptureDuration = 1000 * duration;
55   var width = videoTag.videoWidth;
56   var height = videoTag.videoHeight;
58   if (width == 0 || height == 0) {
59     throw failTest('Trying to capture from ' + videoTag.id +
60                    ' but it is not playing any video.');
61   }
63   console.log('Received width is: ' + width + ', received height is: ' + height
64               + ', capture interval is: ' + gFrameCaptureInterval +
65               ', duration is: ' + gCaptureDuration);
67   var remoteCanvas = document.createElement('canvas');
68   remoteCanvas.width = width;
69   remoteCanvas.height = height;
70   document.body.appendChild(remoteCanvas);
72   gStartedAt = new Date().getTime();
73   gFrames = [];
74   setTimeout(function() { shoot_(videoTag, remoteCanvas, width, height); },
75              gFrameCaptureInterval);
78 /**
79  * Queries if we're done with the frame capturing yet.
80  */
81 function doneFrameCapturing() {
82   if (gDoneFrameCapturing) {
83     returnToTest('done-capturing');
84   } else {
85     returnToTest('still-capturing');
86   }
89 /**
90  * Retrieves the number of captured frames.
91  */
92 function getTotalNumberCapturedFrames() {
93   returnToTest(gFrames.length.toString());
96 /**
97  * Retrieves one captured frame in ARGB format as a base64-encoded string.
98  *
99  * Also updates the page's progress bar.
101  * @param frameIndex A frame index in the range 0 to total-1 where total is
102  *     given by getTotalNumberCapturedFrames.
103  */
104 function getOneCapturedFrame(frameIndex) {
105   var codedFrame = convertArrayBufferToBase64String_(gFrames[frameIndex]);
106   updateProgressBar_(frameIndex);
107   silentReturnToTest(codedFrame);
111  * @private
113  * @param {ArrayBuffer} buffer An array buffer to convert to a base 64 string.
114  * @return {String} A base 64 string.
115  */
116 function convertArrayBufferToBase64String_(buffer) {
117   var binary = '';
118   var bytes = new Uint8Array(buffer);
119   for (var i = 0; i < bytes.byteLength; i++) {
120     binary += String.fromCharCode(bytes[i]);
121   }
122   return window.btoa(binary);
126  * The function which is called at the end of every gFrameCaptureInterval. Gets
127  * the current frame from the video and extracts the data from it. Then it saves
128  * it in the frames array and adjusts the capture interval (timers in JavaScript
129  * aren't precise).
131  * @private
133  * @param {!Object} The video whose frames are to be captured.
134  * @param {Canvas} The canvas on which the image will be captured.
135  * @param {Number} The width of the video/canvas area to be captured.
136  * @param {Number} The height of the video area to be captured.
137  */
138 function shoot_(video, canvas, width, height) {
139   // The first two captured frames have big difference between the ideal time
140   // interval between two frames and the real one. As a consequence this affects
141   // enormously the interval adjustment for subsequent frames. That's why we
142   // have to reset the time after the first two frames and get rid of these two
143   // frames.
144   if (gFrames.length == 1 && !gHasThrownAwayFirstTwoFrames) {
145     gStartedAt = new Date().getTime();
146     gHasThrownAwayFirstTwoFrames = true;
147     gFrames = [];
148   }
150   // We capture the whole video frame.
151   var img = captureFrame_(video, canvas.getContext('2d'), width, height);
152   gFrames.push(img.data.buffer);
154   // Adjust the timer and try to account for timer incorrectness.
155   var currentTime = new Date().getTime();
156   var idealTime = gFrames.length * gFrameCaptureInterval;
157   var realTimeElapsed = currentTime - gStartedAt;
158   var diff = realTimeElapsed - idealTime;
160   if (realTimeElapsed < gCaptureDuration) {
161     // If duration isn't over shoot_ again.
162     setTimeout(function() { shoot_(video, canvas, width, height); },
163                gFrameCaptureInterval - diff);
164   } else {
165     // Done capturing!
166     gDoneFrameCapturing = true;
167     prepareProgressBar_();
168   }
172  * @private
173  */
174 function captureFrame_(video, context, width, height) {
175   context.drawImage(video, 0, 0, width, height);
176   return context.getImageData(0, 0, width, height);
180  * @private
181  */
182 function prepareProgressBar_() {
183   document.body.innerHTML =
184     '<html><body>' +
185     '<p id="progressBar" style="position: absolute; top: 50%; left: 40%;">' +
186     'Preparing to send frames.</p>' +
187     '</body></html>';
191  * @private
192  */
193 function updateProgressBar_(currentFrame) {
194   progressBar.innerHTML =
195     'Transferring captured frames: ' + '(' + currentFrame + '/' +
196     gFrames.length + ')';