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 * @implements {remoting.ProtocolExtension}
19 remoting
.VideoFrameRecorder = function() {
20 /** @private {?function(string,string)} */
21 this.sendMessageToHostCallback_
= null;
23 this.fileWriter_
= null;
24 this.isRecording_
= false;
27 /** @private {string} */
28 remoting
.VideoFrameRecorder
.EXTENSION_TYPE
= 'video-recorder';
30 /** @return {Array<string>} */
31 remoting
.VideoFrameRecorder
.prototype.getExtensionTypes = function() {
32 return [remoting
.VideoFrameRecorder
.EXTENSION_TYPE
];
36 * @param {function(string,string)} sendMessageToHost Callback to send a message
39 remoting
.VideoFrameRecorder
.prototype.startExtension
=
40 function(sendMessageToHost
) {
41 this.sendMessageToHostCallback_
= sendMessageToHost
;
45 * @param {Object} data The data to send.
48 remoting
.VideoFrameRecorder
.prototype.sendMessageToHost_ = function(data
) {
49 this.sendMessageToHostCallback_(remoting
.VideoFrameRecorder
.EXTENSION_TYPE
,
50 JSON
.stringify(data
));
54 * Handles 'video-recorder' extension messages and returns true. Returns
55 * false for all other message types.
57 * @param {string} type Type of extension message.
58 * @param {Object} message The parsed extension message data.
61 remoting
.VideoFrameRecorder
.prototype.onExtensionMessage
=
62 function(type
, message
) {
63 console
.assert(type
== remoting
.VideoFrameRecorder
.EXTENSION_TYPE
,
64 'Unexpected extension message type: ' + type
+ '.');
66 var messageType
= base
.getStringAttr(message
, 'type');
67 var messageData
= base
.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 var videoPacketString
= window
.atob(messageData
);
83 console
.log("Converted from Base64 - length:" + videoPacketString
.length
);
86 for (var offset
= 0; offset
< videoPacketString
.length
; offset
+= 512) {
87 var slice
= videoPacketString
.slice(offset
, offset
+ 512);
88 var byteNumbers
= new Array(slice
.length
);
89 for (var i
= 0; i
< slice
.length
; i
++) {
90 byteNumbers
[i
] = slice
.charCodeAt(i
);
92 var byteArray
= new Uint8Array(byteNumbers
);
93 byteArrays
.push(byteArray
);
96 console
.log("Writing frame");
97 videoPacketString
= null;
99 * @param {Array} parts
102 var makeBlob = function(parts
) {
103 return new Blob(parts
);
105 var videoPacketBlob
= makeBlob(byteArrays
);
108 this.fileWriter_
.write(videoPacketBlob
);
113 console
.log("Unrecognized message: " + messageType
);
118 * Starts or stops video recording.
120 remoting
.VideoFrameRecorder
.prototype.startStopRecording = function() {
122 if (this.isRecording_
) {
123 this.isRecording_
= false;
124 data
= { type
: 'stop' }
126 chrome
.fileSystem
.chooseEntry(
127 {type
: 'saveFile', suggestedName
: 'videoRecording.pb'},
128 this.onFileChosen_
.bind(this));
130 this.isRecording_
= true;
131 data
= { type
: 'start' }
133 this.sendMessageToHost_(data
);
137 * Returns true if the session is currently being recorded.
140 remoting
.VideoFrameRecorder
.prototype.isRecording = function() {
141 return this.isRecording_
;
145 * @param {Entry=} entry The single file entry if multiple files are not
147 * @param {Array<!FileEntry>=} fileEntries List of file entries if multiple
150 remoting
.VideoFrameRecorder
.prototype.onFileChosen_ = function(
151 entry
, fileEntries
) {
153 console
.log("Cancelled save of video frames.");
155 chrome
.fileSystem
.getDisplayPath(entry
, function(path
) {
156 console
.log("Saving video frames to:" + path
);
158 entry
.createWriter(this.onFileWriter_
.bind(this));
162 /** @param {FileWriter} fileWriter */
163 remoting
.VideoFrameRecorder
.prototype.onFileWriter_ = function(fileWriter
) {
164 console
.log("Obtained FileWriter for video frame write");
165 fileWriter
.onwriteend
= this.onWriteComplete_
.bind(this);
166 this.fileWriter_
= fileWriter
;
167 this.fetchNextFrame_();
170 remoting
.VideoFrameRecorder
.prototype.onWriteComplete_ = function(e
) {
171 console
.log("Video frame write complete");
172 this.fetchNextFrame_();
175 remoting
.VideoFrameRecorder
.prototype.fetchNextFrame_ = function() {
176 console
.log("Request next video frame");
177 var data
= { type
: 'next-frame' }
178 this.sendMessageToHost_(data
);