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);
195 progressBar
= document
.getElementById('progress-bar');
196 if (gFrames
.length
> 0) {
197 var frame
= gFrames
.shift();
198 gWebSocket
.send(frame
);
200 setTimeout(function() { sendFrames(); }, 100);
202 var totalNumFrames
= gFrameCounter
+ gFrames
.length
;
203 progressBar
.innerHTML
=
204 'Writing captured frames to disk: ' +
205 '(' + gFrameCounter
+ '/' + totalNumFrames
+ ')';
207 progressBar
.innerHTML
= 'Finished sending frames.'
208 console
.log('Finished sending frames.');
213 * Function checking whether there are more frames to send to the pywebsocket
216 function haveMoreFramesToSend() {
217 if (gFrames
.length
== 0) {
218 returnToTest('no-more-frames');
220 returnToTest('still-have-frames');
225 * Continuously tries to open a WebSocket to the pywebsocket server.
227 function tryOpeningWebSocket() {
228 if (!gWebSocketOpened
) {
229 console
.log('Once again trying to open web socket');
231 setTimeout(function() { tryOpeningWebSocket(); }, 1000);
236 * Open the WebSocket connection and register some events.
238 function openWebSocket() {
239 if (!gWebSocketOpened
) {
240 gWebSocket
= new WebSocket('ws://localhost:12221/webrtc_write');
243 gWebSocket
.onopen = function () {
244 console
.log('Opened WebSocket connection');
245 gWebSocketOpened
= true;
248 gWebSocket
.onerror = function (error
) {
249 console
.log('WebSocket Error ' + error
);
252 gWebSocket
.onmessage = function (e
) {
253 console
.log('Server says: ' + e
.data
);
260 function clearPage_() {
261 document
.body
.innerHTML
= '';
267 function prepareProgressBar_() {
268 document
.body
.innerHTML
=
270 '<p id="progress-bar" style="position: absolute; top: 50%; left: 40%;">' +
271 'Preparing to send frames.</p>' +