| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/video_scheduler.h" | 5 #include "remoting/host/video_scheduler.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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 network_task_runner_(network_task_runner), | 57 network_task_runner_(network_task_runner), |
| 58 capturer_(capturer.Pass()), | 58 capturer_(capturer.Pass()), |
| 59 mouse_cursor_monitor_(mouse_cursor_monitor.Pass()), | 59 mouse_cursor_monitor_(mouse_cursor_monitor.Pass()), |
| 60 encoder_(encoder.Pass()), | 60 encoder_(encoder.Pass()), |
| 61 cursor_stub_(cursor_stub), | 61 cursor_stub_(cursor_stub), |
| 62 video_stub_(video_stub), | 62 video_stub_(video_stub), |
| 63 pending_frames_(0), | 63 pending_frames_(0), |
| 64 capture_pending_(false), | 64 capture_pending_(false), |
| 65 did_skip_frame_(false), | 65 did_skip_frame_(false), |
| 66 is_paused_(false), | 66 is_paused_(false), |
| 67 sequence_number_(0) { | 67 latest_event_timestamp_(0) { |
| 68 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 68 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 69 DCHECK(capturer_); | 69 DCHECK(capturer_); |
| 70 DCHECK(mouse_cursor_monitor_); | 70 DCHECK(mouse_cursor_monitor_); |
| 71 DCHECK(encoder_); | 71 DCHECK(encoder_); |
| 72 DCHECK(cursor_stub_); | 72 DCHECK(cursor_stub_); |
| 73 DCHECK(video_stub_); | 73 DCHECK(video_stub_); |
| 74 } | 74 } |
| 75 | 75 |
| 76 // Public methods -------------------------------------------------------------- | 76 // Public methods -------------------------------------------------------------- |
| 77 | 77 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 89 if (owned_frame) { | 89 if (owned_frame) { |
| 90 scheduler_.RecordCaptureTime( | 90 scheduler_.RecordCaptureTime( |
| 91 base::TimeDelta::FromMilliseconds(owned_frame->capture_time_ms())); | 91 base::TimeDelta::FromMilliseconds(owned_frame->capture_time_ms())); |
| 92 } | 92 } |
| 93 | 93 |
| 94 // Even when |frame| is NULL we still need to post it to the encode thread | 94 // Even when |frame| is NULL we still need to post it to the encode thread |
| 95 // to make sure frames are freed in the same order they are received and | 95 // to make sure frames are freed in the same order they are received and |
| 96 // that we don't start capturing frame n+2 before frame n is freed. | 96 // that we don't start capturing frame n+2 before frame n is freed. |
| 97 encode_task_runner_->PostTask( | 97 encode_task_runner_->PostTask( |
| 98 FROM_HERE, base::Bind(&VideoScheduler::EncodeFrame, this, | 98 FROM_HERE, base::Bind(&VideoScheduler::EncodeFrame, this, |
| 99 base::Passed(&owned_frame), sequence_number_, | 99 base::Passed(&owned_frame), latest_event_timestamp_, |
| 100 base::TimeTicks::Now())); | 100 base::TimeTicks::Now())); |
| 101 | 101 |
| 102 // If a frame was skipped, try to capture it again. | 102 // If a frame was skipped, try to capture it again. |
| 103 if (did_skip_frame_) { | 103 if (did_skip_frame_) { |
| 104 capture_task_runner_->PostTask( | 104 capture_task_runner_->PostTask( |
| 105 FROM_HERE, base::Bind(&VideoScheduler::CaptureNextFrame, this)); | 105 FROM_HERE, base::Bind(&VideoScheduler::CaptureNextFrame, this)); |
| 106 } | 106 } |
| 107 } | 107 } |
| 108 | 108 |
| 109 void VideoScheduler::OnMouseCursor(webrtc::MouseCursor* cursor) { | 109 void VideoScheduler::OnMouseCursor(webrtc::MouseCursor* cursor) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 | 174 |
| 175 if (is_paused_ != pause) { | 175 if (is_paused_ != pause) { |
| 176 is_paused_ = pause; | 176 is_paused_ = pause; |
| 177 | 177 |
| 178 // Restart captures if we're resuming and there are none scheduled. | 178 // Restart captures if we're resuming and there are none scheduled. |
| 179 if (!is_paused_ && capture_timer_ && !capture_timer_->IsRunning()) | 179 if (!is_paused_ && capture_timer_ && !capture_timer_->IsRunning()) |
| 180 CaptureNextFrame(); | 180 CaptureNextFrame(); |
| 181 } | 181 } |
| 182 } | 182 } |
| 183 | 183 |
| 184 void VideoScheduler::UpdateSequenceNumber(int64 sequence_number) { | 184 void VideoScheduler::SetLatestEventTimestamp(int64 latest_event_timestamp) { |
| 185 if (!capture_task_runner_->BelongsToCurrentThread()) { | 185 if (!capture_task_runner_->BelongsToCurrentThread()) { |
| 186 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 186 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 187 capture_task_runner_->PostTask( | 187 capture_task_runner_->PostTask( |
| 188 FROM_HERE, base::Bind(&VideoScheduler::UpdateSequenceNumber, | 188 FROM_HERE, base::Bind(&VideoScheduler::SetLatestEventTimestamp, |
| 189 this, sequence_number)); | 189 this, latest_event_timestamp)); |
| 190 return; | 190 return; |
| 191 } | 191 } |
| 192 | 192 |
| 193 sequence_number_ = sequence_number; | 193 latest_event_timestamp_ = latest_event_timestamp; |
| 194 } | 194 } |
| 195 | 195 |
| 196 void VideoScheduler::SetLosslessEncode(bool want_lossless) { | 196 void VideoScheduler::SetLosslessEncode(bool want_lossless) { |
| 197 if (!encode_task_runner_->BelongsToCurrentThread()) { | 197 if (!encode_task_runner_->BelongsToCurrentThread()) { |
| 198 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 198 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 199 encode_task_runner_->PostTask( | 199 encode_task_runner_->PostTask( |
| 200 FROM_HERE, base::Bind(&VideoScheduler::SetLosslessEncode, | 200 FROM_HERE, base::Bind(&VideoScheduler::SetLosslessEncode, |
| 201 this, want_lossless)); | 201 this, want_lossless)); |
| 202 return; | 202 return; |
| 203 } | 203 } |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 if (!cursor_stub_) | 362 if (!cursor_stub_) |
| 363 return; | 363 return; |
| 364 | 364 |
| 365 cursor_stub_->SetCursorShape(*cursor_shape); | 365 cursor_stub_->SetCursorShape(*cursor_shape); |
| 366 } | 366 } |
| 367 | 367 |
| 368 // Encoder thread -------------------------------------------------------------- | 368 // Encoder thread -------------------------------------------------------------- |
| 369 | 369 |
| 370 void VideoScheduler::EncodeFrame( | 370 void VideoScheduler::EncodeFrame( |
| 371 scoped_ptr<webrtc::DesktopFrame> frame, | 371 scoped_ptr<webrtc::DesktopFrame> frame, |
| 372 int64 sequence_number, | 372 int64 latest_event_timestamp, |
| 373 base::TimeTicks timestamp) { | 373 base::TimeTicks timestamp) { |
| 374 DCHECK(encode_task_runner_->BelongsToCurrentThread()); | 374 DCHECK(encode_task_runner_->BelongsToCurrentThread()); |
| 375 | 375 |
| 376 // If there is nothing to encode then send an empty packet. | 376 // If there is nothing to encode then send an empty packet. |
| 377 if (!frame || frame->updated_region().is_empty()) { | 377 if (!frame || frame->updated_region().is_empty()) { |
| 378 capture_task_runner_->DeleteSoon(FROM_HERE, frame.release()); | 378 capture_task_runner_->DeleteSoon(FROM_HERE, frame.release()); |
| 379 scoped_ptr<VideoPacket> packet(new VideoPacket()); | 379 scoped_ptr<VideoPacket> packet(new VideoPacket()); |
| 380 packet->set_client_sequence_number(sequence_number); | 380 packet->set_latest_event_timestamp(latest_event_timestamp); |
| 381 network_task_runner_->PostTask( | 381 network_task_runner_->PostTask( |
| 382 FROM_HERE, | 382 FROM_HERE, |
| 383 base::Bind( | 383 base::Bind( |
| 384 &VideoScheduler::SendVideoPacket, this, base::Passed(&packet))); | 384 &VideoScheduler::SendVideoPacket, this, base::Passed(&packet))); |
| 385 return; | 385 return; |
| 386 } | 386 } |
| 387 | 387 |
| 388 scoped_ptr<VideoPacket> packet = encoder_->Encode(*frame); | 388 scoped_ptr<VideoPacket> packet = encoder_->Encode(*frame); |
| 389 packet->set_client_sequence_number(sequence_number); | 389 packet->set_latest_event_timestamp(latest_event_timestamp); |
| 390 | 390 |
| 391 if (g_enable_timestamps) { | 391 if (g_enable_timestamps) { |
| 392 packet->set_timestamp(timestamp.ToInternalValue()); | 392 packet->set_timestamp(timestamp.ToInternalValue()); |
| 393 } | 393 } |
| 394 | 394 |
| 395 // Destroy the frame before sending |packet| because SendVideoPacket() may | 395 // Destroy the frame before sending |packet| because SendVideoPacket() may |
| 396 // trigger another frame to be captured, and the screen capturer expects the | 396 // trigger another frame to be captured, and the screen capturer expects the |
| 397 // old frame to be freed by then. | 397 // old frame to be freed by then. |
| 398 frame.reset(); | 398 frame.reset(); |
| 399 | 399 |
| 400 scheduler_.RecordEncodeTime( | 400 scheduler_.RecordEncodeTime( |
| 401 base::TimeDelta::FromMilliseconds(packet->encode_time_ms())); | 401 base::TimeDelta::FromMilliseconds(packet->encode_time_ms())); |
| 402 network_task_runner_->PostTask( | 402 network_task_runner_->PostTask( |
| 403 FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this, | 403 FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this, |
| 404 base::Passed(&packet))); | 404 base::Passed(&packet))); |
| 405 } | 405 } |
| 406 | 406 |
| 407 } // namespace remoting | 407 } // namespace remoting |
| OLD | NEW |