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.
8 * The ID of the video tag from which frames are captured.
11 var gVideoId = 'remote-view';
14 * Counts the number of frames that have been captured. Used in timeout
18 var gFrameCounter = 0;
21 * The gStartOfTime when the capturing begins. Used for timeout adjustments.
27 * The duration of the all frame capture in milliseconds.
30 var gCaptureDuration = 0;
33 * The time interval at which the video is sampled.
36 var gFrameCaptureInterval = 0;
39 * The global array of frames. Frames are pushed, i.e. this should be treated as
40 * a queue and we should read from the start.
43 var gFrames = new Array();
46 * The WebSocket connection to the PyWebSocket server.
49 var gWebSocket = null;
52 * A flag to show whether the WebSocket is open;
55 var gWebSocketOpened = false;
58 * We need to skip the first two frames due to timing issues. This flags helps
59 * us determine weather or not to skip them.
62 var gFrameIntervalAdjustment = false;
65 * We need this global variable to synchronize with the test how long to run the
66 * call between the two peers.
68 var dDoneFrameCapturing = false;
71 * Upon load of the window opens the WebSocket to the PyWebSocket server. The
72 * server should already be up and running.
74 window.onload = function() {
75 tryOpeningWebSocket();
79 * Starts the frame capturing.
81 * @param {Number} The width of the video/canvas area to be captured.
82 * @param {Number} The height of the video area to be captured.
83 * @param {Number} The height of the canvas where we put the video frames.
84 * @param {Number} The frame rate at which we would like to capture frames.
85 * @param {Number} The duration of the frame capture in seconds.
87 function startFrameCapture(width, height, canvas_height, frame_rate, duration){
88 gFrameCaptureInterval = 1000/frame_rate;
89 gCaptureDuration = 1000 * duration;
91 console.log('Received width is: ' + width + ', received height is: ' + height
92 + ', capture interval is: ' + gFrameCaptureInterval +
93 ', duration is: ' + gCaptureDuration);
94 gStartOfTime = new Date().getTime();
95 setTimeout(function() { shoot(width, height, canvas_height); },
96 gFrameCaptureInterval);
100 * Captures an image frame from the provided video element.
102 * @param {Video} video HTML5 video element from where the image frame will
104 * @param {Number} The width of the video/canvas area to be captured.
105 * @param {Number} The height of the video/canvas area to be captured.
109 function capture(video, width, height) {
110 var canvas = document.getElementById('remote-canvas');
111 var ctx = canvas.getContext('2d');
112 ctx.drawImage(video, 0, 0, width, height);
117 * The function which is called at the end of every gFrameCaptureInterval. Gets
118 * the current frame from the video and extracts the data from it. Then it saves
119 * it in the frames array and adjusts the capture interval (timers in JavaScript
122 * @param {Number} The width of the video/canvas area to be captured.
123 * @param {Number} The height of the video area to be captured.
124 * @param {Number} The height of the canvas where we put the video frames.
126 function shoot(width, height, canvas_height){
127 // The first two captured frames have big difference between the ideal time
128 // interval between two frames and the real one. As a consequence this affects
129 // enormously the interval adjustment for subsequent frames. That's why we
130 // have to reset the time after the first two frames and get rid of these two
132 if (gFrameCounter == 1 && !gFrameIntervalAdjustment) {
133 gStartOfTime = new Date().getTime();
135 gFrameIntervalAdjustment = true;
139 var video = document.getElementById(gVideoId);
140 var canvas = capture(video, width, height);
142 // Extract the data from the canvas.
143 var ctx = canvas.getContext('2d');
145 if (height == canvas_height) {
146 // We capture the whole video frame.
147 img = ctx.getImageData(0, 0, width, height);
149 // We capture only the barcode (canvas_height is the height of the barcode).
150 img = ctx.getImageData(0, 0, width, canvas_height);
152 gFrames.push(img.data.buffer);
156 var current_time = new Date().getTime();
157 var ideal_time = gFrameCounter*gFrameCaptureInterval;
158 var real_time_elapsed = current_time - gStartOfTime;
159 var diff = real_time_elapsed - ideal_time;
161 if (real_time_elapsed < gCaptureDuration) {
162 // If duration isn't over shoot again
163 setTimeout(function() { shoot(width, height, canvas_height); },
164 gFrameCaptureInterval - diff);
165 } else { // Else reset gFrameCounter and send the frames
166 dDoneFrameCapturing = true;
169 prepareProgressBar_();
175 * Queries if we're done with the frame capturing yet.
177 function doneFrameCapturing() {
178 if (dDoneFrameCapturing) {
179 returnToTest('done-capturing');
181 returnToTest('still-capturing');
186 * Send the frames to the remote PyWebSocket server. Use setTimeout to regularly
187 * try to send the frames.
189 function sendFrames() {
190 if (!gWebSocketOpened) {
191 console.log('WebSocket connection is not yet open');
192 setTimeout(function() { sendFrames(); }, 100);
196 progressBar = document.getElementById('progress-bar');
197 if (gFrames.length > 0) {
198 var frame = gFrames.shift();
199 gWebSocket.send(frame);
201 setTimeout(function() { sendFrames(); }, 100);
203 var totalNumFrames = gFrameCounter + gFrames.length;
204 progressBar.innerHTML =
205 'Writing captured frames to disk: ' +
206 '(' + gFrameCounter + '/' + totalNumFrames + ')';
208 progressBar.innerHTML = 'Finished sending frames.'
209 console.log('Finished sending frames.');
214 * Function checking whether there are more frames to send to the pywebsocket
217 function haveMoreFramesToSend() {
218 if (gFrames.length == 0) {
219 returnToTest('no-more-frames');
221 returnToTest('still-have-frames');
226 * Continuously tries to open a WebSocket to the pywebsocket server.
228 function tryOpeningWebSocket() {
229 if (!gWebSocketOpened) {
230 console.log('Once again trying to open web socket');
232 setTimeout(function() { tryOpeningWebSocket(); }, 1000);
237 * Open the WebSocket connection and register some events.
239 function openWebSocket() {
240 if (!gWebSocketOpened) {
241 gWebSocket = new WebSocket('ws://localhost:12221/webrtc_write');
244 gWebSocket.onopen = function () {
245 console.log('Opened WebSocket connection');
246 gWebSocketOpened = true;
249 gWebSocket.onerror = function (error) {
250 console.log('WebSocket Error ' + error);
253 gWebSocket.onmessage = function (e) {
254 console.log('Server says: ' + e.data);
261 function clearPage_() {
262 document.body.innerHTML = '';
268 function prepareProgressBar_() {
269 document.body.innerHTML =
271 '<p id="progress-bar" style="position: absolute; top: 50%; left: 40%;">' +
272 'Preparing to send frames.</p>' +