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

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
« no previous file with comments | « remoting/host/video_scheduler.h ('k') | remoting/host/video_scheduler_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
159 } 158 }
160 159
161 VideoScheduler::~VideoScheduler() { 160 VideoScheduler::~VideoScheduler() {
162 } 161 }
163 162
164 // Capturer thread ------------------------------------------------------------- 163 // Capturer thread -------------------------------------------------------------
165 164
166 void VideoScheduler::StartOnCaptureThread() { 165 void VideoScheduler::StartOnCaptureThread() {
167 DCHECK(capture_task_runner_->BelongsToCurrentThread()); 166 DCHECK(capture_task_runner_->BelongsToCurrentThread());
168 167
169 // Start the capturer and let it notify us of cursor shape changes. 168 // Start the capturer and let it notify us of cursor shape changes.
170 capturer_->Start(this); 169 capturer_->Start(this);
171 170
172 capture_timer_.reset(new base::OneShotTimer<VideoScheduler>()); 171 capture_timer_.reset(new base::OneShotTimer<VideoScheduler>());
173 172
174 // Capture first frame immedately. 173 // Capture first frame immedately.
175 CaptureNextFrame(); 174 CaptureNextFrame();
176 } 175 }
177 176
178 void VideoScheduler::StopOnCaptureThread(const base::Closure& done_task) { 177 void VideoScheduler::StopOnCaptureThread() {
179 DCHECK(capture_task_runner_->BelongsToCurrentThread()); 178 DCHECK(capture_task_runner_->BelongsToCurrentThread());
180 179
181 // Stop |capturer_| and clear it to prevent pending tasks from using it. 180 // Stop |capturer_| and clear it to prevent pending tasks from using it.
182 capturer_->Stop(); 181 capturer_->Stop();
183 capturer_ = NULL;
184 182
185 // |capture_timer_| must be destroyed on the thread on which it is used. 183 // |capture_timer_| must be destroyed on the thread on which it is used.
186 capture_timer_.reset(); 184 capture_timer_.reset();
187 185
188 // Ensure that the encode thread is no longer processing capture data, 186 // Schedule deletion of |capturer_| once the encode thread is no longer
189 // otherwise tearing down |capturer_| will crash it. See crbug.com/163641. 187 // processing capture data. See http://crbug.com/163641. This also clears
188 // |capturer_| pointer to prevent pending tasks from using it.
190 // TODO(wez): Make it safe to tear down capturer while buffers remain, and 189 // TODO(wez): Make it safe to tear down capturer while buffers remain, and
191 // remove this work-around. 190 // remove this work-around.
192 encode_task_runner_->PostTask(FROM_HERE, 191 encode_task_runner_->PostTask(
193 base::Bind(&VideoScheduler::StopOnEncodeThread, this, done_task)); 192 FROM_HERE, base::Bind(&VideoScheduler::StopOnEncodeThread, this,
193 base::Passed(&capturer_)));
194 } 194 }
195 195
196 void VideoScheduler::ScheduleNextCapture() { 196 void VideoScheduler::ScheduleNextCapture() {
197 DCHECK(capture_task_runner_->BelongsToCurrentThread()); 197 DCHECK(capture_task_runner_->BelongsToCurrentThread());
198 198
199 capture_timer_->Start(FROM_HERE, 199 capture_timer_->Start(FROM_HERE,
200 scheduler_.NextCaptureDelay(), 200 scheduler_.NextCaptureDelay(),
201 this, 201 this,
202 &VideoScheduler::CaptureNextFrame); 202 &VideoScheduler::CaptureNextFrame);
203 } 203 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 void VideoScheduler::SendCursorShape( 271 void VideoScheduler::SendCursorShape(
272 scoped_ptr<protocol::CursorShapeInfo> cursor_shape) { 272 scoped_ptr<protocol::CursorShapeInfo> cursor_shape) {
273 DCHECK(network_task_runner_->BelongsToCurrentThread()); 273 DCHECK(network_task_runner_->BelongsToCurrentThread());
274 274
275 if (!cursor_stub_) 275 if (!cursor_stub_)
276 return; 276 return;
277 277
278 cursor_stub_->SetCursorShape(*cursor_shape); 278 cursor_stub_->SetCursorShape(*cursor_shape);
279 } 279 }
280 280
281 void VideoScheduler::StopOnNetworkThread(
282 scoped_ptr<VideoFrameCapturer> capturer) {
283 DCHECK(network_task_runner_->BelongsToCurrentThread());
284
285 // This is posted by StopOnEncodeThread meaning that both capture and encode
286 // threads are stopped now and it is safe to delete |capturer|.
287 }
288
281 // Encoder thread -------------------------------------------------------------- 289 // Encoder thread --------------------------------------------------------------
282 290
283 void VideoScheduler::EncodeFrame( 291 void VideoScheduler::EncodeFrame(
284 scoped_refptr<CaptureData> capture_data) { 292 scoped_refptr<CaptureData> capture_data) {
285 DCHECK(encode_task_runner_->BelongsToCurrentThread()); 293 DCHECK(encode_task_runner_->BelongsToCurrentThread());
286 294
287 // If there is nothing to encode then send an empty keep-alive packet. 295 // If there is nothing to encode then send an empty keep-alive packet.
288 if (!capture_data || capture_data->dirty_region().isEmpty()) { 296 if (!capture_data || capture_data->dirty_region().isEmpty()) {
289 scoped_ptr<VideoPacket> packet(new VideoPacket()); 297 scoped_ptr<VideoPacket> packet(new VideoPacket());
290 packet->set_flags(VideoPacket::LAST_PARTITION); 298 packet->set_flags(VideoPacket::LAST_PARTITION);
(...skipping 16 matching lines...) Expand all
307 if (last) { 315 if (last) {
308 scheduler_.RecordEncodeTime( 316 scheduler_.RecordEncodeTime(
309 base::TimeDelta::FromMilliseconds(packet->encode_time_ms())); 317 base::TimeDelta::FromMilliseconds(packet->encode_time_ms()));
310 } 318 }
311 319
312 network_task_runner_->PostTask( 320 network_task_runner_->PostTask(
313 FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this, 321 FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this,
314 base::Passed(&packet))); 322 base::Passed(&packet)));
315 } 323 }
316 324
317 void VideoScheduler::StopOnEncodeThread(const base::Closure& done_task) { 325 void VideoScheduler::StopOnEncodeThread(
326 scoped_ptr<VideoFrameCapturer> capturer) {
318 DCHECK(encode_task_runner_->BelongsToCurrentThread()); 327 DCHECK(encode_task_runner_->BelongsToCurrentThread());
319 328
320 // This is posted by StopOnCaptureThread, so we know that by the time we 329 // This is posted by StopOnCaptureThread, so we know that by the time we
321 // process it there are no more encode tasks queued. 330 // process it there are no more encode tasks queued. Pass |capturer_| for
322 network_task_runner_->PostTask(FROM_HERE, done_task); 331 // deletion on the thread that created it.
332 network_task_runner_->PostTask(
333 FROM_HERE, base::Bind(&VideoScheduler::StopOnNetworkThread, this,
334 base::Passed(&capturer)));
323 } 335 }
324 336
325 } // namespace remoting 337 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/video_scheduler.h ('k') | remoting/host/video_scheduler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698