| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 DCHECK(network_loop_); | 53 DCHECK(network_loop_); |
| 54 } | 54 } |
| 55 | 55 |
| 56 ScreenRecorder::~ScreenRecorder() { | 56 ScreenRecorder::~ScreenRecorder() { |
| 57 } | 57 } |
| 58 | 58 |
| 59 // Public methods -------------------------------------------------------------- | 59 // Public methods -------------------------------------------------------------- |
| 60 | 60 |
| 61 void ScreenRecorder::Start() { | 61 void ScreenRecorder::Start() { |
| 62 capture_loop_->PostTask( | 62 capture_loop_->PostTask( |
| 63 FROM_HERE, NewRunnableMethod(this, &ScreenRecorder::DoStart)); | 63 FROM_HERE, base::Bind(&ScreenRecorder::DoStart, this)); |
| 64 } | 64 } |
| 65 | 65 |
| 66 void ScreenRecorder::Stop(const base::Closure& done_task) { | 66 void ScreenRecorder::Stop(const base::Closure& done_task) { |
| 67 if (MessageLoop::current() != capture_loop_) { | 67 if (MessageLoop::current() != capture_loop_) { |
| 68 capture_loop_->PostTask(FROM_HERE, base::Bind( | 68 capture_loop_->PostTask(FROM_HERE, base::Bind( |
| 69 &ScreenRecorder::Stop, this, done_task)); | 69 &ScreenRecorder::Stop, this, done_task)); |
| 70 return; | 70 return; |
| 71 } | 71 } |
| 72 | 72 |
| 73 DCHECK(!done_task.is_null()); | 73 DCHECK(!done_task.is_null()); |
| 74 | 74 |
| 75 capture_timer_.Stop(); | 75 capture_timer_.Stop(); |
| 76 is_recording_ = false; | 76 is_recording_ = false; |
| 77 | 77 |
| 78 network_loop_->PostTask(FROM_HERE, base::Bind( | 78 network_loop_->PostTask(FROM_HERE, base::Bind( |
| 79 &ScreenRecorder::DoStopOnNetworkThread, this, done_task)); | 79 &ScreenRecorder::DoStopOnNetworkThread, this, done_task)); |
| 80 } | 80 } |
| 81 | 81 |
| 82 void ScreenRecorder::AddConnection( | 82 void ScreenRecorder::AddConnection( |
| 83 scoped_refptr<ConnectionToClient> connection) { | 83 scoped_refptr<ConnectionToClient> connection) { |
| 84 capture_loop_->PostTask( | 84 capture_loop_->PostTask( |
| 85 FROM_HERE, | 85 FROM_HERE, base::Bind(&ScreenRecorder::DoInvalidateFullScreen, this)); |
| 86 NewRunnableMethod(this, &ScreenRecorder::DoInvalidateFullScreen)); | |
| 87 | 86 |
| 88 // Add the client to the list so it can receive update stream. | 87 // Add the client to the list so it can receive update stream. |
| 89 network_loop_->PostTask( | 88 network_loop_->PostTask( |
| 90 FROM_HERE, | 89 FROM_HERE, base::Bind(&ScreenRecorder::DoAddConnection, |
| 91 NewRunnableMethod(this, &ScreenRecorder::DoAddConnection, connection)); | 90 this, connection)); |
| 92 } | 91 } |
| 93 | 92 |
| 94 void ScreenRecorder::RemoveConnection( | 93 void ScreenRecorder::RemoveConnection( |
| 95 scoped_refptr<ConnectionToClient> connection) { | 94 scoped_refptr<ConnectionToClient> connection) { |
| 96 network_loop_->PostTask( | 95 network_loop_->PostTask( |
| 97 FROM_HERE, | 96 FROM_HERE, base::Bind(&ScreenRecorder::DoRemoveClient, this, connection)); |
| 98 NewRunnableMethod(this, &ScreenRecorder::DoRemoveClient, connection)); | |
| 99 } | 97 } |
| 100 | 98 |
| 101 void ScreenRecorder::RemoveAllConnections() { | 99 void ScreenRecorder::RemoveAllConnections() { |
| 102 network_loop_->PostTask( | 100 network_loop_->PostTask( |
| 103 FROM_HERE, | 101 FROM_HERE, base::Bind(&ScreenRecorder::DoRemoveAllClients, this)); |
| 104 NewRunnableMethod(this, &ScreenRecorder::DoRemoveAllClients)); | |
| 105 } | 102 } |
| 106 | 103 |
| 107 void ScreenRecorder::UpdateSequenceNumber(int64 sequence_number) { | 104 void ScreenRecorder::UpdateSequenceNumber(int64 sequence_number) { |
| 108 // Sequence number is used and written only on the capture thread. | 105 // Sequence number is used and written only on the capture thread. |
| 109 if (MessageLoop::current() != capture_loop_) { | 106 if (MessageLoop::current() != capture_loop_) { |
| 110 capture_loop_->PostTask( | 107 capture_loop_->PostTask( |
| 111 FROM_HERE, | 108 FROM_HERE, base::Bind(&ScreenRecorder::UpdateSequenceNumber, |
| 112 NewRunnableMethod(this, &ScreenRecorder::UpdateSequenceNumber, | 109 this, sequence_number)); |
| 113 sequence_number)); | |
| 114 return; | 110 return; |
| 115 } | 111 } |
| 116 | 112 |
| 117 sequence_number_ = sequence_number; | 113 sequence_number_ = sequence_number; |
| 118 } | 114 } |
| 119 | 115 |
| 120 // Private accessors ----------------------------------------------------------- | 116 // Private accessors ----------------------------------------------------------- |
| 121 | 117 |
| 122 Capturer* ScreenRecorder::capturer() { | 118 Capturer* ScreenRecorder::capturer() { |
| 123 DCHECK_EQ(capture_loop_, MessageLoop::current()); | 119 DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 // Before doing a capture schedule for the next one. | 172 // Before doing a capture schedule for the next one. |
| 177 capture_timer_.Stop(); | 173 capture_timer_.Stop(); |
| 178 capture_timer_.Start(FROM_HERE, | 174 capture_timer_.Start(FROM_HERE, |
| 179 scheduler_.NextCaptureDelay(), | 175 scheduler_.NextCaptureDelay(), |
| 180 this, | 176 this, |
| 181 &ScreenRecorder::DoCapture); | 177 &ScreenRecorder::DoCapture); |
| 182 | 178 |
| 183 // And finally perform one capture. | 179 // And finally perform one capture. |
| 184 capture_start_time_ = base::Time::Now(); | 180 capture_start_time_ = base::Time::Now(); |
| 185 capturer()->CaptureInvalidRegion( | 181 capturer()->CaptureInvalidRegion( |
| 186 NewCallback(this, &ScreenRecorder::CaptureDoneCallback)); | 182 base::Bind(&ScreenRecorder::CaptureDoneCallback, this)); |
| 187 } | 183 } |
| 188 | 184 |
| 189 void ScreenRecorder::CaptureDoneCallback( | 185 void ScreenRecorder::CaptureDoneCallback( |
| 190 scoped_refptr<CaptureData> capture_data) { | 186 scoped_refptr<CaptureData> capture_data) { |
| 191 DCHECK_EQ(capture_loop_, MessageLoop::current()); | 187 DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| 192 | 188 |
| 193 if (!is_recording_) | 189 if (!is_recording_) |
| 194 return; | 190 return; |
| 195 | 191 |
| 196 if (capture_data) { | 192 if (capture_data) { |
| 197 base::TimeDelta capture_time = base::Time::Now() - capture_start_time_; | 193 base::TimeDelta capture_time = base::Time::Now() - capture_start_time_; |
| 198 int capture_time_ms = | 194 int capture_time_ms = |
| 199 static_cast<int>(capture_time.InMilliseconds()); | 195 static_cast<int>(capture_time.InMilliseconds()); |
| 200 capture_data->set_capture_time_ms(capture_time_ms); | 196 capture_data->set_capture_time_ms(capture_time_ms); |
| 201 scheduler_.RecordCaptureTime(capture_time); | 197 scheduler_.RecordCaptureTime(capture_time); |
| 202 | 198 |
| 203 // The best way to get this value is by binding the sequence number to | 199 // The best way to get this value is by binding the sequence number to |
| 204 // the callback when calling CaptureInvalidRects(). However the callback | 200 // the callback when calling CaptureInvalidRects(). However the callback |
| 205 // system doesn't allow this. Reading from the member variable is | 201 // system doesn't allow this. Reading from the member variable is |
| 206 // accurate as long as capture is synchronous as the following statement | 202 // accurate as long as capture is synchronous as the following statement |
| 207 // will obtain the most recent sequence number received. | 203 // will obtain the most recent sequence number received. |
| 208 capture_data->set_client_sequence_number(sequence_number_); | 204 capture_data->set_client_sequence_number(sequence_number_); |
| 209 } | 205 } |
| 210 | 206 |
| 211 encode_loop_->PostTask( | 207 encode_loop_->PostTask( |
| 212 FROM_HERE, | 208 FROM_HERE, base::Bind(&ScreenRecorder::DoEncode, this, capture_data)); |
| 213 NewRunnableMethod(this, &ScreenRecorder::DoEncode, capture_data)); | |
| 214 } | 209 } |
| 215 | 210 |
| 216 void ScreenRecorder::DoFinishOneRecording() { | 211 void ScreenRecorder::DoFinishOneRecording() { |
| 217 DCHECK_EQ(capture_loop_, MessageLoop::current()); | 212 DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| 218 | 213 |
| 219 if (!is_recording_) | 214 if (!is_recording_) |
| 220 return; | 215 return; |
| 221 | 216 |
| 222 // Decrement the number of recording in process since we have completed | 217 // Decrement the number of recording in process since we have completed |
| 223 // one cycle. | 218 // one cycle. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 } | 261 } |
| 267 } | 262 } |
| 268 | 263 |
| 269 void ScreenRecorder::FrameSentCallback(VideoPacket* packet) { | 264 void ScreenRecorder::FrameSentCallback(VideoPacket* packet) { |
| 270 delete packet; | 265 delete packet; |
| 271 | 266 |
| 272 if (network_stopped_) | 267 if (network_stopped_) |
| 273 return; | 268 return; |
| 274 | 269 |
| 275 capture_loop_->PostTask( | 270 capture_loop_->PostTask( |
| 276 FROM_HERE, NewRunnableMethod(this, | 271 FROM_HERE, base::Bind(&ScreenRecorder::DoFinishOneRecording, this)); |
| 277 &ScreenRecorder::DoFinishOneRecording)); | |
| 278 } | 272 } |
| 279 | 273 |
| 280 void ScreenRecorder::DoAddConnection( | 274 void ScreenRecorder::DoAddConnection( |
| 281 scoped_refptr<ConnectionToClient> connection) { | 275 scoped_refptr<ConnectionToClient> connection) { |
| 282 DCHECK(network_loop_->BelongsToCurrentThread()); | 276 DCHECK(network_loop_->BelongsToCurrentThread()); |
| 283 | 277 |
| 284 connections_.push_back(connection); | 278 connections_.push_back(connection); |
| 285 } | 279 } |
| 286 | 280 |
| 287 void ScreenRecorder::DoRemoveClient( | 281 void ScreenRecorder::DoRemoveClient( |
| (...skipping 19 matching lines...) Expand all Loading... |
| 307 | 301 |
| 308 // There could be tasks on the network thread when this method is being | 302 // There could be tasks on the network thread when this method is being |
| 309 // executed. By setting the flag we'll not post anymore tasks from network | 303 // executed. By setting the flag we'll not post anymore tasks from network |
| 310 // thread. | 304 // thread. |
| 311 // | 305 // |
| 312 // After that a task is posted on encode thread to continue the stop | 306 // After that a task is posted on encode thread to continue the stop |
| 313 // sequence. | 307 // sequence. |
| 314 network_stopped_ = true; | 308 network_stopped_ = true; |
| 315 | 309 |
| 316 encode_loop_->PostTask( | 310 encode_loop_->PostTask( |
| 317 FROM_HERE, | 311 FROM_HERE, base::Bind(&ScreenRecorder::DoStopOnEncodeThread, |
| 318 NewRunnableMethod(this, &ScreenRecorder::DoStopOnEncodeThread, | 312 this, done_task)); |
| 319 done_task)); | |
| 320 } | 313 } |
| 321 | 314 |
| 322 // Encoder thread -------------------------------------------------------------- | 315 // Encoder thread -------------------------------------------------------------- |
| 323 | 316 |
| 324 void ScreenRecorder::DoEncode( | 317 void ScreenRecorder::DoEncode( |
| 325 scoped_refptr<CaptureData> capture_data) { | 318 scoped_refptr<CaptureData> capture_data) { |
| 326 DCHECK_EQ(encode_loop_, MessageLoop::current()); | 319 DCHECK_EQ(encode_loop_, MessageLoop::current()); |
| 327 | 320 |
| 328 // Early out if there's nothing to encode. | 321 // Early out if there's nothing to encode. |
| 329 if (!capture_data || capture_data->dirty_region().isEmpty()) { | 322 if (!capture_data || capture_data->dirty_region().isEmpty()) { |
| 330 // Send an empty video packet to keep network active. | 323 // Send an empty video packet to keep network active. |
| 331 VideoPacket* packet = new VideoPacket(); | 324 VideoPacket* packet = new VideoPacket(); |
| 332 packet->set_flags(VideoPacket::LAST_PARTITION); | 325 packet->set_flags(VideoPacket::LAST_PARTITION); |
| 333 network_loop_->PostTask( | 326 network_loop_->PostTask( |
| 334 FROM_HERE, | 327 FROM_HERE, base::Bind(&ScreenRecorder::DoSendVideoPacket, |
| 335 NewRunnableMethod(this, | 328 this, packet)); |
| 336 &ScreenRecorder::DoSendVideoPacket, | |
| 337 packet)); | |
| 338 return; | 329 return; |
| 339 } | 330 } |
| 340 | 331 |
| 341 encode_start_time_ = base::Time::Now(); | 332 encode_start_time_ = base::Time::Now(); |
| 342 encoder()->Encode( | 333 encoder()->Encode( |
| 343 capture_data, false, | 334 capture_data, false, |
| 344 NewCallback(this, &ScreenRecorder::EncodedDataAvailableCallback)); | 335 base::Bind(&ScreenRecorder::EncodedDataAvailableCallback, this)); |
| 345 } | 336 } |
| 346 | 337 |
| 347 void ScreenRecorder::DoStopOnEncodeThread(const base::Closure& done_task) { | 338 void ScreenRecorder::DoStopOnEncodeThread(const base::Closure& done_task) { |
| 348 DCHECK_EQ(encode_loop_, MessageLoop::current()); | 339 DCHECK_EQ(encode_loop_, MessageLoop::current()); |
| 349 | 340 |
| 350 encoder_stopped_ = true; | 341 encoder_stopped_ = true; |
| 351 | 342 |
| 352 // When this method is being executed there are no more tasks on encode thread | 343 // When this method is being executed there are no more tasks on encode thread |
| 353 // for this object. We can then post a task to capture thread to finish the | 344 // for this object. We can then post a task to capture thread to finish the |
| 354 // stop sequence. | 345 // stop sequence. |
| 355 capture_loop_->PostTask(FROM_HERE, done_task); | 346 capture_loop_->PostTask(FROM_HERE, done_task); |
| 356 } | 347 } |
| 357 | 348 |
| 358 void ScreenRecorder::EncodedDataAvailableCallback(VideoPacket* packet) { | 349 void ScreenRecorder::EncodedDataAvailableCallback(VideoPacket* packet) { |
| 359 DCHECK_EQ(encode_loop_, MessageLoop::current()); | 350 DCHECK_EQ(encode_loop_, MessageLoop::current()); |
| 360 | 351 |
| 361 if (encoder_stopped_) | 352 if (encoder_stopped_) |
| 362 return; | 353 return; |
| 363 | 354 |
| 364 bool last = (packet->flags() & VideoPacket::LAST_PACKET) != 0; | 355 bool last = (packet->flags() & VideoPacket::LAST_PACKET) != 0; |
| 365 if (last) { | 356 if (last) { |
| 366 base::TimeDelta encode_time = base::Time::Now() - encode_start_time_; | 357 base::TimeDelta encode_time = base::Time::Now() - encode_start_time_; |
| 367 int encode_time_ms = | 358 int encode_time_ms = |
| 368 static_cast<int>(encode_time.InMilliseconds()); | 359 static_cast<int>(encode_time.InMilliseconds()); |
| 369 packet->set_encode_time_ms(encode_time_ms); | 360 packet->set_encode_time_ms(encode_time_ms); |
| 370 scheduler_.RecordEncodeTime(encode_time); | 361 scheduler_.RecordEncodeTime(encode_time); |
| 371 } | 362 } |
| 372 | 363 |
| 373 network_loop_->PostTask( | 364 network_loop_->PostTask( |
| 374 FROM_HERE, | 365 FROM_HERE, base::Bind(&ScreenRecorder::DoSendVideoPacket, this, packet)); |
| 375 NewRunnableMethod(this, &ScreenRecorder::DoSendVideoPacket, packet)); | |
| 376 } | 366 } |
| 377 | 367 |
| 378 } // namespace remoting | 368 } // namespace remoting |
| OLD | NEW |