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
|
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_PROTOCOL_VIDEO_FRAME_PUMP_H_
#define REMOTING_PROTOCOL_VIDEO_FRAME_PUMP_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "remoting/codec/video_encoder.h"
#include "remoting/proto/video.pb.h"
#include "remoting/protocol/capture_scheduler.h"
#include "remoting/protocol/desktop_capturer.h"
#include "remoting/protocol/video_stream.h"
namespace base {
class SingleThreadTaskRunner;
} // namespace base
namespace remoting::protocol {
class VideoFeedbackStub;
class VideoStub;
// Class responsible for scheduling frame captures from a screen capturer,
// 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
//
// VideoFramePump 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 VideoFramePump : public VideoStream,
public webrtc::DesktopCapturer::Callback {
public:
// Creates a VideoFramePump running capture, encode and network tasks on the
// supplied TaskRunners. Video will be pumped to |video_stub|, which must
// outlive the pump..
VideoFramePump(scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
std::unique_ptr<DesktopCapturer> capturer,
std::unique_ptr<VideoEncoder> encoder,
protocol::VideoStub* video_stub);
VideoFramePump(const VideoFramePump&) = delete;
VideoFramePump& operator=(const VideoFramePump&) = delete;
~VideoFramePump() override;
// VideoStream interface.
void SetEventTimestampsSource(scoped_refptr<InputEventTimestampsSource>
event_timestamps_source) override;
void Pause(bool pause) override;
void SetObserver(Observer* observer) override;
void SelectSource(webrtc::ScreenId id) override;
void SetComposeEnabled(bool enabled) override;
void SetMouseCursor(
std::unique_ptr<webrtc::MouseCursor> mouse_cursor) override;
void SetMouseCursorPosition(const webrtc::DesktopVector& position) override;
void SetTargetFramerate(int framerate) override;
protocol::VideoFeedbackStub* video_feedback_stub() {
return &capture_scheduler_;
}
private:
struct FrameTimestamps {
FrameTimestamps();
~FrameTimestamps();
// The following field is not-null for a single frame after each incoming
// input event.
InputEventTimestamps input_event_timestamps;
base::TimeTicks capture_started_time;
base::TimeTicks capture_ended_time;
base::TimeTicks encode_started_time;
base::TimeTicks encode_ended_time;
base::TimeTicks can_send_time;
};
struct PacketWithTimestamps {
PacketWithTimestamps(std::unique_ptr<VideoPacket> packet,
std::unique_ptr<FrameTimestamps> timestamps);
~PacketWithTimestamps();
std::unique_ptr<VideoPacket> packet;
std::unique_ptr<FrameTimestamps> timestamps;
};
// webrtc::DesktopCapturer::Callback interface.
void OnCaptureResult(webrtc::DesktopCapturer::Result result,
std::unique_ptr<webrtc::DesktopFrame> frame) override;
// Callback for CaptureScheduler.
void CaptureNextFrame();
// Task running on the encoder thread to encode the |frame|.
static std::unique_ptr<PacketWithTimestamps> EncodeFrame(
VideoEncoder* encoder,
std::unique_ptr<webrtc::DesktopFrame> frame,
std::unique_ptr<FrameTimestamps> timestamps);
// Task called when a frame has finished encoding.
void OnFrameEncoded(std::unique_ptr<PacketWithTimestamps> packet);
// Sends |packet| to the client.
void SendPacket(std::unique_ptr<PacketWithTimestamps> packet);
// Helper called from SendPacket() to calculate timing fields in the |packet|
// before sending it.
void UpdateFrameTimers(VideoPacket* packet, FrameTimestamps* timestamps);
// Callback passed to |video_stub_|.
void OnVideoPacketSent();
// Called by |keep_alive_timer_|.
void SendKeepAlivePacket();
// Callback for |video_stub_| called after a keep-alive packet is sent.
void OnKeepAlivePacketSent();
// Task runner used to run |encoder_|.
scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner_;
// Capturer used to capture the screen.
std::unique_ptr<DesktopCapturer> capturer_;
// Used to encode captured frames. Always accessed on the encode thread.
std::unique_ptr<VideoEncoder> encoder_;
scoped_refptr<InputEventTimestampsSource> event_timestamps_source_;
// Interface through which video frames are passed to the client.
raw_ptr<protocol::VideoStub> video_stub_;
raw_ptr<Observer> observer_ = nullptr;
webrtc::DesktopSize frame_size_;
webrtc::DesktopVector frame_dpi_;
// 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.
base::RetainingOneShotTimer keep_alive_timer_;
// CaptureScheduler calls CaptureNextFrame() whenever a new frame needs to be
// captured.
CaptureScheduler capture_scheduler_;
// Timestamps for the frame that's being captured.
std::unique_ptr<FrameTimestamps> captured_frame_timestamps_;
bool send_pending_ = false;
std::vector<std::unique_ptr<PacketWithTimestamps>> pending_packets_;
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<VideoFramePump> weak_factory_{this};
};
} // namespace remoting::protocol
#endif // REMOTING_PROTOCOL_VIDEO_FRAME_PUMP_H_
|