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 last_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), last_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::SetLastEventTimestamp(int64 last_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::SetLastEventTimestamp, |
189 this, sequence_number)); | 189 this, last_event_timestamp)); |
190 return; | 190 return; |
191 } | 191 } |
192 | 192 |
193 sequence_number_ = sequence_number; | 193 last_event_timestamp_ = last_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 last_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_last_event_timestamp(last_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_last_event_timestamp(last_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 |