| // Copyright (c) 2012 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_VIDEO_SCHEDULER_H_ |
| #define REMOTING_HOST_VIDEO_SCHEDULER_H_ |
| |
| #include <vector> |
| |
| #include "base/basictypes.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/time/time.h" |
| #include "base/timer/timer.h" |
| #include "remoting/codec/video_encoder.h" |
| #include "remoting/host/capture_scheduler.h" |
| #include "remoting/proto/video.pb.h" |
| #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" |
| |
| namespace base { |
| class SingleThreadTaskRunner; |
| } // namespace base |
| |
| namespace media { |
| class ScreenCapturer; |
| } // namespace media |
| |
| namespace remoting { |
| |
| class CursorShapeInfo; |
| |
| namespace protocol { |
| class CursorShapeInfo; |
| class CursorShapeStub; |
| class VideoStub; |
| } // namespace protocol |
| |
| // Class responsible for scheduling frame captures from a |
| // webrtc::ScreenCapturer, delivering them to a VideoEncoder to encode, and |
| // finally passing the encoded video packets to the specified VideoStub to send |
| // on the network. |
| // |
| // THREADING |
| // |
| // This class is supplied TaskRunners to use for capture, encode and network |
| // operations. Capture, encode and network transmission tasks are interleaved |
| // as illustrated below: |
| // |
| // | CAPTURE ENCODE NETWORK |
| // | ............. |
| // | . Capture . |
| // | ............. |
| // | ............ |
| // | . . |
| // | ............. . . |
| // | . Capture . . Encode . |
| // | ............. . . |
| // | . . |
| // | ............ |
| // | ............. ............ .......... |
| // | . Capture . . . . Send . |
| // | ............. . . .......... |
| // | . Encode . |
| // | . . |
| // | . . |
| // | ............ |
| // | Time |
| // v |
| // |
| // VideoScheduler would ideally schedule captures so as to saturate the slowest |
| // of the capture, encode and network processes. However, it also needs to |
| // rate-limit captures to avoid overloading the host system, either by consuming |
| // too much CPU, or hogging the host's graphics subsystem. |
| |
| class VideoScheduler : public base::RefCountedThreadSafe<VideoScheduler>, |
| public webrtc::DesktopCapturer::Callback, |
| public webrtc::ScreenCapturer::MouseShapeObserver { |
| public: |
| // Creates a VideoScheduler running capture, encode and network tasks on the |
| // supplied TaskRunners. Video and cursor shape updates will be pumped to |
| // |video_stub| and |client_stub|, which must remain valid until Stop() is |
| // called. |capturer| is used to capture frames. |
| VideoScheduler( |
| scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner, |
| scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner, |
| scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, |
| scoped_ptr<webrtc::ScreenCapturer> capturer, |
| scoped_ptr<VideoEncoder> encoder, |
| protocol::CursorShapeStub* cursor_stub, |
| protocol::VideoStub* video_stub); |
| |
| // webrtc::DesktopCapturer::Callback implementation. |
| virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE; |
| virtual void OnCaptureCompleted(webrtc::DesktopFrame* frame) OVERRIDE; |
| |
| // webrtc::ScreenCapturer::MouseShapeObserver implementation. |
| virtual void OnCursorShapeChanged( |
| webrtc::MouseCursorShape* cursor_shape) OVERRIDE; |
| |
| // Starts scheduling frame captures. |
| void Start(); |
| |
| // Stop scheduling frame captures. This object cannot be re-used once |
| // it has been stopped. |
| void Stop(); |
| |
| // Pauses or resumes scheduling of frame captures. Pausing/resuming captures |
| // only affects capture scheduling and does not stop/start the capturer. |
| void Pause(bool pause); |
| |
| // Updates the sequence number embedded in VideoPackets. |
| // Sequence numbers are used for performance measurements. |
| void UpdateSequenceNumber(int64 sequence_number); |
| |
| // Sets whether the video encoder should be requested to encode losslessly, |
| // or to use a lossless color space (typically requiring higher bandwidth). |
| void SetLosslessEncode(bool want_lossless); |
| void SetLosslessColor(bool want_lossless); |
| |
| private: |
| friend class base::RefCountedThreadSafe<VideoScheduler>; |
| virtual ~VideoScheduler(); |
| |
| // Capturer thread ---------------------------------------------------------- |
| |
| // Starts the capturer on the capture thread. |
| void StartOnCaptureThread(); |
| |
| // Stops scheduling frame captures on the capture thread. |
| void StopOnCaptureThread(); |
| |
| // Schedules the next call to CaptureNextFrame. |
| void ScheduleNextCapture(); |
| |
| // Starts the next frame capture, unless there are already too many pending. |
| void CaptureNextFrame(); |
| |
| // Called when a frame capture has been encoded & sent to the client. |
| void FrameCaptureCompleted(); |
| |
| // Network thread ----------------------------------------------------------- |
| |
| // Send |packet| to the client, unless we are in the process of stopping. |
| void SendVideoPacket(scoped_ptr<VideoPacket> packet); |
| |
| // Callback passed to |video_stub_| for the last packet in each frame, to |
| // rate-limit frame captures to network throughput. |
| void OnVideoPacketSent(); |
| |
| // Called by |keep_alive_timer_|. |
| void SendKeepAlivePacket(); |
| |
| // Callback for |video_stub_| called after a keep-alive packet is sent. |
| void OnKeepAlivePacketSent(); |
| |
| // Send updated cursor shape to client. |
| void SendCursorShape(scoped_ptr<protocol::CursorShapeInfo> cursor_shape); |
| |
| // Encoder thread ----------------------------------------------------------- |
| |
| // Encode a frame, passing generated VideoPackets to SendVideoPacket(). |
| void EncodeFrame(scoped_ptr<webrtc::DesktopFrame> frame, |
| int64 sequence_number); |
| |
| void EncodedDataAvailableCallback(int64 sequence_number, |
| scoped_ptr<VideoPacket> packet); |
| |
| // Task runners used by this class. |
| scoped_refptr<base::SingleThreadTaskRunner> capture_task_runner_; |
| scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner_; |
| scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; |
| |
| // Used to capture frames. Always accessed on the capture thread. |
| scoped_ptr<webrtc::ScreenCapturer> capturer_; |
| |
| // Used to encode captured frames. Always accessed on the encode thread. |
| scoped_ptr<VideoEncoder> encoder_; |
| |
| // Interfaces through which video frames and cursor shapes are passed to the |
| // client. These members are always accessed on the network thread. |
| protocol::CursorShapeStub* cursor_stub_; |
| protocol::VideoStub* video_stub_; |
| |
| // Timer used to schedule CaptureNextFrame(). |
| scoped_ptr<base::OneShotTimer<VideoScheduler> > capture_timer_; |
| |
| // Timer used to ensure that we send empty keep-alive frames to the client |
| // even when the video stream is paused or encoder is busy. |
| scoped_ptr<base::DelayTimer<VideoScheduler> > keep_alive_timer_; |
| |
| // The number of frames being processed, i.e. frames that we are currently |
| // capturing, encoding or sending. The value is capped at 2 to minimize |
| // latency. |
| int pending_frames_; |
| |
| // Set when the capturer is capturing a frame. |
| bool capture_pending_; |
| |
| // True if the previous scheduled capture was skipped. |
| bool did_skip_frame_; |
| |
| // True if capture of video frames is paused. |
| bool is_paused_; |
| |
| // Number updated by the caller to trace performance. |
| int64 sequence_number_; |
| |
| // An object to schedule capturing. |
| CaptureScheduler scheduler_; |
| |
| DISALLOW_COPY_AND_ASSIGN(VideoScheduler); |
| }; |
| |
| } // namespace remoting |
| |
| #endif // REMOTING_HOST_VIDEO_SCHEDULER_H_ |