Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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. | |
| 4 | |
| 5 /** | |
| 6 * @fileoverview | |
| 7 * Class implement the video frame recorder extension client. | |
| 8 */ | |
| 9 | |
| 10 'use strict'; | |
| 11 | |
| 12 /** @suppress {duplicate} */ | |
| 13 var remoting = remoting || {}; | |
| 14 | |
| 15 /** | |
| 16 * @constructor | |
| 17 * @param {remoting.ClientPlugin} plugin | |
| 18 */ | |
| 19 remoting.VideoFrameRecorder = function(plugin) { | |
| 20 this.fileWriter_ = null; | |
| 21 this.isRecording_ = false; | |
| 22 this.plugin_ = plugin; | |
| 23 }; | |
| 24 | |
| 25 /** | |
| 26 * Starts or stops video recording. | |
| 27 */ | |
| 28 remoting.VideoFrameRecorder.prototype.startStopRecording = function() { | |
| 29 var data = {}; | |
| 30 if (this.isRecording_) { | |
| 31 this.isRecording_ = false; | |
| 32 data = { type: 'stop' } | |
| 33 | |
| 34 chrome.fileSystem.chooseEntry( | |
| 35 {type: 'saveFile', suggestedName: 'videoRecording.pb'}, | |
| 36 this.onFileChosen_.bind(this)); | |
| 37 } else { | |
| 38 this.isRecording_ = true; | |
| 39 data = { type: 'start' } | |
| 40 } | |
| 41 this.plugin_.sendClientMessage('video-recorder', JSON.stringify(data)); | |
| 42 } | |
| 43 | |
| 44 /** | |
| 45 * Returns true if the session is currently being recorded. | |
| 46 * @return {boolean} | |
| 47 */ | |
| 48 remoting.VideoFrameRecorder.prototype.isRecording = function() { | |
| 49 return this.isRecording_; | |
| 50 } | |
| 51 | |
| 52 /** | |
| 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. | |
| 57 * @return {boolean} | |
| 58 */ | |
| 59 remoting.VideoFrameRecorder.prototype.handleMessage = | |
| 60 function(type, data) { | |
| 61 if (type != 'video-recorder') { | |
| 62 return false; | |
| 63 } | |
| 64 | |
| 65 var message = getJsonObjectFromString(data); | |
| 66 var messageType = getStringAttr(message, 'type'); | |
| 67 var messageData = getStringAttr(message, 'data'); | |
| 68 | |
| 69 if (messageType == 'next-frame-reply') { | |
| 70 if (!this.fileWriter_) { | |
| 71 console.log("Received frame but have no writer"); | |
| 72 return true; | |
| 73 } | |
| 74 if (!messageData) { | |
| 75 console.log("Finished receiving frames"); | |
| 76 this.fileWriter_ = null; | |
| 77 return true; | |
| 78 } | |
| 79 | |
| 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); | |
| 83 | |
| 84 console.log("Converted from Base64 - length:" + videoPacketString.length); | |
| 85 var byteArrays = []; | |
| 86 | |
| 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); | |
| 92 } | |
| 93 var byteArray = new Uint8Array(byteNumbers); | |
| 94 byteArrays.push(byteArray); | |
| 95 } | |
| 96 | |
| 97 console.log("Writing frame"); | |
| 98 videoPacketString = null; | |
| 99 var videoPacketBlob = new Blob(byteArrays); | |
|
Wez
2014/08/19 21:19:00
This raises a jscompile error; it seems to only be
| |
| 100 byteArrays = null; | |
| 101 | |
| 102 this.fileWriter_.write(videoPacketBlob); | |
| 103 | |
| 104 return true; | |
| 105 } | |
| 106 | |
| 107 console.log("Unrecognized message: " + messageType); | |
| 108 return true; | |
| 109 } | |
| 110 | |
| 111 /** @param {FileEntry} fileEntry */ | |
| 112 remoting.VideoFrameRecorder.prototype.onFileChosen_ = function(fileEntry) { | |
| 113 if (!fileEntry) { | |
| 114 console.log("Cancelled save of video frames."); | |
| 115 } else { | |
| 116 /** @type {function(string):void} */ | |
| 117 chrome.fileSystem.getDisplayPath(fileEntry, function(path) { | |
| 118 console.log("Saving video frames to:" + path); | |
| 119 }); | |
| 120 fileEntry.createWriter(this.onFileWriter_.bind(this)); | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 /** @param {FileWriter} fileWriter */ | |
| 125 remoting.VideoFrameRecorder.prototype.onFileWriter_ = function(fileWriter) { | |
| 126 console.log("Obtained FileWriter for video frame write"); | |
| 127 fileWriter.onwriteend = this.onWriteComplete_.bind(this); | |
| 128 this.fileWriter_ = fileWriter; | |
| 129 this.fetchNextFrame_(); | |
| 130 } | |
| 131 | |
| 132 remoting.VideoFrameRecorder.prototype.onWriteComplete_ = function(e) { | |
| 133 console.log("Video frame write complete"); | |
| 134 this.fetchNextFrame_(); | |
| 135 } | |
| 136 | |
| 137 remoting.VideoFrameRecorder.prototype.fetchNextFrame_ = function() { | |
| 138 console.log("Request next video frame"); | |
| 139 var data = { type: 'next-frame' } | |
| 140 this.plugin_.sendClientMessage('video-recorder', JSON.stringify(data)); | |
| 141 } | |
| OLD | NEW |