| 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/callback.h" | 10 #include "base/callback.h" |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 } | 227 } |
| 228 | 228 |
| 229 void ScreenRecorder::DoInvalidateFullScreen() { | 229 void ScreenRecorder::DoInvalidateFullScreen() { |
| 230 DCHECK_EQ(capture_loop_, MessageLoop::current()); | 230 DCHECK_EQ(capture_loop_, MessageLoop::current()); |
| 231 | 231 |
| 232 capturer_->InvalidateFullScreen(); | 232 capturer_->InvalidateFullScreen(); |
| 233 } | 233 } |
| 234 | 234 |
| 235 // Network thread -------------------------------------------------------------- | 235 // Network thread -------------------------------------------------------------- |
| 236 | 236 |
| 237 void ScreenRecorder::DoSendVideoPacket(VideoPacket* packet) { | 237 void ScreenRecorder::DoSendVideoPacket(scoped_ptr<VideoPacket> packet) { |
| 238 DCHECK(network_loop_->BelongsToCurrentThread()); | 238 DCHECK(network_loop_->BelongsToCurrentThread()); |
| 239 | 239 |
| 240 bool last = (packet->flags() & VideoPacket::LAST_PARTITION) != 0; | 240 if (network_stopped_ || connections_.empty()) |
| 241 return; |
| 241 | 242 |
| 242 if (network_stopped_ || connections_.empty()) { | 243 // TODO(sergeyu): Currently we send the data only to the first |
| 243 delete packet; | 244 // connection. Send it to all connections if necessary. |
| 245 connections_.front()->video_stub()->ProcessVideoPacket( |
| 246 packet.get(), base::Bind( |
| 247 &ScreenRecorder::VideoPacketSentCallback, this, |
| 248 base::Passed(packet.Pass()))); |
| 249 } |
| 250 |
| 251 void ScreenRecorder::VideoPacketSentCallback(scoped_ptr<VideoPacket> packet) { |
| 252 if (network_stopped_) |
| 244 return; | 253 return; |
| 245 } | |
| 246 | 254 |
| 247 for (ConnectionToClientList::const_iterator i = connections_.begin(); | 255 if ((packet->flags() & VideoPacket::LAST_PARTITION) != 0) { |
| 248 i < connections_.end(); ++i) { | 256 // Post DoFinishOneRecording() if that was the last packet for the |
| 249 base::Closure done_task; | 257 // frame. |
| 250 | 258 capture_loop_->PostTask( |
| 251 // Call FrameSentCallback() only for the last packet in the first | 259 FROM_HERE, base::Bind(&ScreenRecorder::DoFinishOneRecording, this)); |
| 252 // connection. | |
| 253 if (last && i == connections_.begin()) { | |
| 254 done_task = base::Bind(&ScreenRecorder::FrameSentCallback, this, packet); | |
| 255 } else { | |
| 256 // TODO(hclam): Fix this code since it causes multiple deletion if there's | |
| 257 // more than one connection. | |
| 258 done_task = base::Bind(&base::DeletePointer<VideoPacket>, packet); | |
| 259 } | |
| 260 | |
| 261 (*i)->video_stub()->ProcessVideoPacket(packet, done_task); | |
| 262 } | 260 } |
| 263 } | 261 } |
| 264 | 262 |
| 265 void ScreenRecorder::FrameSentCallback(VideoPacket* packet) { | |
| 266 delete packet; | |
| 267 | |
| 268 if (network_stopped_) | |
| 269 return; | |
| 270 | |
| 271 capture_loop_->PostTask( | |
| 272 FROM_HERE, base::Bind(&ScreenRecorder::DoFinishOneRecording, this)); | |
| 273 } | |
| 274 | |
| 275 void ScreenRecorder::DoStopOnNetworkThread(const base::Closure& done_task) { | 263 void ScreenRecorder::DoStopOnNetworkThread(const base::Closure& done_task) { |
| 276 DCHECK(network_loop_->BelongsToCurrentThread()); | 264 DCHECK(network_loop_->BelongsToCurrentThread()); |
| 277 | 265 |
| 278 // There could be tasks on the network thread when this method is being | 266 // There could be tasks on the network thread when this method is being |
| 279 // executed. By setting the flag we'll not post anymore tasks from network | 267 // executed. By setting the flag we'll not post anymore tasks from network |
| 280 // thread. | 268 // thread. |
| 281 // | 269 // |
| 282 // After that a task is posted on encode thread to continue the stop | 270 // After that a task is posted on encode thread to continue the stop |
| 283 // sequence. | 271 // sequence. |
| 284 network_stopped_ = true; | 272 network_stopped_ = true; |
| 285 | 273 |
| 286 encode_loop_->PostTask( | 274 encode_loop_->PostTask( |
| 287 FROM_HERE, base::Bind(&ScreenRecorder::DoStopOnEncodeThread, | 275 FROM_HERE, base::Bind(&ScreenRecorder::DoStopOnEncodeThread, |
| 288 this, done_task)); | 276 this, done_task)); |
| 289 } | 277 } |
| 290 | 278 |
| 291 // Encoder thread -------------------------------------------------------------- | 279 // Encoder thread -------------------------------------------------------------- |
| 292 | 280 |
| 293 void ScreenRecorder::DoEncode( | 281 void ScreenRecorder::DoEncode( |
| 294 scoped_refptr<CaptureData> capture_data) { | 282 scoped_refptr<CaptureData> capture_data) { |
| 295 DCHECK_EQ(encode_loop_, MessageLoop::current()); | 283 DCHECK_EQ(encode_loop_, MessageLoop::current()); |
| 296 | 284 |
| 297 // Early out if there's nothing to encode. | 285 // Early out if there's nothing to encode. |
| 298 if (!capture_data || capture_data->dirty_region().isEmpty()) { | 286 if (!capture_data || capture_data->dirty_region().isEmpty()) { |
| 299 // Send an empty video packet to keep network active. | 287 // Send an empty video packet to keep network active. |
| 300 VideoPacket* packet = new VideoPacket(); | 288 scoped_ptr<VideoPacket> packet(new VideoPacket()); |
| 301 packet->set_flags(VideoPacket::LAST_PARTITION); | 289 packet->set_flags(VideoPacket::LAST_PARTITION); |
| 302 network_loop_->PostTask( | 290 network_loop_->PostTask( |
| 303 FROM_HERE, base::Bind(&ScreenRecorder::DoSendVideoPacket, | 291 FROM_HERE, base::Bind(&ScreenRecorder::DoSendVideoPacket, |
| 304 this, packet)); | 292 this, base::Passed(packet.Pass()))); |
| 305 return; | 293 return; |
| 306 } | 294 } |
| 307 | 295 |
| 308 encode_start_time_ = base::Time::Now(); | 296 encode_start_time_ = base::Time::Now(); |
| 309 encoder()->Encode( | 297 encoder()->Encode( |
| 310 capture_data, false, | 298 capture_data, false, |
| 311 base::Bind(&ScreenRecorder::EncodedDataAvailableCallback, this)); | 299 base::Bind(&ScreenRecorder::EncodedDataAvailableCallback, this)); |
| 312 } | 300 } |
| 313 | 301 |
| 314 void ScreenRecorder::DoStopOnEncodeThread(const base::Closure& done_task) { | 302 void ScreenRecorder::DoStopOnEncodeThread(const base::Closure& done_task) { |
| 315 DCHECK_EQ(encode_loop_, MessageLoop::current()); | 303 DCHECK_EQ(encode_loop_, MessageLoop::current()); |
| 316 | 304 |
| 317 encoder_stopped_ = true; | 305 encoder_stopped_ = true; |
| 318 | 306 |
| 319 // When this method is being executed there are no more tasks on encode thread | 307 // When this method is being executed there are no more tasks on encode thread |
| 320 // for this object. We can then post a task to capture thread to finish the | 308 // for this object. We can then post a task to capture thread to finish the |
| 321 // stop sequence. | 309 // stop sequence. |
| 322 capture_loop_->PostTask(FROM_HERE, done_task); | 310 capture_loop_->PostTask(FROM_HERE, done_task); |
| 323 } | 311 } |
| 324 | 312 |
| 325 void ScreenRecorder::EncodedDataAvailableCallback(VideoPacket* packet) { | 313 void ScreenRecorder::EncodedDataAvailableCallback( |
| 314 scoped_ptr<VideoPacket> packet) { |
| 326 DCHECK_EQ(encode_loop_, MessageLoop::current()); | 315 DCHECK_EQ(encode_loop_, MessageLoop::current()); |
| 327 | 316 |
| 328 if (encoder_stopped_) | 317 if (encoder_stopped_) |
| 329 return; | 318 return; |
| 330 | 319 |
| 331 bool last = (packet->flags() & VideoPacket::LAST_PACKET) != 0; | 320 bool last = (packet->flags() & VideoPacket::LAST_PACKET) != 0; |
| 332 if (last) { | 321 if (last) { |
| 333 base::TimeDelta encode_time = base::Time::Now() - encode_start_time_; | 322 base::TimeDelta encode_time = base::Time::Now() - encode_start_time_; |
| 334 int encode_time_ms = | 323 int encode_time_ms = |
| 335 static_cast<int>(encode_time.InMilliseconds()); | 324 static_cast<int>(encode_time.InMilliseconds()); |
| 336 packet->set_encode_time_ms(encode_time_ms); | 325 packet->set_encode_time_ms(encode_time_ms); |
| 337 scheduler_.RecordEncodeTime(encode_time); | 326 scheduler_.RecordEncodeTime(encode_time); |
| 338 } | 327 } |
| 339 | 328 |
| 340 network_loop_->PostTask( | 329 network_loop_->PostTask( |
| 341 FROM_HERE, base::Bind(&ScreenRecorder::DoSendVideoPacket, this, packet)); | 330 FROM_HERE, base::Bind(&ScreenRecorder::DoSendVideoPacket, this, |
| 331 base::Passed(packet.Pass()))); |
| 342 } | 332 } |
| 343 | 333 |
| 344 } // namespace remoting | 334 } // namespace remoting |
| OLD | NEW |