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 base
.debug
.assert(type
== remoting
.VideoFrameRecorder
.EXTENSION_TYPE
);
65 var messageType
= base
.getStringAttr(message
, 'type');
66 var messageData
= base
.getStringAttr(message
, 'data');
68 if (messageType
== 'next-frame-reply') {
69 if (!this.fileWriter_
) {
70 console
.log("Received frame but have no writer");
74 console
.log("Finished receiving frames");
75 this.fileWriter_
= null;
79 console
.log("Received frame");
80 var videoPacketString
= window
.atob(messageData
);
82 console
.log("Converted from Base64 - length:" + videoPacketString
.length
);
85 for (var offset
= 0; offset
< videoPacketString
.length
; offset
+= 512) {
86 var slice
= videoPacketString
.slice(offset
, offset
+ 512);
87 var byteNumbers
= new Array(slice
.length
);
88 for (var i
= 0; i
< slice
.length
; i
++) {
89 byteNumbers
[i
] = slice
.charCodeAt(i
);
91 var byteArray
= new Uint8Array(byteNumbers
);
92 byteArrays
.push(byteArray
);
95 console
.log("Writing frame");
96 videoPacketString
= null;
98 * @param {Array} parts
101 var makeBlob = function(parts
) {
102 return new Blob(parts
);
104 var videoPacketBlob
= makeBlob(byteArrays
);
107 this.fileWriter_
.write(videoPacketBlob
);
112 console
.log("Unrecognized message: " + messageType
);
117 * Starts or stops video recording.
119 remoting
.VideoFrameRecorder
.prototype.startStopRecording = function() {
121 if (this.isRecording_
) {
122 this.isRecording_
= false;
123 data
= { type
: 'stop' }
125 chrome
.fileSystem
.chooseEntry(
126 {type
: 'saveFile', suggestedName
: 'videoRecording.pb'},
127 this.onFileChosen_
.bind(this));
129 this.isRecording_
= true;
130 data
= { type
: 'start' }
132 this.sendMessageToHost_(data
);
136 * Returns true if the session is currently being recorded.
139 remoting
.VideoFrameRecorder
.prototype.isRecording = function() {
140 return this.isRecording_
;
144 * @param {Entry} entry The single file entry if multiple files are not allowed.
145 * @param {Array<FileEntry>} fileEntries List of file entries if multiple files
148 remoting
.VideoFrameRecorder
.prototype.onFileChosen_ = function(
149 entry
, fileEntries
) {
151 console
.log("Cancelled save of video frames.");
153 chrome
.fileSystem
.getDisplayPath(entry
, function(path
) {
154 console
.log("Saving video frames to:" + path
);
156 entry
.createWriter(this.onFileWriter_
.bind(this));
160 /** @param {FileWriter} fileWriter */
161 remoting
.VideoFrameRecorder
.prototype.onFileWriter_ = function(fileWriter
) {
162 console
.log("Obtained FileWriter for video frame write");
163 fileWriter
.onwriteend
= this.onWriteComplete_
.bind(this);
164 this.fileWriter_
= fileWriter
;
165 this.fetchNextFrame_();
168 remoting
.VideoFrameRecorder
.prototype.onWriteComplete_ = function(e
) {
169 console
.log("Video frame write complete");
170 this.fetchNextFrame_();
173 remoting
.VideoFrameRecorder
.prototype.fetchNextFrame_ = function() {
174 console
.log("Request next video frame");
175 var data
= { type
: 'next-frame' }
176 this.sendMessageToHost_(data
);