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

Side by Side Diff: remoting/host/screen_recorder.cc

Issue 6282006: Add a done task to ScreenRecorder::Stop() (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ready now Created 9 years, 11 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
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/screen_recorder.h" 5 #include "remoting/host/screen_recorder.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/scoped_ptr.h" 10 #include "base/scoped_ptr.h"
(...skipping 28 matching lines...) Expand all
39 MessageLoop* encode_loop, 39 MessageLoop* encode_loop,
40 MessageLoop* network_loop, 40 MessageLoop* network_loop,
41 Capturer* capturer, 41 Capturer* capturer,
42 Encoder* encoder) 42 Encoder* encoder)
43 : capture_loop_(capture_loop), 43 : capture_loop_(capture_loop),
44 encode_loop_(encode_loop), 44 encode_loop_(encode_loop),
45 network_loop_(network_loop), 45 network_loop_(network_loop),
46 capturer_(capturer), 46 capturer_(capturer),
47 encoder_(encoder), 47 encoder_(encoder),
48 started_(false), 48 started_(false),
49 network_stopped_(false),
49 recordings_(0), 50 recordings_(0),
50 frame_skipped_(false), 51 frame_skipped_(false),
51 max_rate_(kDefaultCaptureRate) { 52 max_rate_(kDefaultCaptureRate) {
52 DCHECK(capture_loop_); 53 DCHECK(capture_loop_);
53 DCHECK(encode_loop_); 54 DCHECK(encode_loop_);
54 DCHECK(network_loop_); 55 DCHECK(network_loop_);
55 } 56 }
56 57
57 ScreenRecorder::~ScreenRecorder() { 58 ScreenRecorder::~ScreenRecorder() {
58 connections_.clear(); 59 connections_.clear();
59 } 60 }
60 61
61 // Public methods -------------------------------------------------------------- 62 // Public methods --------------------------------------------------------------
62 63
63 void ScreenRecorder::Start() { 64 void ScreenRecorder::Start() {
64 capture_loop_->PostTask( 65 capture_loop_->PostTask(
65 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoStart)); 66 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoStart));
66 } 67 }
67 68
68 void ScreenRecorder::Pause() { 69 void ScreenRecorder::Stop(Task* task) {
69 capture_loop_->PostTask( 70 capture_loop_->PostTask(
70 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoPause)); 71 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoStop, task));
71 } 72 }
72 73
73 void ScreenRecorder::SetMaxRate(double rate) { 74 void ScreenRecorder::SetMaxRate(double rate) {
74 capture_loop_->PostTask( 75 capture_loop_->PostTask(
75 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoSetMaxRate, rate)); 76 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoSetMaxRate, rate));
76 } 77 }
77 78
78 void ScreenRecorder::AddConnection( 79 void ScreenRecorder::AddConnection(
79 scoped_refptr<ConnectionToClient> connection) { 80 scoped_refptr<ConnectionToClient> connection) {
80 ScopedTracer tracer("AddConnection"); 81 ScopedTracer tracer("AddConnection");
(...skipping 28 matching lines...) Expand all
109 Encoder* ScreenRecorder::encoder() { 110 Encoder* ScreenRecorder::encoder() {
110 DCHECK_EQ(encode_loop_, MessageLoop::current()); 111 DCHECK_EQ(encode_loop_, MessageLoop::current());
111 DCHECK(encoder_.get()); 112 DCHECK(encoder_.get());
112 return encoder_.get(); 113 return encoder_.get();
113 } 114 }
114 115
115 // Capturer thread ------------------------------------------------------------- 116 // Capturer thread -------------------------------------------------------------
116 117
117 void ScreenRecorder::DoStart() { 118 void ScreenRecorder::DoStart() {
118 DCHECK_EQ(capture_loop_, MessageLoop::current()); 119 DCHECK_EQ(capture_loop_, MessageLoop::current());
119 DCHECK(!started_);
120 120
121 if (started_) { 121 if (started_) {
122 NOTREACHED() << "Record session already started."; 122 NOTREACHED() << "Record session already started.";
123 return; 123 return;
124 } 124 }
125 125
126 started_ = true; 126 started_ = true;
127 StartCaptureTimer(); 127 StartCaptureTimer();
128 128
129 // Capture first frame immedately. 129 // Capture first frame immedately.
130 DoCapture(); 130 DoCapture();
131 } 131 }
132 132
133 void ScreenRecorder::DoPause() { 133 void ScreenRecorder::DoStop(Task* task) {
134 DCHECK_EQ(capture_loop_, MessageLoop::current()); 134 DCHECK_EQ(capture_loop_, MessageLoop::current());
135 135
136 if (!started_) { 136 if (!started_) {
137 NOTREACHED() << "Record session not started."; 137 NOTREACHED() << "Record session not started.";
138 return; 138 return;
139 } 139 }
140 140
141 capture_timer_.Stop(); 141 capture_timer_.Stop();
142 started_ = false; 142 started_ = false;
143
144 DCHECK_GE(recordings_, 0);
145 if (recordings_) {
146 network_loop_->PostTask(
147 FROM_HERE,
148 NewTracedMethod(this, &ScreenRecorder::DoStopOnNetworkThread, task));
149 return;
150 }
151
152 if (task) {
Sergey Ulanov 2011/01/20 19:14:17 Call DoCompleteStop()?
Alpha Left Google 2011/01/20 19:32:08 Done.
153 task->Run();
154 delete task;
155 }
156 }
157
158 void ScreenRecorder::DoCompleteStop(Task* task) {
159 DCHECK_EQ(capture_loop_, MessageLoop::current());
160
161 if (task) {
162 task->Run();
163 delete task;
164 }
143 } 165 }
144 166
145 void ScreenRecorder::DoSetMaxRate(double max_rate) { 167 void ScreenRecorder::DoSetMaxRate(double max_rate) {
146 DCHECK_EQ(capture_loop_, MessageLoop::current()); 168 DCHECK_EQ(capture_loop_, MessageLoop::current());
147 169
148 // TODO(hclam): Should also check for small epsilon. 170 // TODO(hclam): Should also check for small epsilon.
149 DCHECK_GT(max_rate, 0.0) << "Rate is too small."; 171 DCHECK_GT(max_rate, 0.0) << "Rate is too small.";
150 172
151 max_rate_ = max_rate; 173 max_rate_ = max_rate;
152 174
(...skipping 24 matching lines...) Expand all
177 199
178 if (frame_skipped_) { 200 if (frame_skipped_) {
179 frame_skipped_ = false; 201 frame_skipped_ = false;
180 capture_timer_.Reset(); 202 capture_timer_.Reset();
181 } 203 }
182 204
183 TraceContext::tracer()->PrintString("Capture Started"); 205 TraceContext::tracer()->PrintString("Capture Started");
184 206
185 // At this point we are going to perform one capture so save the current time. 207 // At this point we are going to perform one capture so save the current time.
186 ++recordings_; 208 ++recordings_;
209 DCHECK_LE(recordings_, kMaxRecordings);
187 210
188 // And finally perform one capture. 211 // And finally perform one capture.
189 capturer()->CaptureInvalidRects( 212 capturer()->CaptureInvalidRects(
190 NewCallback(this, &ScreenRecorder::CaptureDoneCallback)); 213 NewCallback(this, &ScreenRecorder::CaptureDoneCallback));
191 } 214 }
192 215
193 void ScreenRecorder::CaptureDoneCallback( 216 void ScreenRecorder::CaptureDoneCallback(
194 scoped_refptr<CaptureData> capture_data) { 217 scoped_refptr<CaptureData> capture_data) {
195 // TODO(hclam): There is a bug if the capturer doesn't produce any dirty
196 // rects.
197 DCHECK_EQ(capture_loop_, MessageLoop::current()); 218 DCHECK_EQ(capture_loop_, MessageLoop::current());
219
220 if (!started_)
221 return;
222
198 TraceContext::tracer()->PrintString("Capture Done"); 223 TraceContext::tracer()->PrintString("Capture Done");
199 encode_loop_->PostTask( 224 encode_loop_->PostTask(
200 FROM_HERE, 225 FROM_HERE,
201 NewTracedMethod(this, &ScreenRecorder::DoEncode, capture_data)); 226 NewTracedMethod(this, &ScreenRecorder::DoEncode, capture_data));
202 } 227 }
203 228
204 void ScreenRecorder::DoFinishSend() { 229 void ScreenRecorder::DoFinishOneRecording() {
205 DCHECK_EQ(capture_loop_, MessageLoop::current()); 230 DCHECK_EQ(capture_loop_, MessageLoop::current());
206 231
232 if (!started_)
233 return;
234
207 // Decrement the number of recording in process since we have completed 235 // Decrement the number of recording in process since we have completed
208 // one cycle. 236 // one cycle.
209 --recordings_; 237 --recordings_;
238 DCHECK_GE(recordings_, 0);
210 239
211 // Try to do a capture again. Note that the following method may do nothing 240 // Try to do a capture again. Note that the following method may do nothing
212 // if it is too early to perform a capture. 241 // if it is too early to perform a capture.
213 DoCapture(); 242 DoCapture();
214 } 243 }
215 244
216 // Network thread -------------------------------------------------------------- 245 // Network thread --------------------------------------------------------------
217 246
218 void ScreenRecorder::DoSendVideoPacket(VideoPacket* packet) { 247 void ScreenRecorder::DoSendVideoPacket(VideoPacket* packet) {
219 DCHECK_EQ(network_loop_, MessageLoop::current()); 248 DCHECK_EQ(network_loop_, MessageLoop::current());
220 249
221 TraceContext::tracer()->PrintString("DoSendVideoPacket"); 250 TraceContext::tracer()->PrintString("DoSendVideoPacket");
222 251
223 bool last = (packet->flags() & VideoPacket::LAST_PARTITION) != 0; 252 bool last = (packet->flags() & VideoPacket::LAST_PARTITION) != 0;
224 253
254 if (network_stopped_) {
255 delete packet;
256 return;
257 }
258
225 for (ConnectionToClientList::const_iterator i = connections_.begin(); 259 for (ConnectionToClientList::const_iterator i = connections_.begin();
226 i < connections_.end(); ++i) { 260 i < connections_.end(); ++i) {
227 Task* done_task = NULL; 261 Task* done_task = NULL;
228 262
229 // Call OnFrameSent() only for the last packet in the first connection. 263 // Call FrameSentCallback() only for the last packet in the first
264 // connection.
230 if (last && i == connections_.begin()) { 265 if (last && i == connections_.begin()) {
231 done_task = NewTracedMethod(this, &ScreenRecorder::OnFrameSent, packet); 266 done_task = NewTracedMethod(this, &ScreenRecorder::FrameSentCallback,
267 packet);
232 } else { 268 } else {
269 // TODO(hclam): Fix this code since it causes multiple deletion if there's
270 // more than one connection.
Sergey Ulanov 2011/01/20 19:14:17 I think we should just remove support for parallel
Alpha Left Google 2011/01/20 19:24:18 I'd leave the decision later, not really related t
233 done_task = new DeleteTask<VideoPacket>(packet); 271 done_task = new DeleteTask<VideoPacket>(packet);
234 } 272 }
235 273
236 (*i)->video_stub()->ProcessVideoPacket(packet, done_task); 274 (*i)->video_stub()->ProcessVideoPacket(packet, done_task);
237 } 275 }
238 276
239 TraceContext::tracer()->PrintString("DoSendVideoPacket done"); 277 TraceContext::tracer()->PrintString("DoSendVideoPacket done");
240 } 278 }
241 279
242 void ScreenRecorder::OnFrameSent(VideoPacket* packet) { 280 void ScreenRecorder::FrameSentCallback(VideoPacket* packet) {
243 delete packet; 281 delete packet;
282
283 if (network_stopped_)
Sergey Ulanov 2011/01/20 19:14:17 Do we really need network_stopped_? It should be s
Alpha Left Google 2011/01/20 19:24:18 The problem that needs network_stopped_ here is th
284 return;
285
244 capture_loop_->PostTask( 286 capture_loop_->PostTask(
245 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoFinishSend)); 287 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoFinishOneRecording));
246 } 288 }
247 289
248 void ScreenRecorder::DoAddConnection( 290 void ScreenRecorder::DoAddConnection(
249 scoped_refptr<ConnectionToClient> connection) { 291 scoped_refptr<ConnectionToClient> connection) {
250 DCHECK_EQ(network_loop_, MessageLoop::current()); 292 DCHECK_EQ(network_loop_, MessageLoop::current());
251 293
252 // TODO(hclam): Force a full frame for next encode. 294 // TODO(hclam): Force a full frame for next encode.
253 connections_.push_back(connection); 295 connections_.push_back(connection);
254 } 296 }
255 297
256 void ScreenRecorder::DoRemoveClient( 298 void ScreenRecorder::DoRemoveClient(
257 scoped_refptr<ConnectionToClient> connection) { 299 scoped_refptr<ConnectionToClient> connection) {
258 DCHECK_EQ(network_loop_, MessageLoop::current()); 300 DCHECK_EQ(network_loop_, MessageLoop::current());
259 301
260 // TODO(hclam): Is it correct to do to a scoped_refptr? 302 // TODO(hclam): Is it correct to do to a scoped_refptr?
261 ConnectionToClientList::iterator it = 303 ConnectionToClientList::iterator it =
262 std::find(connections_.begin(), connections_.end(), connection); 304 std::find(connections_.begin(), connections_.end(), connection);
263 if (it != connections_.end()) { 305 if (it != connections_.end()) {
264 connections_.erase(it); 306 connections_.erase(it);
265 } 307 }
266 } 308 }
267 309
268 void ScreenRecorder::DoRemoveAllClients() { 310 void ScreenRecorder::DoRemoveAllClients() {
269 DCHECK_EQ(network_loop_, MessageLoop::current()); 311 DCHECK_EQ(network_loop_, MessageLoop::current());
270 312
271 // Clear the list of connections. 313 // Clear the list of connections.
272 connections_.clear(); 314 connections_.clear();
273 } 315 }
274 316
317 void ScreenRecorder::DoStopOnNetworkThread(Task* task) {
318 DCHECK_EQ(network_loop_, MessageLoop::current());
319
320 // There could be tasks on the network thread when this method is being
321 // executed. By setting the flag we'll not post anymore tasks from network
322 // thread.
323 //
324 // After that a task is posted on encode thread to continue the stop
325 // sequence.
326 network_stopped_ = true;
327
328 encode_loop_->PostTask(
329 FROM_HERE,
330 NewTracedMethod(this, &ScreenRecorder::DoStopOnEncodeThread, task));
331 }
332
275 // Encoder thread -------------------------------------------------------------- 333 // Encoder thread --------------------------------------------------------------
276 334
277 void ScreenRecorder::DoEncode( 335 void ScreenRecorder::DoEncode(
278 scoped_refptr<CaptureData> capture_data) { 336 scoped_refptr<CaptureData> capture_data) {
279 DCHECK_EQ(encode_loop_, MessageLoop::current()); 337 DCHECK_EQ(encode_loop_, MessageLoop::current());
280 TraceContext::tracer()->PrintString("DoEncode called"); 338 TraceContext::tracer()->PrintString("DoEncode called");
281 339
282 // Early out if there's nothing to encode. 340 // Early out if there's nothing to encode.
283 if (!capture_data->dirty_rects().size()) { 341 if (!capture_data->dirty_rects().size()) {
284 capture_loop_->PostTask( 342 capture_loop_->PostTask(
285 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoFinishSend)); 343 FROM_HERE,
344 NewTracedMethod(this, &ScreenRecorder::DoFinishOneRecording));
286 return; 345 return;
287 } 346 }
288 347
289 // TODO(hclam): Enable |force_refresh| if a new connection was 348 // TODO(hclam): Invalid the full screen if there is a new connection added.
Sergey Ulanov 2011/01/20 19:14:17 Invalidate
290 // added.
291 TraceContext::tracer()->PrintString("Encode start"); 349 TraceContext::tracer()->PrintString("Encode start");
292 encoder()->Encode(capture_data, false, 350 encoder()->Encode(
293 NewCallback(this, &ScreenRecorder::EncodeDataAvailableTask)); 351 capture_data, false,
352 NewCallback(this, &ScreenRecorder::EncodedDataAvailableCallback));
294 TraceContext::tracer()->PrintString("Encode Done"); 353 TraceContext::tracer()->PrintString("Encode Done");
295 } 354 }
296 355
297 void ScreenRecorder::EncodeDataAvailableTask(VideoPacket* packet) { 356 void ScreenRecorder::DoStopOnEncodeThread(Task* task) {
357 DCHECK_EQ(encode_loop_, MessageLoop::current());
358
359 // When this method is being executed there are no more tasks on encode thread
360 // for this object. We can then post a task to capture thread to finish the
361 // stop sequence.
362 capture_loop_->PostTask(
363 FROM_HERE,
364 NewTracedMethod(this, &ScreenRecorder::DoCompleteStop, task));
365 }
366
367 void ScreenRecorder::EncodedDataAvailableCallback(VideoPacket* packet) {
298 DCHECK_EQ(encode_loop_, MessageLoop::current()); 368 DCHECK_EQ(encode_loop_, MessageLoop::current());
299 369
300 network_loop_->PostTask( 370 network_loop_->PostTask(
301 FROM_HERE, 371 FROM_HERE,
302 NewTracedMethod(this, &ScreenRecorder::DoSendVideoPacket, packet)); 372 NewTracedMethod(this, &ScreenRecorder::DoSendVideoPacket, packet));
303 } 373 }
304 374
305 } // namespace remoting 375 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698