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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
// Copyright (c) 2011 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_SCREEN_RECORDER_H_
#define REMOTING_HOST_SCREEN_RECORDER_H_
#include <vector>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/time.h"
#include "base/timer.h"
#include "remoting/base/encoder.h"
#include "remoting/host/capturer.h"
#include "remoting/proto/video.pb.h"
namespace remoting {
namespace protocol {
class ConnectionToClient;
} // namespace protocol
class CaptureData;
// 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
//
// ScreenRecorder 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.
//
// This class has the following state variables:
// |is_recording_| - If this is set to false there should be no activity on
// the capture thread by this object.
// |network_stopped_| - This state is to prevent activity on the network thread
// if set to false.
class ScreenRecorder : public base::RefCountedThreadSafe<ScreenRecorder> {
public:
// Construct a ScreenRecorder. Message loops and threads are provided.
// This object does not own capturer but owns encoder.
ScreenRecorder(MessageLoop* capture_loop,
MessageLoop* encode_loop,
MessageLoop* network_loop,
Capturer* capturer,
Encoder* encoder);
virtual ~ScreenRecorder();
// Start recording.
void Start();
// Stop the recording session. |done_task| is executed when recording is fully
// stopped. This object cannot be used again after |task| is executed.
void Stop(Task* done_task);
// 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 connection to this recording session.
void AddConnection(scoped_refptr<protocol::ConnectionToClient> connection);
// Remove a connection from receiving screen updates.
void RemoveConnection(scoped_refptr<protocol::ConnectionToClient> connection);
// Remove all connections.
void RemoveAllConnections();
// Update the sequence number for tracing performance.
void UpdateSequenceNumber(int64 sequence_number);
private:
// Getters for capturer and encoder.
Capturer* capturer();
Encoder* encoder();
// Capturer thread ----------------------------------------------------------
void DoStart();
void DoStop(Task* done_task);
void DoSetMaxRate(double max_rate);
// Hepler method to schedule next capture using the current rate.
void StartCaptureTimer();
void DoCapture();
void CaptureDoneCallback(scoped_refptr<CaptureData> capture_data);
void DoFinishOneRecording();
void DoInvalidateFullScreen();
// Network thread -----------------------------------------------------------
// DoSendVideoPacket takes ownership of the |packet| and is responsible
// for deleting it.
void DoSendVideoPacket(VideoPacket* packet);
void DoSendInit(scoped_refptr<protocol::ConnectionToClient> connection,
int width, int height);
void DoAddConnection(scoped_refptr<protocol::ConnectionToClient> connection);
void DoRemoveClient(scoped_refptr<protocol::ConnectionToClient> connection);
void DoRemoveAllClients();
// Signal network thread to cease activities.
void DoStopOnNetworkThread(Task* done_task);
// Callback for the last packet in one update. Deletes |packet| and
// schedules next screen capture.
void FrameSentCallback(VideoPacket* packet);
// Encoder thread -----------------------------------------------------------
void DoEncode(scoped_refptr<CaptureData> capture_data);
// Perform stop operations on encode thread.
void DoStopOnEncodeThread(Task* done_task);
// EncodedDataAvailableCallback takes ownership of |packet|.
void EncodedDataAvailableCallback(VideoPacket* packet);
void SendVideoPacket(VideoPacket* packet);
// 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.
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.
typedef std::vector<scoped_refptr<protocol::ConnectionToClient> >
ConnectionToClientList;
ConnectionToClientList connections_;
// Flag that indicates recording has been started. This variable should only
// be used on the capture thread.
bool is_recording_;
// Flag that indicates network is being stopped. This variable should only
// be used on the network thread.
bool network_stopped_;
// Timer that calls DoCapture.
base::RepeatingTimer<ScreenRecorder> capture_timer_;
// Count the number of recordings (i.e. capture or encode) happening.
int recordings_;
// Set to true if we've skipped last capture because there are too
// many pending frames.
int frame_skipped_;
// Number of captures to perform every second. Written on the capture thread.
double max_rate_;
// Time when capture is started.
base::Time capture_start_time_;
// Time when encode is started.
base::Time encode_start_time_;
// This is a number updated by client to trace performance.
int64 sequence_number_;
DISALLOW_COPY_AND_ASSIGN(ScreenRecorder);
};
} // namespace remoting
#endif // REMOTING_HOST_SCREEN_RECORDER_H_
|