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/screen_capturer.h"
19
20namespace base {
21class SingleThreadTaskRunner;
22}  // namespace base
23
24namespace media {
25class ScreenCapturer;
26}  // namespace media
27
28namespace remoting {
29
30class CursorShapeInfo;
31
32namespace protocol {
33class CursorShapeInfo;
34class CursorShapeStub;
35class VideoStub;
36}  // namespace protocol
37
38// Class responsible for scheduling frame captures from a
39// webrtc::ScreenCapturer, delivering them to a VideoEncoder to encode, and
40// finally passing the encoded video packets to the specified VideoStub to send
41// on the network.
42//
43// THREADING
44//
45// This class is supplied TaskRunners to use for capture, encode and network
46// operations.  Capture, encode and network transmission tasks are interleaved
47// as illustrated below:
48//
49// |       CAPTURE       ENCODE     NETWORK
50// |    .............
51// |    .  Capture  .
52// |    .............
53// |                  ............
54// |                  .          .
55// |    ............. .          .
56// |    .  Capture  . .  Encode  .
57// |    ............. .          .
58// |                  .          .
59// |                  ............
60// |    ............. ............ ..........
61// |    .  Capture  . .          . .  Send  .
62// |    ............. .          . ..........
63// |                  .  Encode  .
64// |                  .          .
65// |                  .          .
66// |                  ............
67// | Time
68// v
69//
70// VideoScheduler would ideally schedule captures so as to saturate the slowest
71// of the capture, encode and network processes.  However, it also needs to
72// rate-limit captures to avoid overloading the host system, either by consuming
73// too much CPU, or hogging the host's graphics subsystem.
74
75class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>,
76                       public webrtc::DesktopCapturer::Callback,
77                       public webrtc::ScreenCapturer::MouseShapeObserver {
78 public:
79  // Creates a VideoScheduler running capture, encode and network tasks on the
80  // supplied TaskRunners.  Video and cursor shape updates will be pumped to
81  // |video_stub| and |client_stub|, which must remain valid until Stop() is
82  // called. |capturer| is used to capture frames.
83  VideoScheduler(
84      scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner,
85      scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
86      scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
87      scoped_ptr<webrtc::ScreenCapturer> capturer,
88      scoped_ptr<VideoEncoder> encoder,
89      protocol::CursorShapeStub* cursor_stub,
90      protocol::VideoStub* video_stub);
91
92  // webrtc::DesktopCapturer::Callback implementation.
93  virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
94  virtual void OnCaptureCompleted(webrtc::DesktopFrame* frame) OVERRIDE;
95
96  // webrtc::ScreenCapturer::MouseShapeObserver implementation.
97  virtual void OnCursorShapeChanged(
98      webrtc::MouseCursorShape* cursor_shape) OVERRIDE;
99
100  // Starts scheduling frame captures.
101  void Start();
102
103  // Stop scheduling frame captures. This object cannot be re-used once
104  // it has been stopped.
105  void Stop();
106
107  // Pauses or resumes scheduling of frame captures.  Pausing/resuming captures
108  // only affects capture scheduling and does not stop/start the capturer.
109  void Pause(bool pause);
110
111  // Updates the sequence number embedded in VideoPackets.
112  // Sequence numbers are used for performance measurements.
113  void UpdateSequenceNumber(int64 sequence_number);
114
115 private:
116  friend class base::RefCountedThreadSafe<VideoScheduler>;
117  virtual ~VideoScheduler();
118
119  // Capturer thread ----------------------------------------------------------
120
121  // Starts the capturer on the capture thread.
122  void StartOnCaptureThread();
123
124  // Stops scheduling frame captures on the capture thread.
125  void StopOnCaptureThread();
126
127  // Schedules the next call to CaptureNextFrame.
128  void ScheduleNextCapture();
129
130  // Starts the next frame capture, unless there are already too many pending.
131  void CaptureNextFrame();
132
133  // Called when a frame capture has been encoded & sent to the client.
134  void FrameCaptureCompleted();
135
136  // Network thread -----------------------------------------------------------
137
138  // Send |packet| to the client, unless we are in the process of stopping.
139  void SendVideoPacket(scoped_ptr<VideoPacket> packet);
140
141  // Callback passed to |video_stub_| for the last packet in each frame, to
142  // rate-limit frame captures to network throughput.
143  void VideoFrameSentCallback();
144
145  // Send updated cursor shape to client.
146  void SendCursorShape(scoped_ptr<protocol::CursorShapeInfo> cursor_shape);
147
148  // Encoder thread -----------------------------------------------------------
149
150  // Encode a frame, passing generated VideoPackets to SendVideoPacket().
151  void EncodeFrame(scoped_ptr<webrtc::DesktopFrame> frame,
152                   int64 sequence_number);
153
154  void EncodedDataAvailableCallback(int64 sequence_number,
155                                    scoped_ptr<VideoPacket> packet);
156
157  // Task runners used by this class.
158  scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_;
159  scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner_;
160  scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
161
162  // Used to capture frames. Always accessed on the capture thread.
163  scoped_ptr<webrtc::ScreenCapturer> capturer_;
164
165  // Used to encode captured frames. Always accessed on the encode thread.
166  scoped_ptr<VideoEncoder> encoder_;
167
168  // Interfaces through which video frames and cursor shapes are passed to the
169  // client. These members are always accessed on the network thread.
170  protocol::CursorShapeStub* cursor_stub_;
171  protocol::VideoStub* video_stub_;
172
173  // Timer used to schedule CaptureNextFrame().
174  scoped_ptr<base::OneShotTimer<VideoScheduler> > capture_timer_;
175
176  // The number of frames being processed, i.e. frames that we are currently
177  // capturing, encoding or sending. The value is capped at 2 to minimize
178  // latency.
179  int pending_frames_;
180
181  // Set when the capturer is capturing a frame.
182  bool capture_pending_;
183
184  // True if the previous scheduled capture was skipped.
185  bool did_skip_frame_;
186
187  // True if capture of video frames is paused.
188  bool is_paused_;
189
190  // This is a number updated by client to trace performance.
191  int64 sequence_number_;
192
193  // An object to schedule capturing.
194  CaptureScheduler scheduler_;
195
196  DISALLOW_COPY_AND_ASSIGN(VideoScheduler);
197};
198
199}  // namespace remoting
200
201#endif  // REMOTING_HOST_VIDEO_SCHEDULER_H_
202