Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Unified Diff: remoting/host/video_frame_recorder_host_extension.cc

Issue 372943002: Add video frame recording capability to Chromoting hosts. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Correct comment Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: remoting/host/video_frame_recorder_host_extension.cc
diff --git a/remoting/host/video_frame_recorder_host_extension.cc b/remoting/host/video_frame_recorder_host_extension.cc
new file mode 100644
index 0000000000000000000000000000000000000000..67f9c941eb392af2fff38ae283fcdb4d74a1d169
--- /dev/null
+++ b/remoting/host/video_frame_recorder_host_extension.cc
@@ -0,0 +1,161 @@
+// 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.
+
+#include "remoting/host/video_frame_recorder_host_extension.h"
+
+#include "base/base64.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/logging.h"
+#include "base/values.h"
+#include "remoting/codec/video_encoder_verbatim.h"
+#include "remoting/host/host_extension_session.h"
+#include "remoting/host/video_frame_recorder.h"
+#include "remoting/proto/control.pb.h"
+#include "remoting/proto/video.pb.h"
+#include "remoting/protocol/client_stub.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+
+namespace remoting {
+
+namespace {
+
+const char kVideoRecorderCapabilities[] = "videoRecorder";
+
+const char kVideoRecorderType[] = "video-recorder";
+
+const char kType[] = "type";
+const char kData[] = "data";
+
+const char kStartType[] = "start";
+const char kStopType[] = "stop";
+const char kNextFrameType[] = "next-frame";
+const char kNextFrameReplyType[] = "next-frame-reply";
Jamie 2014/08/01 19:53:51 Are these constants duplicated somewhere in JS cod
Wez 2014/08/01 22:33:56 I've added a note to the capability definition; I'
+
+class VideoFrameRecorderHostExtensionSession : public HostExtensionSession {
+ public:
+ explicit VideoFrameRecorderHostExtensionSession(int64_t max_content_bytes);
+ virtual ~VideoFrameRecorderHostExtensionSession() {}
+
+ // remoting::HostExtensionSession interface.
+ virtual scoped_ptr<VideoEncoder> OnCreateVideoEncoder(
+ scoped_ptr<VideoEncoder> encoder) OVERRIDE;
+ virtual bool ModifiesVideoPipeline() const OVERRIDE;
+ virtual bool OnExtensionMessage(
+ ClientSessionControl* client_session_control,
+ protocol::ClientStub* client_stub,
+ const protocol::ExtensionMessage& message) OVERRIDE;
+
+ private:
+ VideoEncoderVerbatim verbatim_encoder;
+ VideoFrameRecorder video_frame_recorder;
+
+ DISALLOW_COPY_AND_ASSIGN(VideoFrameRecorderHostExtensionSession);
+};
+
+VideoFrameRecorderHostExtensionSession::VideoFrameRecorderHostExtensionSession(
+ int64_t max_content_bytes) {
+ video_frame_recorder.SetMaxContentBytes(max_content_bytes);
+}
+
+scoped_ptr<VideoEncoder>
+VideoFrameRecorderHostExtensionSession::OnCreateVideoEncoder(
+ scoped_ptr<VideoEncoder> encoder) {
+ video_frame_recorder.DetachVideoEncoderWrapper();
+ return video_frame_recorder.WrapVideoEncoder(encoder.Pass());
+}
+
+bool VideoFrameRecorderHostExtensionSession::ModifiesVideoPipeline() const {
+ return true;
+}
+
+bool VideoFrameRecorderHostExtensionSession::OnExtensionMessage(
+ ClientSessionControl* client_session_control,
+ protocol::ClientStub* client_stub,
+ const protocol::ExtensionMessage& message) {
+ if (message.type() != kVideoRecorderType) {
+ return false;
+ }
+
+ if (!message.has_data()) {
+ return true;
+ }
+
+ scoped_ptr<base::Value> value(base::JSONReader::Read(message.data()));
+ base::DictionaryValue* client_message;
+ if (value && value->GetAsDictionary(&client_message)) {
Jamie 2014/08/01 19:53:52 Elsewhere in this function, you seem to prefer ear
Wez 2014/08/01 22:33:56 Done.
+ std::string type;
+ if (!client_message->GetString(kType, &type)) {
+ LOG(ERROR) << "Invalid video-recorder message";
+ return true;
+ }
+
+ if (type == kStartType) {
+ video_frame_recorder.SetEnableRecording(true);
+ } else if (type == kStopType) {
+ video_frame_recorder.SetEnableRecording(false);
+ } else if (type == kNextFrameType) {
+ scoped_ptr<webrtc::DesktopFrame> frame(video_frame_recorder.NextFrame());
+
+ // TODO(wez): This involves six copies of the entire frame.
+ // See if there's some way to optimize at least a few of them out.
+ base::DictionaryValue reply_message;
+ reply_message.SetString(kType, kNextFrameReplyType);
+ if (frame) {
+ // Encode the frame into a raw ARGB VideoPacket.
+ scoped_ptr<VideoPacket> encoded_frame(
+ verbatim_encoder.Encode(*frame));
+
+ // Serialize that packet into a string.
+ std::string data;
+ data.resize(encoded_frame->ByteSize());
+ encoded_frame->SerializeWithCachedSizesToArray(
+ reinterpret_cast<uint8_t*>(&data[0]));
+
+ // Convert that string to Base64, so it's JSON-friendly.
+ std::string base64_data;
+ base::Base64Encode(data, &base64_data);
+
+ // Copy the Base64 data into the message.
+ reply_message.SetString(kData, base64_data);
+ }
+
+ // JSON-encode the reply into a string.
+ std::string reply_json;
+ if (!base::JSONWriter::Write(&reply_message, &reply_json)) {
+ LOG(ERROR) << "Failed to create reply json";
+ return true;
+ }
+
+ // Return the frame (or a 'data'-less reply) to the client.
+ protocol::ExtensionMessage message;
+ message.set_type(kVideoRecorderType);
+ message.set_data(reply_json);
+ client_stub->DeliverHostMessage(message);
+ }
+ }
+
+ return true;
+}
+
+} // namespace
+
+void VideoFrameRecorderHostExtension::SetMaxContentBytes(
+ int64_t max_content_bytes) {
+ max_content_bytes_ = max_content_bytes;
+}
+
+std::string VideoFrameRecorderHostExtension::capability() const {
+ return kVideoRecorderCapabilities;
+}
+
+scoped_ptr<HostExtensionSession>
+VideoFrameRecorderHostExtension::CreateExtensionSession(
+ ClientSessionControl* client_session_control,
+ protocol::ClientStub* client_stub) {
+ return scoped_ptr<HostExtensionSession>(
+ new VideoFrameRecorderHostExtensionSession(max_content_bytes_));
+}
+
+} // namespace remoting

Powered by Google App Engine
This is Rietveld 408576698