summaryrefslogtreecommitdiffstats
path: root/remoting/host/session_manager.h
blob: 677e3bda0ae64e9f31ea6a4b8439b6a20136f57e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef REMOTING_HOST_RECORD_SESSION_H_
#define REMOTING_HOST_RECORD_SESSION_H_

#include <vector>

#include "base/basictypes.h"
#include "base/message_loop.h"
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
#include "base/time.h"
#include "remoting/base/protocol/chromotocol.pb.h"
#include "remoting/host/capturer.h"

namespace media {

class DataBuffer;

}  // namespace media

namespace remoting {

class Encoder;
class ClientConnection;

// A class for controlling and coordinate Capturer, Encoder
// and NetworkChannel in a record session.
//
// THREADING
//
// This class works on three threads, namely capture, encode and network
// thread. The main function of this class is to coordinate and schedule
// capture, encode and transmission of data on different threads.
//
// The following is an example of timeline for operations scheduled.
//
// |       CAPTURE       ENCODE     NETWORK
// |    .............
// |    .  Capture  .
// |    .............
// |                  ............
// |                  .          .
// |    ............. .          .
// |    .  Capture  . .  Encode  .
// |    ............. .          .
// |                  .          .
// |                  ............
// |    ............. ............ ..........
// |    .  Capture  . .          . .  Send  .
// |    ............. .          . ..........
// |                  .  Encode  .
// |                  .          .
// |                  .          .
// |                  ............
// | Time
// v
//
// SessionManager has the following responsibilities:
// 1. Make sure capture and encode occurs no more frequently than |rate|.
// 2. Make sure there is at most one outstanding capture not being encoded.
// 3. Distribute tasks on three threads on a timely fashion to minimize latency.
class SessionManager : public base::RefCountedThreadSafe<SessionManager> {
 public:

  // Construct a SessionManager. Message loops and threads are provided.
  // Ownership of Capturer and Encoder are given to this object.
  SessionManager(MessageLoop* capture_loop,
                MessageLoop* encode_loop,
                MessageLoop* network_loop,
                Capturer* capturer,
                Encoder* encoder);

  virtual ~SessionManager();

  // Start recording.
  void Start();

  // Pause the recording session.
  void Pause();

  // Set the maximum capture rate. This is denoted by number of updates
  // in one second. The actual system may run in a slower rate than the maximum
  // rate due to various factors, e.g. capture speed, encode speed and network
  // conditions.
  // This method should be called before Start() is called.
  void SetMaxRate(double rate);

  // Add a client to this recording session.
  void AddClient(scoped_refptr<ClientConnection> client);

  // Remove a client from receiving screen updates.
  void RemoveClient(scoped_refptr<ClientConnection> client);

 private:
  void DoStart();
  void DoPause();
  void DoStartRateControl();
  void DoPauseRateControl();

  void DoCapture();
  void DoFinishEncode();
  void DoEncode();
  void DoSendUpdate(
      UpdateStreamPacketHeader* header,
      scoped_refptr<media::DataBuffer> encoded_data,
      bool begin_update,
      bool end_update);
  void DoSendInit(scoped_refptr<ClientConnection> client,
                  int width, int height);
  void DoGetInitInfo(scoped_refptr<ClientConnection> client);
  void DoSetRate(double rate);
  void DoSetMaxRate(double max_rate);
  void DoAddClient(scoped_refptr<ClientConnection> client);
  void DoRemoveClient(scoped_refptr<ClientConnection> client);
  void DoRateControl();

  // Hepler method to schedule next capture using the current rate.
  void ScheduleNextCapture();

  // Helper method to schedule next rate regulation task.
  void ScheduleNextRateControl();

  void CaptureDoneTask();
  void EncodeDataAvailableTask();

  // Message loops used by this class.
  MessageLoop* capture_loop_;
  MessageLoop* encode_loop_;
  MessageLoop* network_loop_;

  // Reference to the capturer. This member is always accessed on the capture
  // thread.
  scoped_ptr<Capturer> capturer_;

  // Reference to the encoder. This member is always accessed on the encode
  // thread.
  scoped_ptr<Encoder> encoder_;

  // A list of clients connected to this hosts.
  // This member is always accessed on the NETWORK thread.
  // TODO(hclam): Have to scoped_refptr the clients since they have a shorter
  // lifetime than this object.
  typedef std::vector<scoped_refptr<ClientConnection> > ClientConnectionList;
  ClientConnectionList clients_;

  // The following members are accessed on the capture thread.
  double rate_;  // Number of captures to perform every second.
  bool started_;
  base::Time last_capture_time_; // Saves the time last capture started.
  int recordings_; // Count the number of recordings
                   // (i.e. capture or encode) happening.

  // The maximum rate is written on the capture thread and read on the network
  // thread.
  double max_rate_;  // Number of captures to perform every second.

  // The following member is accessed on the network thread.
  bool rate_control_started_;

  // Stores the data and information of the last capture done.
  // These members are written on capture thread and read on encode thread.
  // It is guranteed the read happens after the write.
  DirtyRects capture_dirty_rects_;
  const uint8* capture_data_[3];
  int capture_data_strides_[3];
  int capture_width_;
  int capture_height_;
  PixelFormat capture_pixel_format_;

  // The following members are accessed on the encode thread.
  // Output parameter written by Encoder to carry encoded data.
  UpdateStreamPacketHeader encoded_data_header_;
  scoped_refptr<media::DataBuffer> encoded_data_;

  // True if we have started receiving encoded data from the Encoder.
  bool encode_stream_started_;

  // Output parameter written by Encoder to notify the end of encoded data
  // stream.
  bool encode_done_;

  DISALLOW_COPY_AND_ASSIGN(SessionManager);
};

}  // namespace remoting

#endif  // REMOTING_HOST_RECORD_SESSION_H_