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

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

Issue 13983010: Use webrtc::DesktopCapturer for screen capturer implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: q Created 7 years, 7 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"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop_proxy.h" 13 #include "base/message_loop_proxy.h"
14 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 #include "base/sys_info.h" 15 #include "base/sys_info.h"
16 #include "base/time.h" 16 #include "base/time.h"
17 #include "media/video/capture/screen/mouse_cursor_shape.h" 17 #include "media/video/capture/screen/mouse_cursor_shape.h"
18 #include "media/video/capture/screen/screen_capture_data.h"
19 #include "media/video/capture/screen/screen_capturer.h" 18 #include "media/video/capture/screen/screen_capturer.h"
20 #include "remoting/proto/control.pb.h" 19 #include "remoting/proto/control.pb.h"
21 #include "remoting/proto/internal.pb.h" 20 #include "remoting/proto/internal.pb.h"
22 #include "remoting/proto/video.pb.h" 21 #include "remoting/proto/video.pb.h"
23 #include "remoting/protocol/cursor_shape_stub.h" 22 #include "remoting/protocol/cursor_shape_stub.h"
24 #include "remoting/protocol/message_decoder.h" 23 #include "remoting/protocol/message_decoder.h"
25 #include "remoting/protocol/video_stub.h" 24 #include "remoting/protocol/video_stub.h"
26 #include "remoting/protocol/util.h" 25 #include "remoting/protocol/util.h"
26 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.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 // 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,
(...skipping 13 matching lines...) Expand all
50 capture_task_runner, encode_task_runner, network_task_runner, 50 capture_task_runner, encode_task_runner, network_task_runner,
51 capturer.Pass(), 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 webrtc::SharedMemory* VideoScheduler::CreateSharedMemory(size_t size) {
61 scoped_refptr<media::ScreenCaptureData> capture_data) { 61 return NULL;
62 }
63
64 void VideoScheduler::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
62 DCHECK(capture_task_runner_->BelongsToCurrentThread()); 65 DCHECK(capture_task_runner_->BelongsToCurrentThread());
63 66
64 // Do nothing if the scheduler is being stopped. 67 scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
65 if (!capturer_)
66 return;
67 68
68 if (capture_data) { 69 if (frame) {
69 scheduler_.RecordCaptureTime( 70 scheduler_.RecordCaptureTime(
70 base::TimeDelta::FromMilliseconds(capture_data->capture_time_ms())); 71 base::TimeDelta::FromMilliseconds(frame->capture_time_ms()));
71
72 // The best way to get this value is by binding the sequence number to
73 // the callback when calling CaptureInvalidRects(). However the callback
74 // system doesn't allow this. Reading from the member variable is
75 // accurate as long as capture is synchronous as the following statement
76 // will obtain the most recent sequence number received.
77 capture_data->set_client_sequence_number(sequence_number_);
78 } 72 }
79 73
80 encode_task_runner_->PostTask( 74 encode_task_runner_->PostTask(
81 FROM_HERE, base::Bind(&VideoScheduler::EncodeFrame, this, capture_data)); 75 FROM_HERE, base::Bind(&VideoScheduler::EncodeFrame, this,
76 base::Passed(&owned_frame), sequence_number_));
82 } 77 }
83 78
84 void VideoScheduler::OnCursorShapeChanged( 79 void VideoScheduler::OnCursorShapeChanged(
85 scoped_ptr<media::MouseCursorShape> cursor_shape) { 80 scoped_ptr<media::MouseCursorShape> cursor_shape) {
86 DCHECK(capture_task_runner_->BelongsToCurrentThread()); 81 DCHECK(capture_task_runner_->BelongsToCurrentThread());
87 82
88 // Do nothing if the scheduler is being stopped. 83 // Do nothing if the scheduler is being stopped.
89 if (!capturer_) 84 if (!capturer_)
90 return; 85 return;
91 86
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 162
168 VideoScheduler::~VideoScheduler() { 163 VideoScheduler::~VideoScheduler() {
169 } 164 }
170 165
171 // Capturer thread ------------------------------------------------------------- 166 // Capturer thread -------------------------------------------------------------
172 167
173 void VideoScheduler::StartOnCaptureThread() { 168 void VideoScheduler::StartOnCaptureThread() {
174 DCHECK(capture_task_runner_->BelongsToCurrentThread()); 169 DCHECK(capture_task_runner_->BelongsToCurrentThread());
175 170
176 // Start the capturer and let it notify us if cursor shape changes. 171 // Start the capturer and let it notify us if cursor shape changes.
172 capturer_->SetMouseShapeObserver(this);
177 capturer_->Start(this); 173 capturer_->Start(this);
178 174
179 capture_timer_.reset(new base::OneShotTimer<VideoScheduler>()); 175 capture_timer_.reset(new base::OneShotTimer<VideoScheduler>());
180 176
181 // Capture first frame immedately. 177 // Capture first frame immedately.
182 CaptureNextFrame(); 178 CaptureNextFrame();
183 } 179 }
184 180
185 void VideoScheduler::StopOnCaptureThread() { 181 void VideoScheduler::StopOnCaptureThread() {
186 DCHECK(capture_task_runner_->BelongsToCurrentThread()); 182 DCHECK(capture_task_runner_->BelongsToCurrentThread());
187 183
184 capturer_.reset();
alexeypa (please no reviews) 2013/04/26 21:33:58 nit: Add a comment saying that the frames currentl
Sergey Ulanov 2013/05/07 22:25:50 Done.
185
188 // |capture_timer_| must be destroyed on the thread on which it is used. 186 // |capture_timer_| must be destroyed on the thread on which it is used.
189 capture_timer_.reset(); 187 capture_timer_.reset();
190
191 // Schedule deletion of |capturer_| once the encode thread is no longer
192 // processing capture data. See http://crbug.com/163641. This also clears
193 // |capturer_| pointer to prevent pending tasks from using it.
194 // TODO(wez): Make it safe to tear down capturer while buffers remain, and
195 // remove this work-around.
196 encode_task_runner_->PostTask(
197 FROM_HERE, base::Bind(&VideoScheduler::StopOnEncodeThread, this,
198 base::Passed(&capturer_)));
199 } 188 }
200 189
201 void VideoScheduler::ScheduleNextCapture() { 190 void VideoScheduler::ScheduleNextCapture() {
202 DCHECK(capture_task_runner_->BelongsToCurrentThread()); 191 DCHECK(capture_task_runner_->BelongsToCurrentThread());
203 192
204 capture_timer_->Start(FROM_HERE, 193 capture_timer_->Start(FROM_HERE,
205 scheduler_.NextCaptureDelay(), 194 scheduler_.NextCaptureDelay(),
206 this, 195 this,
207 &VideoScheduler::CaptureNextFrame); 196 &VideoScheduler::CaptureNextFrame);
208 } 197 }
(...skipping 16 matching lines...) Expand all
225 did_skip_frame_ = false; 214 did_skip_frame_ = false;
226 215
227 // At this point we are going to perform one capture so save the current time. 216 // At this point we are going to perform one capture so save the current time.
228 pending_captures_++; 217 pending_captures_++;
229 DCHECK_LE(pending_captures_, kMaxPendingCaptures); 218 DCHECK_LE(pending_captures_, kMaxPendingCaptures);
230 219
231 // Before doing a capture schedule for the next one. 220 // Before doing a capture schedule for the next one.
232 ScheduleNextCapture(); 221 ScheduleNextCapture();
233 222
234 // And finally perform one capture. 223 // And finally perform one capture.
235 capturer_->CaptureFrame(); 224 capturer_->Capture(webrtc::DesktopRegion());
236 } 225 }
237 226
238 void VideoScheduler::FrameCaptureCompleted() { 227 void VideoScheduler::FrameCaptureCompleted() {
239 DCHECK(capture_task_runner_->BelongsToCurrentThread()); 228 DCHECK(capture_task_runner_->BelongsToCurrentThread());
240 229
241 // Decrement the pending capture count. 230 // Decrement the pending capture count.
242 pending_captures_--; 231 pending_captures_--;
243 DCHECK_GE(pending_captures_, 0); 232 DCHECK_GE(pending_captures_, 0);
244 233
245 // If we've skipped a frame capture because too we had too many captures 234 // If we've skipped a frame capture because too we had too many captures
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 268
280 if (!cursor_stub_) 269 if (!cursor_stub_)
281 return; 270 return;
282 271
283 cursor_stub_->SetCursorShape(*cursor_shape); 272 cursor_stub_->SetCursorShape(*cursor_shape);
284 } 273 }
285 274
286 // Encoder thread -------------------------------------------------------------- 275 // Encoder thread --------------------------------------------------------------
287 276
288 void VideoScheduler::EncodeFrame( 277 void VideoScheduler::EncodeFrame(
289 scoped_refptr<media::ScreenCaptureData> capture_data) { 278 scoped_ptr<webrtc::DesktopFrame> frame,
279 int sequence_number) {
290 DCHECK(encode_task_runner_->BelongsToCurrentThread()); 280 DCHECK(encode_task_runner_->BelongsToCurrentThread());
291 281
292 // If there is nothing to encode then send an empty keep-alive packet. 282 // If there is nothing to encode then send an empty keep-alive packet.
293 if (!capture_data || capture_data->dirty_region().isEmpty()) { 283 if (!frame || frame->updated_region().is_empty()) {
294 scoped_ptr<VideoPacket> packet(new VideoPacket()); 284 scoped_ptr<VideoPacket> packet(new VideoPacket());
295 packet->set_flags(VideoPacket::LAST_PARTITION); 285 packet->set_flags(VideoPacket::LAST_PARTITION);
286 packet->set_sequence_number(sequence_number);
296 network_task_runner_->PostTask( 287 network_task_runner_->PostTask(
297 FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this, 288 FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this,
298 base::Passed(&packet))); 289 base::Passed(&packet)));
290 capture_task_runner_->DeleteSoon(FROM_HERE, frame.release());
299 return; 291 return;
300 } 292 }
301 293
302 encoder_->Encode( 294 encoder_->Encode(
303 capture_data, false, 295 frame.get(), base::Bind(&VideoScheduler::EncodedDataAvailableCallback,
304 base::Bind(&VideoScheduler::EncodedDataAvailableCallback, this)); 296 this, sequence_number));
297 capture_task_runner_->DeleteSoon(FROM_HERE, frame.release());
305 } 298 }
306 299
307 void VideoScheduler::EncodedDataAvailableCallback( 300 void VideoScheduler::EncodedDataAvailableCallback(
301 int sequence_number,
308 scoped_ptr<VideoPacket> packet) { 302 scoped_ptr<VideoPacket> packet) {
309 DCHECK(encode_task_runner_->BelongsToCurrentThread()); 303 DCHECK(encode_task_runner_->BelongsToCurrentThread());
310 304
305 packet->set_sequence_number(sequence_number);
306
311 bool last = (packet->flags() & VideoPacket::LAST_PACKET) != 0; 307 bool last = (packet->flags() & VideoPacket::LAST_PACKET) != 0;
312 if (last) { 308 if (last) {
313 scheduler_.RecordEncodeTime( 309 scheduler_.RecordEncodeTime(
314 base::TimeDelta::FromMilliseconds(packet->encode_time_ms())); 310 base::TimeDelta::FromMilliseconds(packet->encode_time_ms()));
315 } 311 }
316 312
317 network_task_runner_->PostTask( 313 network_task_runner_->PostTask(
318 FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this, 314 FROM_HERE, base::Bind(&VideoScheduler::SendVideoPacket, this,
319 base::Passed(&packet))); 315 base::Passed(&packet)));
320 } 316 }
321 317
322 void VideoScheduler::StopOnEncodeThread(
323 scoped_ptr<media::ScreenCapturer> capturer) {
324 DCHECK(encode_task_runner_->BelongsToCurrentThread());
325
326 // 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
328 // deletion on the capture thread.
329 capture_task_runner_->DeleteSoon(FROM_HERE, capturer.release());
330 }
331
332 } // namespace remoting 318 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698