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 18 matching lines...) Expand all Loading... |
29 // Maximum number of frames that can be processed simultaneously. | 29 // Maximum number of frames that can be processed simultaneously. |
30 // TODO(hclam): Move this value to CaptureScheduler. | 30 // TODO(hclam): Move this value to CaptureScheduler. |
31 static const int kMaxPendingFrames = 2; | 31 static const int kMaxPendingFrames = 2; |
32 | 32 |
33 // Interval between empty keep-alive frames. These frames are sent only | 33 // Interval between empty keep-alive frames. These frames are sent only |
34 // when there are no real video frames being sent. To prevent PseudoTCP from | 34 // when there are no real video frames being sent. To prevent PseudoTCP from |
35 // resetting congestion window this value must be smaller than the minimum | 35 // resetting congestion window this value must be smaller than the minimum |
36 // RTO used in PseudoTCP, which is 250ms. | 36 // RTO used in PseudoTCP, which is 250ms. |
37 static const int kKeepAlivePacketIntervalMs = 200; | 37 static const int kKeepAlivePacketIntervalMs = 200; |
38 | 38 |
| 39 static bool g_enable_timestamps = false; |
| 40 |
| 41 // static |
| 42 void VideoScheduler::EnableTimestampsForTests() { |
| 43 g_enable_timestamps = true; |
| 44 } |
| 45 |
39 VideoScheduler::VideoScheduler( | 46 VideoScheduler::VideoScheduler( |
40 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, | 47 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, |
41 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, | 48 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, |
42 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, | 49 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, |
43 scoped_ptr<webrtc::ScreenCapturer> capturer, | 50 scoped_ptr<webrtc::ScreenCapturer> capturer, |
44 scoped_ptr<VideoEncoder> encoder, | 51 scoped_ptr<VideoEncoder> encoder, |
45 protocol::CursorShapeStub* cursor_stub, | 52 protocol::CursorShapeStub* cursor_stub, |
46 protocol::VideoStub* video_stub) | 53 protocol::VideoStub* video_stub) |
47 : capture_task_runner_(capture_task_runner), | 54 : capture_task_runner_(capture_task_runner), |
48 encode_task_runner_(encode_task_runner), | 55 encode_task_runner_(encode_task_runner), |
(...skipping 30 matching lines...) Expand all Loading... |
79 if (owned_frame) { | 86 if (owned_frame) { |
80 scheduler_.RecordCaptureTime( | 87 scheduler_.RecordCaptureTime( |
81 base::TimeDelta::FromMilliseconds(owned_frame->capture_time_ms())); | 88 base::TimeDelta::FromMilliseconds(owned_frame->capture_time_ms())); |
82 } | 89 } |
83 | 90 |
84 // Even when |frame| is NULL we still need to post it to the encode thread | 91 // Even when |frame| is NULL we still need to post it to the encode thread |
85 // to make sure frames are freed in the same order they are received and | 92 // to make sure frames are freed in the same order they are received and |
86 // that we don't start capturing frame n+2 before frame n is freed. | 93 // that we don't start capturing frame n+2 before frame n is freed. |
87 encode_task_runner_->PostTask( | 94 encode_task_runner_->PostTask( |
88 FROM_HERE, base::Bind(&VideoScheduler::EncodeFrame, this, | 95 FROM_HERE, base::Bind(&VideoScheduler::EncodeFrame, this, |
89 base::Passed(&owned_frame), sequence_number_)); | 96 base::Passed(&owned_frame), sequence_number_, |
| 97 base::TimeTicks::Now())); |
90 | 98 |
91 // If a frame was skipped, try to capture it again. | 99 // If a frame was skipped, try to capture it again. |
92 if (did_skip_frame_) { | 100 if (did_skip_frame_) { |
93 capture_task_runner_->PostTask( | 101 capture_task_runner_->PostTask( |
94 FROM_HERE, base::Bind(&VideoScheduler::CaptureNextFrame, this)); | 102 FROM_HERE, base::Bind(&VideoScheduler::CaptureNextFrame, this)); |
95 } | 103 } |
96 } | 104 } |
97 | 105 |
98 void VideoScheduler::OnCursorShapeChanged( | 106 void VideoScheduler::OnCursorShapeChanged( |
99 webrtc::MouseCursorShape* cursor_shape) { | 107 webrtc::MouseCursorShape* cursor_shape) { |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 if (!cursor_stub_) | 338 if (!cursor_stub_) |
331 return; | 339 return; |
332 | 340 |
333 cursor_stub_->SetCursorShape(*cursor_shape); | 341 cursor_stub_->SetCursorShape(*cursor_shape); |
334 } | 342 } |
335 | 343 |
336 // Encoder thread -------------------------------------------------------------- | 344 // Encoder thread -------------------------------------------------------------- |
337 | 345 |
338 void VideoScheduler::EncodeFrame( | 346 void VideoScheduler::EncodeFrame( |
339 scoped_ptr<webrtc::DesktopFrame> frame, | 347 scoped_ptr<webrtc::DesktopFrame> frame, |
340 int64 sequence_number) { | 348 int64 sequence_number, |
| 349 base::TimeTicks timestamp) { |
341 DCHECK(encode_task_runner_->BelongsToCurrentThread()); | 350 DCHECK(encode_task_runner_->BelongsToCurrentThread()); |
342 | 351 |
343 // Drop the frame if there were no changes. | 352 // Drop the frame if there were no changes. |
344 if (!frame || frame->updated_region().is_empty()) { | 353 if (!frame || frame->updated_region().is_empty()) { |
345 capture_task_runner_->DeleteSoon(FROM_HERE, frame.release()); | 354 capture_task_runner_->DeleteSoon(FROM_HERE, frame.release()); |
346 capture_task_runner_->PostTask( | 355 capture_task_runner_->PostTask( |
347 FROM_HERE, base::Bind(&VideoScheduler::FrameCaptureCompleted, this)); | 356 FROM_HERE, base::Bind(&VideoScheduler::FrameCaptureCompleted, this)); |
348 return; | 357 return; |
349 } | 358 } |
350 | 359 |
351 scoped_ptr<VideoPacket> packet = encoder_->Encode(*frame); | 360 scoped_ptr<VideoPacket> packet = encoder_->Encode(*frame); |
352 packet->set_client_sequence_number(sequence_number); | 361 packet->set_client_sequence_number(sequence_number); |
353 | 362 |
| 363 if (g_enable_timestamps) { |
| 364 packet->set_timestamp(timestamp.ToInternalValue()); |
| 365 } |
| 366 |
354 // Destroy the frame before sending |packet| because SendVideoPacket() may | 367 // Destroy the frame before sending |packet| because SendVideoPacket() may |
355 // trigger another frame to be captured, and the screen capturer expects the | 368 // trigger another frame to be captured, and the screen capturer expects the |
356 // old frame to be freed by then. | 369 // old frame to be freed by then. |
357 frame.reset(); | 370 frame.reset(); |
358 | 371 |
359 scheduler_.RecordEncodeTime( | 372 scheduler_.RecordEncodeTime( |
360 base::TimeDelta::FromMilliseconds(packet->encode_time_ms())); | 373 base::TimeDelta::FromMilliseconds(packet->encode_time_ms())); |
361 network_task_runner_->PostTask( | 374 network_task_runner_->PostTask( |
362 FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this, | 375 FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this, |
363 base::Passed(&packet))); | 376 base::Passed(&packet))); |
364 } | 377 } |
365 | 378 |
366 } // namespace remoting | 379 } // namespace remoting |
OLD | NEW |