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

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: fix style 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
« no previous file with comments | « remoting/host/screen_recorder.h ('k') | remoting/host/screen_recorder_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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* done_task) {
69 capture_loop_->PostTask( 70 capture_loop_->PostTask(
70 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoPause)); 71 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoStop, done_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* done_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,
149 &ScreenRecorder::DoStopOnNetworkThread, done_task));
150 return;
151 }
152
153 DoCompleteStop(done_task);
154 }
155
156 void ScreenRecorder::DoCompleteStop(Task* done_task) {
157 DCHECK_EQ(capture_loop_, MessageLoop::current());
158
159 if (done_task) {
160 done_task->Run();
161 delete done_task;
162 }
143 } 163 }
144 164
145 void ScreenRecorder::DoSetMaxRate(double max_rate) { 165 void ScreenRecorder::DoSetMaxRate(double max_rate) {
146 DCHECK_EQ(capture_loop_, MessageLoop::current()); 166 DCHECK_EQ(capture_loop_, MessageLoop::current());
147 167
148 // TODO(hclam): Should also check for small epsilon. 168 // TODO(hclam): Should also check for small epsilon.
149 DCHECK_GT(max_rate, 0.0) << "Rate is too small."; 169 DCHECK_GT(max_rate, 0.0) << "Rate is too small.";
150 170
151 max_rate_ = max_rate; 171 max_rate_ = max_rate;
152 172
(...skipping 24 matching lines...) Expand all
177 197
178 if (frame_skipped_) { 198 if (frame_skipped_) {
179 frame_skipped_ = false; 199 frame_skipped_ = false;
180 capture_timer_.Reset(); 200 capture_timer_.Reset();
181 } 201 }
182 202
183 TraceContext::tracer()->PrintString("Capture Started"); 203 TraceContext::tracer()->PrintString("Capture Started");
184 204
185 // At this point we are going to perform one capture so save the current time. 205 // At this point we are going to perform one capture so save the current time.
186 ++recordings_; 206 ++recordings_;
207 DCHECK_LE(recordings_, kMaxRecordings);
187 208
188 // And finally perform one capture. 209 // And finally perform one capture.
189 capturer()->CaptureInvalidRects( 210 capturer()->CaptureInvalidRects(
190 NewCallback(this, &ScreenRecorder::CaptureDoneCallback)); 211 NewCallback(this, &ScreenRecorder::CaptureDoneCallback));
191 } 212 }
192 213
193 void ScreenRecorder::CaptureDoneCallback( 214 void ScreenRecorder::CaptureDoneCallback(
194 scoped_refptr<CaptureData> capture_data) { 215 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()); 216 DCHECK_EQ(capture_loop_, MessageLoop::current());
217
218 if (!started_)
219 return;
220
198 TraceContext::tracer()->PrintString("Capture Done"); 221 TraceContext::tracer()->PrintString("Capture Done");
199 encode_loop_->PostTask( 222 encode_loop_->PostTask(
200 FROM_HERE, 223 FROM_HERE,
201 NewTracedMethod(this, &ScreenRecorder::DoEncode, capture_data)); 224 NewTracedMethod(this, &ScreenRecorder::DoEncode, capture_data));
202 } 225 }
203 226
204 void ScreenRecorder::DoFinishSend() { 227 void ScreenRecorder::DoFinishOneRecording() {
205 DCHECK_EQ(capture_loop_, MessageLoop::current()); 228 DCHECK_EQ(capture_loop_, MessageLoop::current());
206 229
230 if (!started_)
231 return;
232
207 // Decrement the number of recording in process since we have completed 233 // Decrement the number of recording in process since we have completed
208 // one cycle. 234 // one cycle.
209 --recordings_; 235 --recordings_;
236 DCHECK_GE(recordings_, 0);
210 237
211 // Try to do a capture again. Note that the following method may do nothing 238 // Try to do a capture again. Note that the following method may do nothing
212 // if it is too early to perform a capture. 239 // if it is too early to perform a capture.
213 DoCapture(); 240 DoCapture();
214 } 241 }
215 242
216 // Network thread -------------------------------------------------------------- 243 // Network thread --------------------------------------------------------------
217 244
218 void ScreenRecorder::DoSendVideoPacket(VideoPacket* packet) { 245 void ScreenRecorder::DoSendVideoPacket(VideoPacket* packet) {
219 DCHECK_EQ(network_loop_, MessageLoop::current()); 246 DCHECK_EQ(network_loop_, MessageLoop::current());
220 247
221 TraceContext::tracer()->PrintString("DoSendVideoPacket"); 248 TraceContext::tracer()->PrintString("DoSendVideoPacket");
222 249
223 bool last = (packet->flags() & VideoPacket::LAST_PARTITION) != 0; 250 bool last = (packet->flags() & VideoPacket::LAST_PARTITION) != 0;
224 251
252 if (network_stopped_) {
253 delete packet;
254 return;
255 }
256
225 for (ConnectionToClientList::const_iterator i = connections_.begin(); 257 for (ConnectionToClientList::const_iterator i = connections_.begin();
226 i < connections_.end(); ++i) { 258 i < connections_.end(); ++i) {
227 Task* done_task = NULL; 259 Task* done_task = NULL;
228 260
229 // Call OnFrameSent() only for the last packet in the first connection. 261 // Call FrameSentCallback() only for the last packet in the first
262 // connection.
230 if (last && i == connections_.begin()) { 263 if (last && i == connections_.begin()) {
231 done_task = NewTracedMethod(this, &ScreenRecorder::OnFrameSent, packet); 264 done_task = NewTracedMethod(this, &ScreenRecorder::FrameSentCallback,
265 packet);
232 } else { 266 } else {
267 // TODO(hclam): Fix this code since it causes multiple deletion if there's
268 // more than one connection.
233 done_task = new DeleteTask<VideoPacket>(packet); 269 done_task = new DeleteTask<VideoPacket>(packet);
234 } 270 }
235 271
236 (*i)->video_stub()->ProcessVideoPacket(packet, done_task); 272 (*i)->video_stub()->ProcessVideoPacket(packet, done_task);
237 } 273 }
238 274
239 TraceContext::tracer()->PrintString("DoSendVideoPacket done"); 275 TraceContext::tracer()->PrintString("DoSendVideoPacket done");
240 } 276 }
241 277
242 void ScreenRecorder::OnFrameSent(VideoPacket* packet) { 278 void ScreenRecorder::FrameSentCallback(VideoPacket* packet) {
243 delete packet; 279 delete packet;
280
281 if (network_stopped_)
282 return;
283
244 capture_loop_->PostTask( 284 capture_loop_->PostTask(
245 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoFinishSend)); 285 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoFinishOneRecording));
246 } 286 }
247 287
248 void ScreenRecorder::DoAddConnection( 288 void ScreenRecorder::DoAddConnection(
249 scoped_refptr<ConnectionToClient> connection) { 289 scoped_refptr<ConnectionToClient> connection) {
250 DCHECK_EQ(network_loop_, MessageLoop::current()); 290 DCHECK_EQ(network_loop_, MessageLoop::current());
251 291
252 // TODO(hclam): Force a full frame for next encode. 292 // TODO(hclam): Force a full frame for next encode.
253 connections_.push_back(connection); 293 connections_.push_back(connection);
254 } 294 }
255 295
256 void ScreenRecorder::DoRemoveClient( 296 void ScreenRecorder::DoRemoveClient(
257 scoped_refptr<ConnectionToClient> connection) { 297 scoped_refptr<ConnectionToClient> connection) {
258 DCHECK_EQ(network_loop_, MessageLoop::current()); 298 DCHECK_EQ(network_loop_, MessageLoop::current());
259 299
260 // TODO(hclam): Is it correct to do to a scoped_refptr? 300 // TODO(hclam): Is it correct to do to a scoped_refptr?
261 ConnectionToClientList::iterator it = 301 ConnectionToClientList::iterator it =
262 std::find(connections_.begin(), connections_.end(), connection); 302 std::find(connections_.begin(), connections_.end(), connection);
263 if (it != connections_.end()) { 303 if (it != connections_.end()) {
264 connections_.erase(it); 304 connections_.erase(it);
265 } 305 }
266 } 306 }
267 307
268 void ScreenRecorder::DoRemoveAllClients() { 308 void ScreenRecorder::DoRemoveAllClients() {
269 DCHECK_EQ(network_loop_, MessageLoop::current()); 309 DCHECK_EQ(network_loop_, MessageLoop::current());
270 310
271 // Clear the list of connections. 311 // Clear the list of connections.
272 connections_.clear(); 312 connections_.clear();
273 } 313 }
274 314
315 void ScreenRecorder::DoStopOnNetworkThread(Task* done_task) {
316 DCHECK_EQ(network_loop_, MessageLoop::current());
317
318 // There could be tasks on the network thread when this method is being
319 // executed. By setting the flag we'll not post anymore tasks from network
320 // thread.
321 //
322 // After that a task is posted on encode thread to continue the stop
323 // sequence.
324 network_stopped_ = true;
325
326 encode_loop_->PostTask(
327 FROM_HERE,
328 NewTracedMethod(this, &ScreenRecorder::DoStopOnEncodeThread, done_task));
329 }
330
275 // Encoder thread -------------------------------------------------------------- 331 // Encoder thread --------------------------------------------------------------
276 332
277 void ScreenRecorder::DoEncode( 333 void ScreenRecorder::DoEncode(
278 scoped_refptr<CaptureData> capture_data) { 334 scoped_refptr<CaptureData> capture_data) {
279 DCHECK_EQ(encode_loop_, MessageLoop::current()); 335 DCHECK_EQ(encode_loop_, MessageLoop::current());
280 TraceContext::tracer()->PrintString("DoEncode called"); 336 TraceContext::tracer()->PrintString("DoEncode called");
281 337
282 // Early out if there's nothing to encode. 338 // Early out if there's nothing to encode.
283 if (!capture_data->dirty_rects().size()) { 339 if (!capture_data->dirty_rects().size()) {
284 capture_loop_->PostTask( 340 capture_loop_->PostTask(
285 FROM_HERE, NewTracedMethod(this, &ScreenRecorder::DoFinishSend)); 341 FROM_HERE,
342 NewTracedMethod(this, &ScreenRecorder::DoFinishOneRecording));
286 return; 343 return;
287 } 344 }
288 345
289 // TODO(hclam): Enable |force_refresh| if a new connection was 346 // TODO(hclam): Invalid the full screen if there is a new connection added.
Sergey Ulanov 2011/01/20 20:00:06 s/Invalid/Invalidate/
290 // added.
291 TraceContext::tracer()->PrintString("Encode start"); 347 TraceContext::tracer()->PrintString("Encode start");
292 encoder()->Encode(capture_data, false, 348 encoder()->Encode(
293 NewCallback(this, &ScreenRecorder::EncodeDataAvailableTask)); 349 capture_data, false,
350 NewCallback(this, &ScreenRecorder::EncodedDataAvailableCallback));
294 TraceContext::tracer()->PrintString("Encode Done"); 351 TraceContext::tracer()->PrintString("Encode Done");
295 } 352 }
296 353
297 void ScreenRecorder::EncodeDataAvailableTask(VideoPacket* packet) { 354 void ScreenRecorder::DoStopOnEncodeThread(Task* done_task) {
355 DCHECK_EQ(encode_loop_, MessageLoop::current());
356
357 // When this method is being executed there are no more tasks on encode thread
358 // for this object. We can then post a task to capture thread to finish the
359 // stop sequence.
360 capture_loop_->PostTask(
361 FROM_HERE,
362 NewTracedMethod(this, &ScreenRecorder::DoCompleteStop, done_task));
363 }
364
365 void ScreenRecorder::EncodedDataAvailableCallback(VideoPacket* packet) {
298 DCHECK_EQ(encode_loop_, MessageLoop::current()); 366 DCHECK_EQ(encode_loop_, MessageLoop::current());
299 367
300 network_loop_->PostTask( 368 network_loop_->PostTask(
301 FROM_HERE, 369 FROM_HERE,
302 NewTracedMethod(this, &ScreenRecorder::DoSendVideoPacket, packet)); 370 NewTracedMethod(this, &ScreenRecorder::DoSendVideoPacket, packet));
303 } 371 }
304 372
305 } // namespace remoting 373 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/screen_recorder.h ('k') | remoting/host/screen_recorder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698