Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(274)

Side by Side Diff: remoting/host/video_scheduler.cc

Issue 11778049: Making DesktopEnvironment a factory class used by ClientSession to create audio/video capturers and… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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 // static
35 scoped_refptr<VideoScheduler> VideoScheduler::Create( 35 scoped_refptr<VideoScheduler> VideoScheduler::Create(
36 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, 36 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
37 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, 37 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
38 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, 38 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
39 VideoFrameCapturer* capturer, 39 scoped_ptr<VideoFrameCapturer> capturer,
40 scoped_ptr<VideoEncoder> encoder, 40 scoped_ptr<VideoEncoder> encoder,
41 protocol::CursorShapeStub* cursor_stub, 41 protocol::CursorShapeStub* cursor_stub,
42 protocol::VideoStub* video_stub) { 42 protocol::VideoStub* video_stub) {
43 DCHECK(network_task_runner->BelongsToCurrentThread()); 43 DCHECK(network_task_runner->BelongsToCurrentThread());
44 DCHECK(capturer); 44 DCHECK(capturer);
45 DCHECK(encoder); 45 DCHECK(encoder);
46 DCHECK(cursor_stub); 46 DCHECK(cursor_stub);
47 DCHECK(video_stub); 47 DCHECK(video_stub);
48 48
49 scoped_refptr<VideoScheduler> scheduler = new VideoScheduler( 49 scoped_refptr<VideoScheduler> scheduler = new VideoScheduler(
50 capture_task_runner, encode_task_runner, network_task_runner, 50 capture_task_runner, encode_task_runner, network_task_runner,
51 capturer, encoder.Pass(), cursor_stub, video_stub); 51 capturer.Pass(), encoder.Pass(), cursor_stub, video_stub);
52 capture_task_runner->PostTask( 52 capture_task_runner->PostTask(
53 FROM_HERE, base::Bind(&VideoScheduler::StartOnCaptureThread, scheduler)); 53 FROM_HERE, base::Bind(&VideoScheduler::StartOnCaptureThread, scheduler));
54 54
55 return scheduler; 55 return scheduler;
56 } 56 }
57 57
58 // Public methods -------------------------------------------------------------- 58 // Public methods --------------------------------------------------------------
59 59
60 void VideoScheduler::OnCaptureCompleted( 60 void VideoScheduler::OnCaptureCompleted(
61 scoped_refptr<CaptureData> capture_data) { 61 scoped_refptr<CaptureData> capture_data) {
(...skipping 25 matching lines...) Expand all
87 cursor_proto->set_height(cursor_shape->size.height()); 87 cursor_proto->set_height(cursor_shape->size.height());
88 cursor_proto->set_hotspot_x(cursor_shape->hotspot.x()); 88 cursor_proto->set_hotspot_x(cursor_shape->hotspot.x());
89 cursor_proto->set_hotspot_y(cursor_shape->hotspot.y()); 89 cursor_proto->set_hotspot_y(cursor_shape->hotspot.y());
90 cursor_proto->set_data(cursor_shape->data); 90 cursor_proto->set_data(cursor_shape->data);
91 91
92 network_task_runner_->PostTask( 92 network_task_runner_->PostTask(
93 FROM_HERE, base::Bind(&VideoScheduler::SendCursorShape, this, 93 FROM_HERE, base::Bind(&VideoScheduler::SendCursorShape, this,
94 base::Passed(&cursor_proto))); 94 base::Passed(&cursor_proto)));
95 } 95 }
96 96
97 void VideoScheduler::Stop(const base::Closure& done_task) { 97 void VideoScheduler::Stop() {
98 DCHECK(network_task_runner_->BelongsToCurrentThread()); 98 DCHECK(network_task_runner_->BelongsToCurrentThread());
99 DCHECK(!done_task.is_null());
100 99
101 // Clear stubs to prevent further updates reaching the client. 100 // Clear stubs to prevent further updates reaching the client.
102 cursor_stub_ = NULL; 101 cursor_stub_ = NULL;
103 video_stub_ = NULL; 102 video_stub_ = NULL;
104 103
105 capture_task_runner_->PostTask(FROM_HERE, 104 capture_task_runner_->PostTask(FROM_HERE,
106 base::Bind(&VideoScheduler::StopOnCaptureThread, this, done_task)); 105 base::Bind(&VideoScheduler::StopOnCaptureThread, this));
107 } 106 }
108 107
109 void VideoScheduler::Pause(bool pause) { 108 void VideoScheduler::Pause(bool pause) {
110 if (!capture_task_runner_->BelongsToCurrentThread()) { 109 if (!capture_task_runner_->BelongsToCurrentThread()) {
111 DCHECK(network_task_runner_->BelongsToCurrentThread()); 110 DCHECK(network_task_runner_->BelongsToCurrentThread());
112 capture_task_runner_->PostTask( 111 capture_task_runner_->PostTask(
113 FROM_HERE, base::Bind(&VideoScheduler::Pause, this, pause)); 112 FROM_HERE, base::Bind(&VideoScheduler::Pause, this, pause));
114 return; 113 return;
115 } 114 }
116 115
(...skipping 17 matching lines...) Expand all
134 133
135 sequence_number_ = sequence_number; 134 sequence_number_ = sequence_number;
136 } 135 }
137 136
138 // Private methods ----------------------------------------------------------- 137 // Private methods -----------------------------------------------------------
139 138
140 VideoScheduler::VideoScheduler( 139 VideoScheduler::VideoScheduler(
141 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, 140 scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
142 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, 141 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
143 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, 142 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
144 VideoFrameCapturer* capturer, 143 scoped_ptr<VideoFrameCapturer> capturer,
145 scoped_ptr<VideoEncoder> encoder, 144 scoped_ptr<VideoEncoder> encoder,
146 protocol::CursorShapeStub* cursor_stub, 145 protocol::CursorShapeStub* cursor_stub,
147 protocol::VideoStub* video_stub) 146 protocol::VideoStub* video_stub)
148 : capture_task_runner_(capture_task_runner), 147 : capture_task_runner_(capture_task_runner),
149 encode_task_runner_(encode_task_runner), 148 encode_task_runner_(encode_task_runner),
150 network_task_runner_(network_task_runner), 149 network_task_runner_(network_task_runner),
151 capturer_(capturer), 150 capturer_(capturer.Pass()),
152 encoder_(encoder.Pass()), 151 encoder_(encoder.Pass()),
153 cursor_stub_(cursor_stub), 152 cursor_stub_(cursor_stub),
154 video_stub_(video_stub), 153 video_stub_(video_stub),
155 pending_captures_(0), 154 pending_captures_(0),
156 did_skip_frame_(false), 155 did_skip_frame_(false),
157 is_paused_(false), 156 is_paused_(false),
158 sequence_number_(0) { 157 sequence_number_(0),
158 size_most_recent_(SkISize::Make(0, 0)) {
159 } 159 }
160 160
161 VideoScheduler::~VideoScheduler() { 161 VideoScheduler::~VideoScheduler() {
162 } 162 }
163 163
164 // Capturer thread ------------------------------------------------------------- 164 // Capturer thread -------------------------------------------------------------
165 165
166 void VideoScheduler::StartOnCaptureThread() { 166 void VideoScheduler::StartOnCaptureThread() {
167 DCHECK(capture_task_runner_->BelongsToCurrentThread()); 167 DCHECK(capture_task_runner_->BelongsToCurrentThread());
168 168
169 // Start the capturer and let it notify us of cursor shape changes. 169 // Start the capturer and let it notify us of cursor shape changes.
170 capturer_->Start(this); 170 capturer_->Start(this);
171 171
172 capture_timer_.reset(new base::OneShotTimer<VideoScheduler>()); 172 capture_timer_.reset(new base::OneShotTimer<VideoScheduler>());
173 173
174 // Capture first frame immedately. 174 // Capture first frame immedately.
175 CaptureNextFrame(); 175 CaptureNextFrame();
176 } 176 }
177 177
178 void VideoScheduler::StopOnCaptureThread(const base::Closure& done_task) { 178 void VideoScheduler::StopOnCaptureThread() {
179 DCHECK(capture_task_runner_->BelongsToCurrentThread()); 179 DCHECK(capture_task_runner_->BelongsToCurrentThread());
180 180
181 // Stop |capturer_| and clear it to prevent pending tasks from using it. 181 // Stop |capturer_| and clear it to prevent pending tasks from using it.
182 capturer_->Stop(); 182 capturer_->Stop();
183 capturer_ = NULL;
184 183
185 // |capture_timer_| must be destroyed on the thread on which it is used. 184 // |capture_timer_| must be destroyed on the thread on which it is used.
186 capture_timer_.reset(); 185 capture_timer_.reset();
187 186
188 // Ensure that the encode thread is no longer processing capture data, 187 // Schedule deletion of |capturer_| once the encode thread is no longer
189 // otherwise tearing down |capturer_| will crash it. See crbug.com/163641. 188 // processing capture data. See http://crbug.com/163641. This also clears
189 // |capturer_| pointer to prevent pending tasks from using it.
190 // TODO(wez): Make it safe to tear down capturer while buffers remain, and 190 // TODO(wez): Make it safe to tear down capturer while buffers remain, and
191 // remove this work-around. 191 // remove this work-around.
192 encode_task_runner_->PostTask(FROM_HERE, 192 encode_task_runner_->PostTask(
193 base::Bind(&VideoScheduler::StopOnEncodeThread, this, done_task)); 193 FROM_HERE, base::Bind(&VideoScheduler::StopOnEncodeThread, this,
194 base::Passed(&capturer_)));
194 } 195 }
195 196
196 void VideoScheduler::ScheduleNextCapture() { 197 void VideoScheduler::ScheduleNextCapture() {
197 DCHECK(capture_task_runner_->BelongsToCurrentThread()); 198 DCHECK(capture_task_runner_->BelongsToCurrentThread());
198 199
199 capture_timer_->Start(FROM_HERE, 200 capture_timer_->Start(FROM_HERE,
200 scheduler_.NextCaptureDelay(), 201 scheduler_.NextCaptureDelay(),
201 this, 202 this,
202 &VideoScheduler::CaptureNextFrame); 203 &VideoScheduler::CaptureNextFrame);
203 } 204 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 void VideoScheduler::SendVideoPacket(scoped_ptr<VideoPacket> packet) { 249 void VideoScheduler::SendVideoPacket(scoped_ptr<VideoPacket> packet) {
249 DCHECK(network_task_runner_->BelongsToCurrentThread()); 250 DCHECK(network_task_runner_->BelongsToCurrentThread());
250 251
251 if (!video_stub_) 252 if (!video_stub_)
252 return; 253 return;
253 254
254 base::Closure callback; 255 base::Closure callback;
255 if ((packet->flags() & VideoPacket::LAST_PARTITION) != 0) 256 if ((packet->flags() & VideoPacket::LAST_PARTITION) != 0)
256 callback = base::Bind(&VideoScheduler::VideoFrameSentCallback, this); 257 callback = base::Bind(&VideoScheduler::VideoFrameSentCallback, this);
257 258
259 // Update saved screen size.
260 if (packet->format().has_screen_width() &&
261 packet->format().has_screen_height()) {
262 size_most_recent_ = SkISize::Make(packet->format().screen_width(),
263 packet->format().screen_height());
264 }
265
258 video_stub_->ProcessVideoPacket(packet.Pass(), callback); 266 video_stub_->ProcessVideoPacket(packet.Pass(), callback);
259 } 267 }
260 268
261 void VideoScheduler::VideoFrameSentCallback() { 269 void VideoScheduler::VideoFrameSentCallback() {
262 DCHECK(network_task_runner_->BelongsToCurrentThread()); 270 DCHECK(network_task_runner_->BelongsToCurrentThread());
263 271
264 if (!video_stub_) 272 if (!video_stub_)
265 return; 273 return;
266 274
267 capture_task_runner_->PostTask( 275 capture_task_runner_->PostTask(
268 FROM_HERE, base::Bind(&VideoScheduler::FrameCaptureCompleted, this)); 276 FROM_HERE, base::Bind(&VideoScheduler::FrameCaptureCompleted, this));
269 } 277 }
270 278
271 void VideoScheduler::SendCursorShape( 279 void VideoScheduler::SendCursorShape(
272 scoped_ptr<protocol::CursorShapeInfo> cursor_shape) { 280 scoped_ptr<protocol::CursorShapeInfo> cursor_shape) {
273 DCHECK(network_task_runner_->BelongsToCurrentThread()); 281 DCHECK(network_task_runner_->BelongsToCurrentThread());
274 282
275 if (!cursor_stub_) 283 if (!cursor_stub_)
276 return; 284 return;
277 285
278 cursor_stub_->SetCursorShape(*cursor_shape); 286 cursor_stub_->SetCursorShape(*cursor_shape);
279 } 287 }
280 288
289 void VideoScheduler::StopOnNetworkThread(
290 scoped_ptr<VideoFrameCapturer> capturer) {
291 DCHECK(network_task_runner_->BelongsToCurrentThread());
292
293 // This is posted by StopOnEncodeThread meaning that both capture and encode
294 // threads are stopped now and it is safe to delete |capturer|.
295 }
296
281 // Encoder thread -------------------------------------------------------------- 297 // Encoder thread --------------------------------------------------------------
282 298
283 void VideoScheduler::EncodeFrame( 299 void VideoScheduler::EncodeFrame(
284 scoped_refptr<CaptureData> capture_data) { 300 scoped_refptr<CaptureData> capture_data) {
285 DCHECK(encode_task_runner_->BelongsToCurrentThread()); 301 DCHECK(encode_task_runner_->BelongsToCurrentThread());
286 302
287 // If there is nothing to encode then send an empty keep-alive packet. 303 // If there is nothing to encode then send an empty keep-alive packet.
288 if (!capture_data || capture_data->dirty_region().isEmpty()) { 304 if (!capture_data || capture_data->dirty_region().isEmpty()) {
289 scoped_ptr<VideoPacket> packet(new VideoPacket()); 305 scoped_ptr<VideoPacket> packet(new VideoPacket());
290 packet->set_flags(VideoPacket::LAST_PARTITION); 306 packet->set_flags(VideoPacket::LAST_PARTITION);
(...skipping 16 matching lines...) Expand all
307 if (last) { 323 if (last) {
308 scheduler_.RecordEncodeTime( 324 scheduler_.RecordEncodeTime(
309 base::TimeDelta::FromMilliseconds(packet->encode_time_ms())); 325 base::TimeDelta::FromMilliseconds(packet->encode_time_ms()));
310 } 326 }
311 327
312 network_task_runner_->PostTask( 328 network_task_runner_->PostTask(
313 FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this, 329 FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this,
314 base::Passed(&packet))); 330 base::Passed(&packet)));
315 } 331 }
316 332
317 void VideoScheduler::StopOnEncodeThread(const base::Closure& done_task) { 333 void VideoScheduler::StopOnEncodeThread(
334 scoped_ptr<VideoFrameCapturer> capturer) {
318 DCHECK(encode_task_runner_->BelongsToCurrentThread()); 335 DCHECK(encode_task_runner_->BelongsToCurrentThread());
319 336
320 // This is posted by StopOnCaptureThread, so we know that by the time we 337 // This is posted by StopOnCaptureThread, so we know that by the time we
321 // process it there are no more encode tasks queued. 338 // process it there are no more encode tasks queued. Schedule deletion of
322 network_task_runner_->PostTask(FROM_HERE, done_task); 339 // |capturer_| on the same thread it was created on.
Wez 2013/01/11 02:23:41 nit: Suggest "Pass |capturer_| for deletion on the
alexeypa (please no reviews) 2013/01/11 19:59:46 Done.
340 network_task_runner_->PostTask(
341 FROM_HERE, base::Bind(&VideoScheduler::StopOnNetworkThread, this,
342 base::Passed(&capturer)));
323 } 343 }
324 344
325 } // namespace remoting 345 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698