blob: 67301622c9cbe146c704838f80c5d156d22cec0e [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview
* Class implement the video frame recorder extension client.
*/
'use strict';
/** @suppress {duplicate} */
var remoting = remoting || {};
/**
* @constructor
* @param {remoting.ClientPlugin} plugin
*/
remoting.VideoFrameRecorder = function(plugin) {
this.fileWriter_ = null;
this.isRecording_ = false;
this.plugin_ = plugin;
};
/**
* Starts or stops video recording.
*/
remoting.VideoFrameRecorder.prototype.startStopRecording = function() {
var data = {};
if (this.isRecording_) {
this.isRecording_ = false;
data = { type: 'stop' }
chrome.fileSystem.chooseEntry(
{type: 'saveFile', suggestedName: 'videoRecording.pb'},
this.onFileChosen_.bind(this));
} else {
this.isRecording_ = true;
data = { type: 'start' }
}
this.plugin_.sendClientMessage('video-recorder', JSON.stringify(data));
}
/**
* Returns true if the session is currently being recorded.
* @return {boolean}
*/
remoting.VideoFrameRecorder.prototype.isRecording = function() {
return this.isRecording_;
}
/**
* Handles 'video-recorder' extension messages and returns true. Returns
* false for all other message types.
* @param {string} type Type of extension message.
* @param {string} data Content of the extension message.
* @return {boolean}
*/
remoting.VideoFrameRecorder.prototype.handleMessage =
function(type, data) {
if (type != 'video-recorder') {
return false;
}
var message = getJsonObjectFromString(data);
var messageType = getStringAttr(message, 'type');
var messageData = getStringAttr(message, 'data');
if (messageType == 'next-frame-reply') {
if (!this.fileWriter_) {
console.log("Received frame but have no writer");
return true;
}
if (!messageData) {
console.log("Finished receiving frames");
this.fileWriter_ = null;
return true;
}
console.log("Received frame");
/* jscompile gets confused if you refer to this as just atob(). */
var videoPacketString = /** @type {string?} */ window.atob(messageData);
console.log("Converted from Base64 - length:" + videoPacketString.length);
var byteArrays = [];
for (var offset = 0; offset < videoPacketString.length; offset += 512) {
var slice = videoPacketString.slice(offset, offset + 512);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
console.log("Writing frame");
videoPacketString = null;
/**
* Our current compiler toolchain only understands the old (deprecated)
* Blob constructor, which does not accept any parameters.
* TODO(wez): Remove this when compiler is updated (see crbug.com/405298).
* @suppress {checkTypes}
* @param {Array} parts
* @return {Blob}
*/
var makeBlob = function(parts) {
return new Blob(parts);
}
var videoPacketBlob = makeBlob(byteArrays);
byteArrays = null;
this.fileWriter_.write(videoPacketBlob);
return true;
}
console.log("Unrecognized message: " + messageType);
return true;
}
/** @param {FileEntry} fileEntry */
remoting.VideoFrameRecorder.prototype.onFileChosen_ = function(fileEntry) {
if (!fileEntry) {
console.log("Cancelled save of video frames.");
} else {
/** @type {function(string):void} */
chrome.fileSystem.getDisplayPath(fileEntry, function(path) {
console.log("Saving video frames to:" + path);
});
fileEntry.createWriter(this.onFileWriter_.bind(this));
}
}
/** @param {FileWriter} fileWriter */
remoting.VideoFrameRecorder.prototype.onFileWriter_ = function(fileWriter) {
console.log("Obtained FileWriter for video frame write");
fileWriter.onwriteend = this.onWriteComplete_.bind(this);
this.fileWriter_ = fileWriter;
this.fetchNextFrame_();
}
remoting.VideoFrameRecorder.prototype.onWriteComplete_ = function(e) {
console.log("Video frame write complete");
this.fetchNextFrame_();
}
remoting.VideoFrameRecorder.prototype.fetchNextFrame_ = function() {
console.log("Request next video frame");
var data = { type: 'next-frame' }
this.plugin_.sendClientMessage('video-recorder', JSON.stringify(data));
}