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 13 matching lines...) Expand all Loading... |
24 #include "remoting/protocol/message_decoder.h" | 24 #include "remoting/protocol/message_decoder.h" |
25 #include "remoting/protocol/video_stub.h" | 25 #include "remoting/protocol/video_stub.h" |
26 #include "remoting/protocol/util.h" | 26 #include "remoting/protocol/util.h" |
27 | 27 |
28 namespace remoting { | 28 namespace remoting { |
29 | 29 |
30 // Maximum number of frames that can be processed simultaneously. | 30 // Maximum number of frames that can be processed simultaneously. |
31 // TODO(hclam): Move this value to CaptureScheduler. | 31 // TODO(hclam): Move this value to CaptureScheduler. |
32 static const int kMaxPendingCaptures = 2; | 32 static const int kMaxPendingCaptures = 2; |
33 | 33 |
34 // static | 34 VideoScheduler::VideoScheduler( |
35 scoped_refptr<VideoScheduler> VideoScheduler::Create( | |
36 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, | 35 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, |
37 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, | 36 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, |
38 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, | 37 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, |
39 scoped_ptr<media::ScreenCapturer> capturer, | 38 scoped_ptr<media::ScreenCapturer> capturer, |
40 scoped_ptr<VideoEncoder> encoder, | 39 scoped_ptr<VideoEncoder> encoder, |
41 protocol::CursorShapeStub* cursor_stub, | 40 protocol::CursorShapeStub* cursor_stub, |
42 protocol::VideoStub* video_stub) { | 41 protocol::VideoStub* video_stub) |
43 DCHECK(network_task_runner->BelongsToCurrentThread()); | 42 : capture_task_runner_(capture_task_runner), |
44 DCHECK(capturer); | 43 encode_task_runner_(encode_task_runner), |
45 DCHECK(encoder); | 44 network_task_runner_(network_task_runner), |
46 DCHECK(cursor_stub); | 45 capturer_(capturer.Pass()), |
47 DCHECK(video_stub); | 46 encoder_(encoder.Pass()), |
48 | 47 cursor_stub_(cursor_stub), |
49 scoped_refptr<VideoScheduler> scheduler = new VideoScheduler( | 48 video_stub_(video_stub), |
50 capture_task_runner, encode_task_runner, network_task_runner, | 49 pending_captures_(0), |
51 capturer.Pass(), encoder.Pass(), cursor_stub, video_stub); | 50 did_skip_frame_(false), |
52 capture_task_runner->PostTask( | 51 is_paused_(false), |
53 FROM_HERE, base::Bind(&VideoScheduler::StartOnCaptureThread, scheduler)); | 52 sequence_number_(0) { |
54 | 53 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
55 return scheduler; | 54 DCHECK(capturer_); |
| 55 DCHECK(encoder_); |
| 56 DCHECK(cursor_stub_); |
| 57 DCHECK(video_stub_); |
56 } | 58 } |
57 | 59 |
58 // Public methods -------------------------------------------------------------- | 60 // Public methods -------------------------------------------------------------- |
59 | 61 |
60 void VideoScheduler::OnCaptureCompleted( | 62 void VideoScheduler::OnCaptureCompleted( |
61 scoped_refptr<media::ScreenCaptureData> capture_data) { | 63 scoped_refptr<media::ScreenCaptureData> capture_data) { |
62 DCHECK(capture_task_runner_->BelongsToCurrentThread()); | 64 DCHECK(capture_task_runner_->BelongsToCurrentThread()); |
63 | 65 |
64 // Do nothing if the scheduler is being stopped. | 66 // Do nothing if the scheduler is being stopped. |
65 if (!capturer_) | 67 if (!capturer_) |
(...skipping 29 matching lines...) Expand all Loading... |
95 cursor_proto->set_height(cursor_shape->size.height()); | 97 cursor_proto->set_height(cursor_shape->size.height()); |
96 cursor_proto->set_hotspot_x(cursor_shape->hotspot.x()); | 98 cursor_proto->set_hotspot_x(cursor_shape->hotspot.x()); |
97 cursor_proto->set_hotspot_y(cursor_shape->hotspot.y()); | 99 cursor_proto->set_hotspot_y(cursor_shape->hotspot.y()); |
98 cursor_proto->set_data(cursor_shape->data); | 100 cursor_proto->set_data(cursor_shape->data); |
99 | 101 |
100 network_task_runner_->PostTask( | 102 network_task_runner_->PostTask( |
101 FROM_HERE, base::Bind(&VideoScheduler::SendCursorShape, this, | 103 FROM_HERE, base::Bind(&VideoScheduler::SendCursorShape, this, |
102 base::Passed(&cursor_proto))); | 104 base::Passed(&cursor_proto))); |
103 } | 105 } |
104 | 106 |
| 107 void VideoScheduler::Start() { |
| 108 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 109 |
| 110 capture_task_runner_->PostTask( |
| 111 FROM_HERE, base::Bind(&VideoScheduler::StartOnCaptureThread, this)); |
| 112 } |
| 113 |
105 void VideoScheduler::Stop() { | 114 void VideoScheduler::Stop() { |
106 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 115 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
107 | 116 |
108 // Clear stubs to prevent further updates reaching the client. | 117 // Clear stubs to prevent further updates reaching the client. |
109 cursor_stub_ = NULL; | 118 cursor_stub_ = NULL; |
110 video_stub_ = NULL; | 119 video_stub_ = NULL; |
111 | 120 |
112 capture_task_runner_->PostTask(FROM_HERE, | 121 capture_task_runner_->PostTask(FROM_HERE, |
113 base::Bind(&VideoScheduler::StopOnCaptureThread, this)); | 122 base::Bind(&VideoScheduler::StopOnCaptureThread, this)); |
114 } | 123 } |
115 | 124 |
116 void VideoScheduler::Pause(bool pause) { | 125 void VideoScheduler::Pause(bool pause) { |
117 if (!capture_task_runner_->BelongsToCurrentThread()) { | 126 if (!capture_task_runner_->BelongsToCurrentThread()) { |
118 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 127 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
119 capture_task_runner_->PostTask( | 128 capture_task_runner_->PostTask( |
120 FROM_HERE, base::Bind(&VideoScheduler::Pause, this, pause)); | 129 FROM_HERE, base::Bind(&VideoScheduler::Pause, this, pause)); |
121 return; | 130 return; |
122 } | 131 } |
123 | 132 |
124 if (is_paused_ != pause) { | 133 if (is_paused_ != pause) { |
125 is_paused_ = pause; | 134 is_paused_ = pause; |
126 | 135 |
127 // Restart captures if we're resuming and there are none scheduled. | 136 // Restart captures if we're resuming and there are none scheduled. |
128 if (!is_paused_ && !capture_timer_->IsRunning()) | 137 if (!is_paused_ && capture_timer_ && !capture_timer_->IsRunning()) |
129 CaptureNextFrame(); | 138 CaptureNextFrame(); |
130 } | 139 } |
131 } | 140 } |
132 | 141 |
133 void VideoScheduler::UpdateSequenceNumber(int64 sequence_number) { | 142 void VideoScheduler::UpdateSequenceNumber(int64 sequence_number) { |
134 if (!capture_task_runner_->BelongsToCurrentThread()) { | 143 if (!capture_task_runner_->BelongsToCurrentThread()) { |
135 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 144 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
136 capture_task_runner_->PostTask( | 145 capture_task_runner_->PostTask( |
137 FROM_HERE, base::Bind(&VideoScheduler::UpdateSequenceNumber, | 146 FROM_HERE, base::Bind(&VideoScheduler::UpdateSequenceNumber, |
138 this, sequence_number)); | 147 this, sequence_number)); |
139 return; | 148 return; |
140 } | 149 } |
141 | 150 |
142 sequence_number_ = sequence_number; | 151 sequence_number_ = sequence_number; |
143 } | 152 } |
144 | 153 |
145 // Private methods ----------------------------------------------------------- | 154 // Private methods ----------------------------------------------------------- |
146 | 155 |
147 VideoScheduler::VideoScheduler( | |
148 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, | |
149 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, | |
150 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, | |
151 scoped_ptr<media::ScreenCapturer> capturer, | |
152 scoped_ptr<VideoEncoder> encoder, | |
153 protocol::CursorShapeStub* cursor_stub, | |
154 protocol::VideoStub* video_stub) | |
155 : capture_task_runner_(capture_task_runner), | |
156 encode_task_runner_(encode_task_runner), | |
157 network_task_runner_(network_task_runner), | |
158 capturer_(capturer.Pass()), | |
159 encoder_(encoder.Pass()), | |
160 cursor_stub_(cursor_stub), | |
161 video_stub_(video_stub), | |
162 pending_captures_(0), | |
163 did_skip_frame_(false), | |
164 is_paused_(false), | |
165 sequence_number_(0) { | |
166 } | |
167 | |
168 VideoScheduler::~VideoScheduler() { | 156 VideoScheduler::~VideoScheduler() { |
169 } | 157 } |
170 | 158 |
171 // Capturer thread ------------------------------------------------------------- | 159 // Capturer thread ------------------------------------------------------------- |
172 | 160 |
173 void VideoScheduler::StartOnCaptureThread() { | 161 void VideoScheduler::StartOnCaptureThread() { |
174 DCHECK(capture_task_runner_->BelongsToCurrentThread()); | 162 DCHECK(capture_task_runner_->BelongsToCurrentThread()); |
| 163 DCHECK(!capture_timer_); |
175 | 164 |
176 // Start the capturer and let it notify us if cursor shape changes. | 165 // Start the capturer and let it notify us if cursor shape changes. |
177 capturer_->Start(this); | 166 capturer_->Start(this); |
178 | 167 |
179 capture_timer_.reset(new base::OneShotTimer<VideoScheduler>()); | 168 capture_timer_.reset(new base::OneShotTimer<VideoScheduler>()); |
180 | 169 |
181 // Capture first frame immedately. | 170 // Capture first frame immedately. |
182 CaptureNextFrame(); | 171 CaptureNextFrame(); |
183 } | 172 } |
184 | 173 |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 scoped_ptr<media::ScreenCapturer> capturer) { | 312 scoped_ptr<media::ScreenCapturer> capturer) { |
324 DCHECK(encode_task_runner_->BelongsToCurrentThread()); | 313 DCHECK(encode_task_runner_->BelongsToCurrentThread()); |
325 | 314 |
326 // This is posted by StopOnCaptureThread, so we know that by the time we | 315 // This is posted by StopOnCaptureThread, so we know that by the time we |
327 // process it there are no more encode tasks queued. Pass |capturer| for | 316 // process it there are no more encode tasks queued. Pass |capturer| for |
328 // deletion on the capture thread. | 317 // deletion on the capture thread. |
329 capture_task_runner_->DeleteSoon(FROM_HERE, capturer.release()); | 318 capture_task_runner_->DeleteSoon(FROM_HERE, capturer.release()); |
330 } | 319 } |
331 | 320 |
332 } // namespace remoting | 321 } // namespace remoting |
OLD | NEW |