[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 1 | // Copyright (c) 2010 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 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 5 | #include "remoting/host/screen_recorder.h" |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 6 | |
| 7 | #include <algorithm> |
| 8 | |
| 9 | #include "base/logging.h" |
[email protected] | 7c186b16f | 2010-06-15 16:35:33 | [diff] [blame] | 10 | #include "base/scoped_ptr.h" |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 11 | #include "base/stl_util-inl.h" |
[email protected] | c56acf54ff | 2010-11-19 23:44:45 | [diff] [blame] | 12 | #include "base/task.h" |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 13 | #include "base/time.h" |
[email protected] | be2da4d | 2010-07-23 00:54:47 | [diff] [blame] | 14 | #include "remoting/base/capture_data.h" |
[email protected] | 8ea7a167 | 2010-10-04 19:48:42 | [diff] [blame] | 15 | #include "remoting/base/tracer.h" |
[email protected] | 35b9c56 | 2010-11-09 02:22:43 | [diff] [blame] | 16 | #include "remoting/proto/control.pb.h" |
[email protected] | 3adf1b2 | 2010-11-09 23:22:20 | [diff] [blame] | 17 | #include "remoting/proto/video.pb.h" |
[email protected] | 35b9c56 | 2010-11-09 02:22:43 | [diff] [blame] | 18 | #include "remoting/protocol/client_stub.h" |
[email protected] | cd8d237 | 2010-11-04 01:18:04 | [diff] [blame] | 19 | #include "remoting/protocol/connection_to_client.h" |
[email protected] | 4d10ede | 2010-10-28 18:43:37 | [diff] [blame] | 20 | #include "remoting/protocol/message_decoder.h" |
[email protected] | 35b9c56 | 2010-11-09 02:22:43 | [diff] [blame] | 21 | #include "remoting/protocol/util.h" |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 22 | |
[email protected] | cd8d237 | 2010-11-04 01:18:04 | [diff] [blame] | 23 | using remoting::protocol::ConnectionToClient; |
| 24 | |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 25 | namespace remoting { |
| 26 | |
| 27 | // By default we capture 20 times a second. This number is obtained by |
| 28 | // experiment to provide good latency. |
| 29 | static const double kDefaultCaptureRate = 20.0; |
| 30 | |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 31 | // Maximum number of frames that can be processed similtaneously. |
| 32 | // TODO(sergeyu): Should this be set to 1? Or should we change |
| 33 | // dynamically depending on how fast network and CPU are? Experement |
| 34 | // with it. |
| 35 | static const int kMaxRecordings = 2; |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 36 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 37 | ScreenRecorder::ScreenRecorder( |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 38 | MessageLoop* capture_loop, |
| 39 | MessageLoop* encode_loop, |
| 40 | MessageLoop* network_loop, |
| 41 | Capturer* capturer, |
| 42 | Encoder* encoder) |
| 43 | : capture_loop_(capture_loop), |
| 44 | encode_loop_(encode_loop), |
| 45 | network_loop_(network_loop), |
| 46 | capturer_(capturer), |
| 47 | encoder_(encoder), |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 48 | started_(false), |
| 49 | recordings_(0), |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 50 | frame_skipped_(false), |
| 51 | max_rate_(kDefaultCaptureRate) { |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 52 | DCHECK(capture_loop_); |
| 53 | DCHECK(encode_loop_); |
| 54 | DCHECK(network_loop_); |
| 55 | } |
| 56 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 57 | ScreenRecorder::~ScreenRecorder() { |
[email protected] | cd8d237 | 2010-11-04 01:18:04 | [diff] [blame] | 58 | connections_.clear(); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 59 | } |
| 60 | |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 61 | // Public methods -------------------------------------------------------------- |
| 62 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 63 | void ScreenRecorder::Start() { |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 64 | capture_loop_->PostTask( |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 65 | FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoStart)); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 66 | } |
| 67 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 68 | void ScreenRecorder::Pause() { |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 69 | capture_loop_->PostTask( |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 70 | FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoPause)); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 71 | } |
| 72 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 73 | void ScreenRecorder::SetMaxRate(double rate) { |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 74 | capture_loop_->PostTask( |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 75 | FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoSetMaxRate, rate)); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 76 | } |
| 77 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 78 | void ScreenRecorder::AddConnection( |
[email protected] | cd8d237 | 2010-11-04 01:18:04 | [diff] [blame] | 79 | scoped_refptr<ConnectionToClient> connection) { |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 80 | ScopedTracer tracer("AddConnection"); |
| 81 | |
| 82 | // Add the client to the list so it can receive update stream. |
| 83 | network_loop_->PostTask( |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 84 | FROM_HERE, |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 85 | NewTracedMethod(this, &ScreenRecorder::DoAddConnection, connection)); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 86 | } |
| 87 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 88 | void ScreenRecorder::RemoveConnection( |
[email protected] | cd8d237 | 2010-11-04 01:18:04 | [diff] [blame] | 89 | scoped_refptr<ConnectionToClient> connection) { |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 90 | network_loop_->PostTask( |
| 91 | FROM_HERE, |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 92 | NewTracedMethod(this, &ScreenRecorder::DoRemoveClient, connection)); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 93 | } |
| 94 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 95 | void ScreenRecorder::RemoveAllConnections() { |
[email protected] | 92698ce | 2010-06-28 21:49:30 | [diff] [blame] | 96 | network_loop_->PostTask( |
| 97 | FROM_HERE, |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 98 | NewTracedMethod(this, &ScreenRecorder::DoRemoveAllClients)); |
[email protected] | 92698ce | 2010-06-28 21:49:30 | [diff] [blame] | 99 | } |
| 100 | |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 101 | // Private accessors ----------------------------------------------------------- |
| 102 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 103 | Capturer* ScreenRecorder::capturer() { |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 104 | DCHECK_EQ(capture_loop_, MessageLoop::current()); |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 105 | DCHECK(capturer_.get()); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 106 | return capturer_.get(); |
| 107 | } |
| 108 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 109 | Encoder* ScreenRecorder::encoder() { |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 110 | DCHECK_EQ(encode_loop_, MessageLoop::current()); |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 111 | DCHECK(encoder_.get()); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 112 | return encoder_.get(); |
| 113 | } |
| 114 | |
| 115 | // Capturer thread ------------------------------------------------------------- |
| 116 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 117 | void ScreenRecorder::DoStart() { |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 118 | DCHECK_EQ(capture_loop_, MessageLoop::current()); |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 119 | DCHECK(!started_); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 120 | |
| 121 | if (started_) { |
[email protected] | 58b4897 | 2010-09-03 00:45:32 | [diff] [blame] | 122 | NOTREACHED() << "Record session already started."; |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 123 | return; |
| 124 | } |
| 125 | |
| 126 | started_ = true; |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 127 | StartCaptureTimer(); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 128 | |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 129 | // Capture first frame immedately. |
| 130 | DoCapture(); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 131 | } |
| 132 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 133 | void ScreenRecorder::DoPause() { |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 134 | DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| 135 | |
| 136 | if (!started_) { |
[email protected] | 58b4897 | 2010-09-03 00:45:32 | [diff] [blame] | 137 | NOTREACHED() << "Record session not started."; |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 138 | return; |
| 139 | } |
| 140 | |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 141 | capture_timer_.Stop(); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 142 | started_ = false; |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 143 | } |
| 144 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 145 | void ScreenRecorder::DoSetMaxRate(double max_rate) { |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 146 | DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| 147 | |
| 148 | // TODO(hclam): Should also check for small epsilon. |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 149 | DCHECK_GT(max_rate, 0.0) << "Rate is too small."; |
| 150 | |
| 151 | max_rate_ = max_rate; |
| 152 | |
| 153 | // Restart the timer with the new rate. |
| 154 | if (started_) { |
| 155 | capture_timer_.Stop(); |
| 156 | StartCaptureTimer(); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 157 | } |
| 158 | } |
| 159 | |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 160 | void ScreenRecorder::StartCaptureTimer() { |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 161 | DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| 162 | |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 163 | base::TimeDelta interval = base::TimeDelta::FromMilliseconds( |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 164 | static_cast<int>(base::Time::kMillisecondsPerSecond / max_rate_)); |
| 165 | capture_timer_.Start(interval, this, &ScreenRecorder::DoCapture); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 166 | } |
| 167 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 168 | void ScreenRecorder::DoCapture() { |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 169 | DCHECK_EQ(capture_loop_, MessageLoop::current()); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 170 | // Make sure we have at most two oustanding recordings. We can simply return |
| 171 | // if we can't make a capture now, the next capture will be started by the |
| 172 | // end of an encode operation. |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 173 | if (recordings_ >= kMaxRecordings || !started_) { |
| 174 | frame_skipped_ = true; |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 175 | return; |
[email protected] | 804c9962 | 2010-07-01 15:02:53 | [diff] [blame] | 176 | } |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 177 | |
| 178 | if (frame_skipped_) { |
| 179 | frame_skipped_ = false; |
| 180 | capture_timer_.Reset(); |
| 181 | } |
| 182 | |
[email protected] | 8ea7a167 | 2010-10-04 19:48:42 | [diff] [blame] | 183 | TraceContext::tracer()->PrintString("Capture Started"); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 184 | |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 185 | // At this point we are going to perform one capture so save the current time. |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 186 | ++recordings_; |
| 187 | |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 188 | // And finally perform one capture. |
[email protected] | 8ea7a167 | 2010-10-04 19:48:42 | [diff] [blame] | 189 | capturer()->CaptureInvalidRects( |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 190 | NewCallback(this, &ScreenRecorder::CaptureDoneCallback)); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 191 | } |
| 192 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 193 | void ScreenRecorder::CaptureDoneCallback( |
[email protected] | be2da4d | 2010-07-23 00:54:47 | [diff] [blame] | 194 | scoped_refptr<CaptureData> capture_data) { |
[email protected] | 88552a9 | 2010-08-06 22:50:00 | [diff] [blame] | 195 | // TODO(hclam): There is a bug if the capturer doesn't produce any dirty |
| 196 | // rects. |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 197 | DCHECK_EQ(capture_loop_, MessageLoop::current()); |
[email protected] | 8ea7a167 | 2010-10-04 19:48:42 | [diff] [blame] | 198 | TraceContext::tracer()->PrintString("Capture Done"); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 199 | encode_loop_->PostTask( |
| 200 | FROM_HERE, |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 201 | NewTracedMethod(this, &ScreenRecorder::DoEncode, capture_data)); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 202 | } |
| 203 | |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 204 | void ScreenRecorder::DoFinishSend() { |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 205 | DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| 206 | |
| 207 | // Decrement the number of recording in process since we have completed |
| 208 | // one cycle. |
| 209 | --recordings_; |
| 210 | |
| 211 | // Try to do a capture again. Note that the following method may do nothing |
| 212 | // if it is too early to perform a capture. |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 213 | DoCapture(); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 214 | } |
| 215 | |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 216 | // Network thread -------------------------------------------------------------- |
| 217 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 218 | void ScreenRecorder::DoSendVideoPacket(VideoPacket* packet) { |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 219 | DCHECK_EQ(network_loop_, MessageLoop::current()); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 220 | |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 221 | TraceContext::tracer()->PrintString("DoSendVideoPacket"); |
| 222 | |
| 223 | bool last = (packet->flags() & VideoPacket::LAST_PARTITION) != 0; |
[email protected] | 8ea7a167 | 2010-10-04 19:48:42 | [diff] [blame] | 224 | |
[email protected] | cd8d237 | 2010-11-04 01:18:04 | [diff] [blame] | 225 | for (ConnectionToClientList::const_iterator i = connections_.begin(); |
| 226 | i < connections_.end(); ++i) { |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 227 | Task* done_task = NULL; |
| 228 | |
| 229 | // Call OnFrameSent() only for the last packet in the first connection. |
| 230 | if (last && i == connections_.begin()) { |
| 231 | done_task = NewTracedMethod(this, &ScreenRecorder::OnFrameSent, packet); |
| 232 | } else { |
| 233 | done_task = new DeleteTask<VideoPacket>(packet); |
| 234 | } |
| 235 | |
| 236 | (*i)->video_stub()->ProcessVideoPacket(packet, done_task); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 237 | } |
[email protected] | c3af26f33 | 2010-10-06 22:46:00 | [diff] [blame] | 238 | |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 239 | TraceContext::tracer()->PrintString("DoSendVideoPacket done"); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 240 | } |
| 241 | |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 242 | void ScreenRecorder::OnFrameSent(VideoPacket* packet) { |
| 243 | delete packet; |
| 244 | capture_loop_->PostTask( |
| 245 | FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoFinishSend)); |
| 246 | } |
| 247 | |
| 248 | void ScreenRecorder::DoAddConnection( |
| 249 | scoped_refptr<ConnectionToClient> connection) { |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 250 | DCHECK_EQ(network_loop_, MessageLoop::current()); |
| 251 | |
| 252 | // TODO(hclam): Force a full frame for next encode. |
[email protected] | cd8d237 | 2010-11-04 01:18:04 | [diff] [blame] | 253 | connections_.push_back(connection); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 254 | } |
| 255 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 256 | void ScreenRecorder::DoRemoveClient( |
[email protected] | cd8d237 | 2010-11-04 01:18:04 | [diff] [blame] | 257 | scoped_refptr<ConnectionToClient> connection) { |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 258 | DCHECK_EQ(network_loop_, MessageLoop::current()); |
| 259 | |
| 260 | // TODO(hclam): Is it correct to do to a scoped_refptr? |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 261 | ConnectionToClientList::iterator it = |
| 262 | std::find(connections_.begin(), connections_.end(), connection); |
[email protected] | cd8d237 | 2010-11-04 01:18:04 | [diff] [blame] | 263 | if (it != connections_.end()) { |
| 264 | connections_.erase(it); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 265 | } |
| 266 | } |
| 267 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 268 | void ScreenRecorder::DoRemoveAllClients() { |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 269 | DCHECK_EQ(network_loop_, MessageLoop::current()); |
| 270 | |
[email protected] | cd8d237 | 2010-11-04 01:18:04 | [diff] [blame] | 271 | // Clear the list of connections. |
| 272 | connections_.clear(); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 273 | } |
| 274 | |
| 275 | // Encoder thread -------------------------------------------------------------- |
| 276 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 277 | void ScreenRecorder::DoEncode( |
[email protected] | be2da4d | 2010-07-23 00:54:47 | [diff] [blame] | 278 | scoped_refptr<CaptureData> capture_data) { |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 279 | DCHECK_EQ(encode_loop_, MessageLoop::current()); |
[email protected] | 8ea7a167 | 2010-10-04 19:48:42 | [diff] [blame] | 280 | TraceContext::tracer()->PrintString("DoEncode called"); |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 281 | |
[email protected] | 8ea7a167 | 2010-10-04 19:48:42 | [diff] [blame] | 282 | // Early out if there's nothing to encode. |
[email protected] | 5a196bd | 2010-08-18 21:37:59 | [diff] [blame] | 283 | if (!capture_data->dirty_rects().size()) { |
| 284 | capture_loop_->PostTask( |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 285 | FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoFinishSend)); |
[email protected] | 8ea7a167 | 2010-10-04 19:48:42 | [diff] [blame] | 286 | return; |
[email protected] | 5a196bd | 2010-08-18 21:37:59 | [diff] [blame] | 287 | } |
| 288 | |
[email protected] | cd8d237 | 2010-11-04 01:18:04 | [diff] [blame] | 289 | // TODO(hclam): Enable |force_refresh| if a new connection was |
[email protected] | 3b3d3af | 2010-07-02 22:23:17 | [diff] [blame] | 290 | // added. |
[email protected] | 8ea7a167 | 2010-10-04 19:48:42 | [diff] [blame] | 291 | TraceContext::tracer()->PrintString("Encode start"); |
[email protected] | 5bc7183 | 2010-12-09 01:34:08 | [diff] [blame^] | 292 | encoder()->Encode(capture_data, false, |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 293 | NewCallback(this, &ScreenRecorder::EncodeDataAvailableTask)); |
[email protected] | 8ea7a167 | 2010-10-04 19:48:42 | [diff] [blame] | 294 | TraceContext::tracer()->PrintString("Encode Done"); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 295 | } |
| 296 | |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 297 | void ScreenRecorder::EncodeDataAvailableTask(VideoPacket* packet) { |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 298 | DCHECK_EQ(encode_loop_, MessageLoop::current()); |
| 299 | |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 300 | network_loop_->PostTask( |
| 301 | FROM_HERE, |
[email protected] | 2cb5bd4 | 2010-12-06 23:06:07 | [diff] [blame] | 302 | NewTracedMethod(this, &ScreenRecorder::DoSendVideoPacket, packet)); |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 303 | } |
| 304 | |
[email protected] | cb3b1f931 | 2010-06-07 19:58:23 | [diff] [blame] | 305 | } // namespace remoting |