1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 * Class implement the video frame recorder extension client.
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
17 * @param {remoting.ClientPlugin} plugin
19 remoting.VideoFrameRecorder = function(plugin) {
20 this.fileWriter_ = null;
21 this.isRecording_ = false;
22 this.plugin_ = plugin;
26 * Starts or stops video recording.
28 remoting.VideoFrameRecorder.prototype.startStopRecording = function() {
30 if (this.isRecording_) {
31 this.isRecording_ = false;
32 data = { type: 'stop' }
34 chrome.fileSystem.chooseEntry(
35 {type: 'saveFile', suggestedName: 'videoRecording.pb'},
36 this.onFileChosen_.bind(this));
38 this.isRecording_ = true;
39 data = { type: 'start' }
41 this.plugin_.sendClientMessage('video-recorder', JSON.stringify(data));
45 * Returns true if the session is currently being recorded.
48 remoting.VideoFrameRecorder.prototype.isRecording = function() {
49 return this.isRecording_;
53 * Handles 'video-recorder' extension messages and returns true. Returns
54 * false for all other message types.
55 * @param {string} type Type of extension message.
56 * @param {string} data Content of the extension message.
59 remoting.VideoFrameRecorder.prototype.handleMessage =
60 function(type, data) {
61 if (type != 'video-recorder') {
65 var message = getJsonObjectFromString(data);
66 var messageType = getStringAttr(message, 'type');
67 var messageData = getStringAttr(message, 'data');
69 if (messageType == 'next-frame-reply') {
70 if (!this.fileWriter_) {
71 console.log("Received frame but have no writer");
75 console.log("Finished receiving frames");
76 this.fileWriter_ = null;
80 console.log("Received frame");
81 /* jscompile gets confused if you refer to this as just atob(). */
82 var videoPacketString = /** @type {string?} */ window.atob(messageData);
84 console.log("Converted from Base64 - length:" + videoPacketString.length);
87 for (var offset = 0; offset < videoPacketString.length; offset += 512) {
88 var slice = videoPacketString.slice(offset, offset + 512);
89 var byteNumbers = new Array(slice.length);
90 for (var i = 0; i < slice.length; i++) {
91 byteNumbers[i] = slice.charCodeAt(i);
93 var byteArray = new Uint8Array(byteNumbers);
94 byteArrays.push(byteArray);
97 console.log("Writing frame");
98 videoPacketString = null;
100 * Our current compiler toolchain only understands the old (deprecated)
101 * Blob constructor, which does not accept any parameters.
102 * TODO(wez): Remove this when compiler is updated (see crbug.com/405298).
103 * @suppress {checkTypes}
104 * @param {Array} parts
107 var makeBlob = function(parts) {
108 return new Blob(parts);
110 var videoPacketBlob = makeBlob(byteArrays);
113 this.fileWriter_.write(videoPacketBlob);
118 console.log("Unrecognized message: " + messageType);
122 /** @param {FileEntry} fileEntry */
123 remoting.VideoFrameRecorder.prototype.onFileChosen_ = function(fileEntry) {
125 console.log("Cancelled save of video frames.");
127 /** @type {function(string):void} */
128 chrome.fileSystem.getDisplayPath(fileEntry, function(path) {
129 console.log("Saving video frames to:" + path);
131 fileEntry.createWriter(this.onFileWriter_.bind(this));
135 /** @param {FileWriter} fileWriter */
136 remoting.VideoFrameRecorder.prototype.onFileWriter_ = function(fileWriter) {
137 console.log("Obtained FileWriter for video frame write");
138 fileWriter.onwriteend = this.onWriteComplete_.bind(this);
139 this.fileWriter_ = fileWriter;
140 this.fetchNextFrame_();
143 remoting.VideoFrameRecorder.prototype.onWriteComplete_ = function(e) {
144 console.log("Video frame write complete");
145 this.fetchNextFrame_();
148 remoting.VideoFrameRecorder.prototype.fetchNextFrame_ = function() {
149 console.log("Request next video frame");
150 var data = { type: 'next-frame' }
151 this.plugin_.sendClientMessage('video-recorder', JSON.stringify(data));