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

Side by Side 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, 4 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 #include "remoting/host/video_frame_recorder_host_extension.h"
6
7 #include "base/base64.h"
8 #include "base/json/json_reader.h"
9 #include "base/json/json_writer.h"
10 #include "base/logging.h"
11 #include "base/values.h"
12 #include "remoting/codec/video_encoder_verbatim.h"
13 #include "remoting/host/host_extension_session.h"
14 #include "remoting/host/video_frame_recorder.h"
15 #include "remoting/proto/control.pb.h"
16 #include "remoting/proto/video.pb.h"
17 #include "remoting/protocol/client_stub.h"
18 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
19
20 namespace remoting {
21
22 namespace {
23
24 const char kVideoRecorderCapabilities[] = "videoRecorder";
25
26 const char kVideoRecorderType[] = "video-recorder";
27
28 const char kType[] = "type";
29 const char kData[] = "data";
30
31 const char kStartType[] = "start";
32 const char kStopType[] = "stop";
33 const char kNextFrameType[] = "next-frame";
34 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'
35
36 class VideoFrameRecorderHostExtensionSession : public HostExtensionSession {
37 public:
38 explicit VideoFrameRecorderHostExtensionSession(int64_t max_content_bytes);
39 virtual ~VideoFrameRecorderHostExtensionSession() {}
40
41 // remoting::HostExtensionSession interface.
42 virtual scoped_ptr<VideoEncoder> OnCreateVideoEncoder(
43 scoped_ptr<VideoEncoder> encoder) OVERRIDE;
44 virtual bool ModifiesVideoPipeline() const OVERRIDE;
45 virtual bool OnExtensionMessage(
46 ClientSessionControl* client_session_control,
47 protocol::ClientStub* client_stub,
48 const protocol::ExtensionMessage& message) OVERRIDE;
49
50 private:
51 VideoEncoderVerbatim verbatim_encoder;
52 VideoFrameRecorder video_frame_recorder;
53
54 DISALLOW_COPY_AND_ASSIGN(VideoFrameRecorderHostExtensionSession);
55 };
56
57 VideoFrameRecorderHostExtensionSession::VideoFrameRecorderHostExtensionSession(
58 int64_t max_content_bytes) {
59 video_frame_recorder.SetMaxContentBytes(max_content_bytes);
60 }
61
62 scoped_ptr<VideoEncoder>
63 VideoFrameRecorderHostExtensionSession::OnCreateVideoEncoder(
64 scoped_ptr<VideoEncoder> encoder) {
65 video_frame_recorder.DetachVideoEncoderWrapper();
66 return video_frame_recorder.WrapVideoEncoder(encoder.Pass());
67 }
68
69 bool VideoFrameRecorderHostExtensionSession::ModifiesVideoPipeline() const {
70 return true;
71 }
72
73 bool VideoFrameRecorderHostExtensionSession::OnExtensionMessage(
74 ClientSessionControl* client_session_control,
75 protocol::ClientStub* client_stub,
76 const protocol::ExtensionMessage& message) {
77 if (message.type() != kVideoRecorderType) {
78 return false;
79 }
80
81 if (!message.has_data()) {
82 return true;
83 }
84
85 scoped_ptr<base::Value> value(base::JSONReader::Read(message.data()));
86 base::DictionaryValue* client_message;
87 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.
88 std::string type;
89 if (!client_message->GetString(kType, &type)) {
90 LOG(ERROR) << "Invalid video-recorder message";
91 return true;
92 }
93
94 if (type == kStartType) {
95 video_frame_recorder.SetEnableRecording(true);
96 } else if (type == kStopType) {
97 video_frame_recorder.SetEnableRecording(false);
98 } else if (type == kNextFrameType) {
99 scoped_ptr<webrtc::DesktopFrame> frame(video_frame_recorder.NextFrame());
100
101 // TODO(wez): This involves six copies of the entire frame.
102 // See if there's some way to optimize at least a few of them out.
103 base::DictionaryValue reply_message;
104 reply_message.SetString(kType, kNextFrameReplyType);
105 if (frame) {
106 // Encode the frame into a raw ARGB VideoPacket.
107 scoped_ptr<VideoPacket> encoded_frame(
108 verbatim_encoder.Encode(*frame));
109
110 // Serialize that packet into a string.
111 std::string data;
112 data.resize(encoded_frame->ByteSize());
113 encoded_frame->SerializeWithCachedSizesToArray(
114 reinterpret_cast<uint8_t*>(&data[0]));
115
116 // Convert that string to Base64, so it's JSON-friendly.
117 std::string base64_data;
118 base::Base64Encode(data, &base64_data);
119
120 // Copy the Base64 data into the message.
121 reply_message.SetString(kData, base64_data);
122 }
123
124 // JSON-encode the reply into a string.
125 std::string reply_json;
126 if (!base::JSONWriter::Write(&reply_message, &reply_json)) {
127 LOG(ERROR) << "Failed to create reply json";
128 return true;
129 }
130
131 // Return the frame (or a 'data'-less reply) to the client.
132 protocol::ExtensionMessage message;
133 message.set_type(kVideoRecorderType);
134 message.set_data(reply_json);
135 client_stub->DeliverHostMessage(message);
136 }
137 }
138
139 return true;
140 }
141
142 } // namespace
143
144 void VideoFrameRecorderHostExtension::SetMaxContentBytes(
145 int64_t max_content_bytes) {
146 max_content_bytes_ = max_content_bytes;
147 }
148
149 std::string VideoFrameRecorderHostExtension::capability() const {
150 return kVideoRecorderCapabilities;
151 }
152
153 scoped_ptr<HostExtensionSession>
154 VideoFrameRecorderHostExtension::CreateExtensionSession(
155 ClientSessionControl* client_session_control,
156 protocol::ClientStub* client_stub) {
157 return scoped_ptr<HostExtensionSession>(
158 new VideoFrameRecorderHostExtensionSession(max_content_bytes_));
159 }
160
161 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698