blob: 2e341c774e07a46c725833acbcb26fb5fb4c6b66 [file] [log] [blame]
// 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/callback.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 base {
class MessageLoopProxy;
} // namespace base
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,
base::MessageLoopProxy* 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(const base::Closure& 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 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(const base::Closure& 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(const base::Closure& 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_;
scoped_refptr<base::MessageLoopProxy> 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_;
// Per-thread flags that are set when the ScreenRecorder is
// stopped. They must be used on the corresponding threads only.
bool network_stopped_;
bool encoder_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_