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
3// found in the LICENSE file.
4
5#ifndef REMOTING_HOST_VIDEO_SCHEDULER_H_
6#define REMOTING_HOST_VIDEO_SCHEDULER_H_
7
8#include <vector>
9
10#include "base/basictypes.h"
11#include "base/memory/ref_counted.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/time/time.h"
14#include "base/timer/timer.h"
15#include "remoting/codec/video_encoder.h"
16#include "remoting/host/capture_scheduler.h"
17#include "remoting/proto/video.pb.h"
18#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
19#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
20
21namespace base {
22class SingleThreadTaskRunner;
23}  // namespace base
24
25namespace media {
26class DesktopCapturer;
27}  // namespace media
28
29namespace remoting {
30
31class CursorShapeInfo;
32
33namespace protocol {
34class CursorShapeInfo;
35class CursorShapeStub;
36class VideoStub;
37}  // namespace protocol
38
39// Class responsible for scheduling frame captures from a
40// webrtc::DesktopCapturer, delivering them to a VideoEncoder to encode, and
41// finally passing the encoded video packets to the specified VideoStub to send
42// on the network.
43//
44// THREADING
45//
46// This class is supplied TaskRunners to use for capture, encode and network
47// operations.  Capture, encode and network transmission tasks are interleaved
48// as illustrated below:
49//
50// |       CAPTURE       ENCODE     NETWORK
51// |    .............
52// |    .  Capture  .
53// |    .............
54// |                  ............
55// |                  .          .
56// |    ............. .          .
57// |    .  Capture  . .  Encode  .
58// |    ............. .          .
59// |                  .          .
60// |                  ............
61// |    ............. ............ ..........
62// |    .  Capture  . .          . .  Send  .
63// |    ............. .          . ..........
64// |                  .  Encode  .
65// |                  .          .
66// |                  .          .
67// |                  ............
68// | Time
69// v
70//
71// VideoScheduler would ideally schedule captures so as to saturate the slowest
72// of the capture, encode and network processes.  However, it also needs to
73// rate-limit captures to avoid overloading the host system, either by consuming
74// too much CPU, or hogging the host's graphics subsystem.
75
76class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>,
77                       public webrtc::DesktopCapturer::Callback,
78                       public webrtc::MouseCursorMonitor::Callback {
79 public:
80  // Enables timestamps for generated frames. Used for testing.
81  static void EnableTimestampsForTests();
82
83  // Creates a VideoScheduler running capture, encode and network tasks on the
84  // supplied TaskRunners.  Video and cursor shape updates will be pumped to
85  // |video_stub| and |client_stub|, which must remain valid until Stop() is
86  // called. |capturer| is used to capture frames.
87  VideoScheduler(
88      scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
89      scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
90      scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
91      scoped_ptr<webrtc::DesktopCapturer> capturer,
92      scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor,
93      scoped_ptr<VideoEncoder> encoder,
94      protocol::CursorShapeStub* cursor_stub,
95      protocol::VideoStub* video_stub);
96
97  // webrtc::DesktopCapturer::Callback implementation.
98  virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
99  virtual void OnCaptureCompleted(webrtc::DesktopFrame* frame) OVERRIDE;
100
101  // webrtc::MouseCursorMonitor::Callback implementation.
102  virtual void OnMouseCursor(
103      webrtc::MouseCursor* mouse_cursor) OVERRIDE;
104  virtual void OnMouseCursorPosition(
105      webrtc::MouseCursorMonitor::CursorState state,
106      const webrtc::DesktopVector& position) OVERRIDE;
107
108  // Starts scheduling frame captures.
109  void Start();
110
111  // Stop scheduling frame captures. This object cannot be re-used once
112  // it has been stopped.
113  void Stop();
114
115  // Pauses or resumes scheduling of frame captures.  Pausing/resuming captures
116  // only affects capture scheduling and does not stop/start the capturer.
117  void Pause(bool pause);
118
119  // Updates the sequence number embedded in VideoPackets.
120  // Sequence numbers are used for performance measurements.
121  void UpdateSequenceNumber(int64 sequence_number);
122
123  // Sets whether the video encoder should be requested to encode losslessly,
124  // or to use a lossless color space (typically requiring higher bandwidth).
125  void SetLosslessEncode(bool want_lossless);
126  void SetLosslessColor(bool want_lossless);
127
128 private:
129  friend class base::RefCountedThreadSafe<VideoScheduler>;
130  virtual ~VideoScheduler();
131
132  // Capturer thread ----------------------------------------------------------
133
134  // Starts the capturer on the capture thread.
135  void StartOnCaptureThread();
136
137  // Stops scheduling frame captures on the capture thread.
138  void StopOnCaptureThread();
139
140  // Schedules the next call to CaptureNextFrame.
141  void ScheduleNextCapture();
142
143  // Starts the next frame capture, unless there are already too many pending.
144  void CaptureNextFrame();
145
146  // Called when a frame capture has been encoded & sent to the client.
147  void FrameCaptureCompleted();
148
149  // Network thread -----------------------------------------------------------
150
151  // Send |packet| to the client, unless we are in the process of stopping.
152  void SendVideoPacket(scoped_ptr<VideoPacket> packet);
153
154  // Callback passed to |video_stub_| for the last packet in each frame, to
155  // rate-limit frame captures to network throughput.
156  void OnVideoPacketSent();
157
158  // Called by |keep_alive_timer_|.
159  void SendKeepAlivePacket();
160
161  // Callback for |video_stub_| called after a keep-alive packet is sent.
162  void OnKeepAlivePacketSent();
163
164  // Send updated cursor shape to client.
165  void SendCursorShape(scoped_ptr<protocol::CursorShapeInfo> cursor_shape);
166
167  // Encoder thread -----------------------------------------------------------
168
169  // Encode a frame, passing generated VideoPackets to SendVideoPacket().
170  void EncodeFrame(scoped_ptr<webrtc::DesktopFrame> frame,
171                   int64 sequence_number,
172                   base::TimeTicks timestamp);
173
174  void EncodedDataAvailableCallback(int64 sequence_number,
175                                    scoped_ptr<VideoPacket> packet);
176
177  // Task runners used by this class.
178  scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_;
179  scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner_;
180  scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
181
182  // Used to capture frames. Always accessed on the capture thread.
183  scoped_ptr<webrtc::DesktopCapturer> capturer_;
184
185  // Used to capture mouse cursor shapes. Always accessed on the capture thread.
186  scoped_ptr<webrtc::MouseCursorMonitor> mouse_cursor_monitor_;
187
188  // Used to encode captured frames. Always accessed on the encode thread.
189  scoped_ptr<VideoEncoder> encoder_;
190
191  // Interfaces through which video frames and cursor shapes are passed to the
192  // client. These members are always accessed on the network thread.
193  protocol::CursorShapeStub* cursor_stub_;
194  protocol::VideoStub* video_stub_;
195
196  // Timer used to schedule CaptureNextFrame().
197  scoped_ptr<base::OneShotTimer<VideoScheduler> > capture_timer_;
198
199  // Timer used to ensure that we send empty keep-alive frames to the client
200  // even when the video stream is paused or encoder is busy.
201  scoped_ptr<base::DelayTimer<VideoScheduler> > keep_alive_timer_;
202
203  // The number of frames being processed, i.e. frames that we are currently
204  // capturing, encoding or sending. The value is capped at 2 to minimize
205  // latency.
206  int pending_frames_;
207
208  // Set when the capturer is capturing a frame.
209  bool capture_pending_;
210
211  // True if the previous scheduled capture was skipped.
212  bool did_skip_frame_;
213
214  // True if capture of video frames is paused.
215  bool is_paused_;
216
217  // Number updated by the caller to trace performance.
218  int64 sequence_number_;
219
220  // An object to schedule capturing.
221  CaptureScheduler scheduler_;
222
223  DISALLOW_COPY_AND_ASSIGN(VideoScheduler);
224};
225
226}  // namespace remoting
227
228#endif  // REMOTING_HOST_VIDEO_SCHEDULER_H_
229