blob: 46e8b0f69813df6ef46ae5ebf0feafc165c1c470 [file] [log] [blame]
sergeyu10ce97b2015-02-05 23:53:141// Copyright 2015 The Chromium Authors. All rights reserved.
[email protected]cb3b1f9312010-06-07 19:58:232// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
sergeyu4d208002015-11-23 22:27:435#include "remoting/protocol/video_frame_pump.h"
[email protected]cb3b1f9312010-06-07 19:58:236
7#include <algorithm>
dcheng0765c492016-04-06 22:41:538#include <memory>
sergeyu89d088b2015-12-24 00:22:449#include <utility>
[email protected]cb3b1f9312010-06-07 19:58:2310
[email protected]8db2aaae2011-08-12 22:46:1111#include "base/bind.h"
[email protected]8ef69222011-12-20 03:12:5412#include "base/callback.h"
[email protected]cb3b1f9312010-06-07 19:58:2313#include "base/logging.h"
sergeyu1afb35a12015-02-13 18:45:3014#include "base/single_thread_task_runner.h"
sergeyu91f93b62015-02-05 20:14:3015#include "base/task_runner_util.h"
[email protected]5d7eb862013-06-28 15:21:2416#include "base/time/time.h"
sergeyu7785d5a2016-04-01 21:55:0017#include "remoting/base/constants.h"
[email protected]35b9c562010-11-09 02:22:4318#include "remoting/proto/control.pb.h"
[email protected]3adf1b22010-11-09 23:22:2019#include "remoting/proto/video.pb.h"
[email protected]3aef7222013-06-07 22:39:5020#include "remoting/protocol/video_stub.h"
[email protected]b9ed58f2013-05-16 10:45:2421#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
[email protected]cb3b1f9312010-06-07 19:58:2322
23namespace remoting {
sergeyu4d208002015-11-23 22:27:4324namespace protocol {
[email protected]cb3b1f9312010-06-07 19:58:2325
[email protected]b2bdc102014-08-15 22:23:1626// Interval between empty keep-alive frames. These frames are sent only when the
27// stream is paused or inactive for some other reason (e.g. when blocked on
28// capturer). To prevent PseudoTCP from resetting congestion window this value
29// must be smaller than the minimum RTO used in PseudoTCP, which is 250ms.
[email protected]997a3222014-07-08 06:17:2430static const int kKeepAlivePacketIntervalMs = 200;
[email protected]3e555342014-05-26 04:30:3531
Chris Watkins6fe52aa2017-11-28 03:24:0532VideoFramePump::FrameTimestamps::FrameTimestamps() = default;
33VideoFramePump::FrameTimestamps::~FrameTimestamps() = default;
sergeyu752c6e62015-09-30 06:40:2734
35VideoFramePump::PacketWithTimestamps::PacketWithTimestamps(
dcheng0765c492016-04-06 22:41:5336 std::unique_ptr<VideoPacket> packet,
37 std::unique_ptr<FrameTimestamps> timestamps)
sergeyuaa6fa2342015-12-22 23:26:4838 : packet(std::move(packet)), timestamps(std::move(timestamps)) {}
sergeyu752c6e62015-09-30 06:40:2739
Chris Watkins6fe52aa2017-11-28 03:24:0540VideoFramePump::PacketWithTimestamps::~PacketWithTimestamps() = default;
sergeyu752c6e62015-09-30 06:40:2741
sergeyu10ce97b2015-02-05 23:53:1442VideoFramePump::VideoFramePump(
[email protected]3c8cfbe72012-07-03 00:24:1543 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
dcheng0765c492016-04-06 22:41:5344 std::unique_ptr<webrtc::DesktopCapturer> capturer,
45 std::unique_ptr<VideoEncoder> encoder,
[email protected]324b1962013-05-01 19:30:2246 protocol::VideoStub* video_stub)
sergeyu1afb35a12015-02-13 18:45:3047 : encode_task_runner_(encode_task_runner),
sergeyuaa6fa2342015-12-22 23:26:4848 capturer_(std::move(capturer)),
49 encoder_(std::move(encoder)),
[email protected]324b1962013-05-01 19:30:2250 video_stub_(video_stub),
sergeyu9fa354c2015-02-19 00:39:2551 keep_alive_timer_(
52 FROM_HERE,
53 base::TimeDelta::FromMilliseconds(kKeepAlivePacketIntervalMs),
54 base::Bind(&VideoFramePump::SendKeepAlivePacket,
tzik9cd62f9d2018-07-11 02:27:2555 base::Unretained(this))),
sergeyu1afb35a12015-02-13 18:45:3056 capture_scheduler_(base::Bind(&VideoFramePump::CaptureNextFrame,
57 base::Unretained(this))),
sergeyu1afb35a12015-02-13 18:45:3058 weak_factory_(this) {
[email protected]324b1962013-05-01 19:30:2259 DCHECK(encoder_);
[email protected]324b1962013-05-01 19:30:2260 DCHECK(video_stub_);
[email protected]cb3b1f9312010-06-07 19:58:2361
sergeyu1afb35a12015-02-13 18:45:3062 capturer_->Start(this);
63 capture_scheduler_.Start();
sergeyu91f93b62015-02-05 20:14:3064}
65
sergeyu1afb35a12015-02-13 18:45:3066VideoFramePump::~VideoFramePump() {
joedow18837eb2017-05-17 18:28:2467 DCHECK(thread_checker_.CalledOnValidThread());
sergeyu1afb35a12015-02-13 18:45:3068 encode_task_runner_->DeleteSoon(FROM_HERE, encoder_.release());
sergeyu91f93b62015-02-05 20:14:3069}
70
sergeyue84cc622016-10-15 06:54:0371void VideoFramePump::SetEventTimestampsSource(
72 scoped_refptr<InputEventTimestampsSource> event_timestamps_source) {
73 DCHECK(thread_checker_.CalledOnValidThread());
74
75 event_timestamps_source_ = event_timestamps_source;
76}
77
sergeyu10ce97b2015-02-05 23:53:1478void VideoFramePump::Pause(bool pause) {
sergeyu1afb35a12015-02-13 18:45:3079 DCHECK(thread_checker_.CalledOnValidThread());
sergeyu91f93b62015-02-05 20:14:3080
sergeyu1afb35a12015-02-13 18:45:3081 capture_scheduler_.Pause(pause);
sergeyu91f93b62015-02-05 20:14:3082}
83
sergeyu10ce97b2015-02-05 23:53:1484void VideoFramePump::SetLosslessEncode(bool want_lossless) {
sergeyu1afb35a12015-02-13 18:45:3085 DCHECK(thread_checker_.CalledOnValidThread());
sergeyu91f93b62015-02-05 20:14:3086
87 encode_task_runner_->PostTask(
kylechar2caf4d62019-02-15 20:03:4288 FROM_HERE,
89 base::BindOnce(&VideoEncoder::SetLosslessEncode,
90 base::Unretained(encoder_.get()), want_lossless));
sergeyu91f93b62015-02-05 20:14:3091}
92
sergeyu10ce97b2015-02-05 23:53:1493void VideoFramePump::SetLosslessColor(bool want_lossless) {
sergeyu1afb35a12015-02-13 18:45:3094 DCHECK(thread_checker_.CalledOnValidThread());
sergeyu91f93b62015-02-05 20:14:3095
96 encode_task_runner_->PostTask(
kylechar2caf4d62019-02-15 20:03:4297 FROM_HERE,
98 base::BindOnce(&VideoEncoder::SetLosslessColor,
99 base::Unretained(encoder_.get()), want_lossless));
sergeyu91f93b62015-02-05 20:14:30100}
101
sergeyuad51be82016-06-22 06:04:39102void VideoFramePump::SetObserver(Observer* observer) {
sergeyua609b7a2015-11-30 06:25:39103 DCHECK(thread_checker_.CalledOnValidThread());
sergeyuad51be82016-06-22 06:04:39104 observer_ = observer;
sergeyua609b7a2015-11-30 06:25:39105}
106
Gary Kacmarcik0c56fda2019-01-17 03:10:12107void VideoFramePump::SelectSource(int id) {}
108
sergeyu546cbaa2016-06-17 20:39:32109void VideoFramePump::OnCaptureResult(
110 webrtc::DesktopCapturer::Result result,
111 std::unique_ptr<webrtc::DesktopFrame> frame) {
sergeyu1afb35a12015-02-13 18:45:30112 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]489682932012-11-08 19:36:14113
sergeyu1afb35a12015-02-13 18:45:30114 capture_scheduler_.OnCaptureCompleted();
sergeyu91f93b62015-02-05 20:14:30115
sergeyu752c6e62015-09-30 06:40:27116 captured_frame_timestamps_->capture_ended_time = base::TimeTicks::Now();
117
sergeyu7785d5a2016-04-01 21:55:00118 if (frame) {
119 webrtc::DesktopVector dpi =
120 frame->dpi().is_zero() ? webrtc::DesktopVector(kDefaultDpi, kDefaultDpi)
121 : frame->dpi();
122 if (!frame_size_.equals(frame->size()) || !frame_dpi_.equals(dpi)) {
123 frame_size_ = frame->size();
124 frame_dpi_ = dpi;
sergeyuad51be82016-06-22 06:04:39125 if (observer_)
126 observer_->OnVideoSizeChanged(this, frame_size_, frame_dpi_);
sergeyu7785d5a2016-04-01 21:55:00127 }
sergeyua609b7a2015-11-30 06:25:39128 }
129
sergeyu91f93b62015-02-05 20:14:30130 // Even when |frame| is nullptr we still need to post it to the encode thread
131 // to make sure frames are freed in the same order they are received and
132 // that we don't start capturing frame n+2 before frame n is freed.
133 base::PostTaskAndReplyWithResult(
134 encode_task_runner_.get(), FROM_HERE,
sergeyu752c6e62015-09-30 06:40:27135 base::Bind(&VideoFramePump::EncodeFrame, encoder_.get(),
sergeyu546cbaa2016-06-17 20:39:32136 base::Passed(&frame),
sergeyu752c6e62015-09-30 06:40:27137 base::Passed(&captured_frame_timestamps_)),
138 base::Bind(&VideoFramePump::OnFrameEncoded, weak_factory_.GetWeakPtr()));
sergeyu91f93b62015-02-05 20:14:30139}
140
sergeyu1afb35a12015-02-13 18:45:30141void VideoFramePump::CaptureNextFrame() {
142 DCHECK(thread_checker_.CalledOnValidThread());
143
sergeyue84cc622016-10-15 06:54:03144 captured_frame_timestamps_.reset(new FrameTimestamps());
sergeyu752c6e62015-09-30 06:40:27145 captured_frame_timestamps_->capture_started_time = base::TimeTicks::Now();
146
sergeyue84cc622016-10-15 06:54:03147 if (event_timestamps_source_) {
148 captured_frame_timestamps_->input_event_timestamps =
149 event_timestamps_source_->TakeLastEventTimestamps();
150 }
151
zijiehe27bcc912016-10-18 05:57:56152 capturer_->CaptureFrame();
sergeyu1afb35a12015-02-13 18:45:30153}
154
sergeyu752c6e62015-09-30 06:40:27155// static
dcheng0765c492016-04-06 22:41:53156std::unique_ptr<VideoFramePump::PacketWithTimestamps>
157VideoFramePump::EncodeFrame(VideoEncoder* encoder,
158 std::unique_ptr<webrtc::DesktopFrame> frame,
159 std::unique_ptr<FrameTimestamps> timestamps) {
sergeyu752c6e62015-09-30 06:40:27160 timestamps->encode_started_time = base::TimeTicks::Now();
161
dcheng0765c492016-04-06 22:41:53162 std::unique_ptr<VideoPacket> packet;
sergeyu752c6e62015-09-30 06:40:27163 // If |frame| is non-NULL then let the encoder process it.
164 if (frame)
sergeyu2becb6012016-09-13 18:41:32165 packet = encoder->Encode(*frame);
sergeyu752c6e62015-09-30 06:40:27166
167 // If |frame| is NULL, or the encoder returned nothing, return an empty
168 // packet.
169 if (!packet)
170 packet.reset(new VideoPacket());
171
172 if (frame)
173 packet->set_capture_time_ms(frame->capture_time_ms());
174
175 timestamps->encode_ended_time = base::TimeTicks::Now();
anandc6928da072015-10-31 01:33:49176 packet->set_encode_time_ms(
177 (timestamps->encode_ended_time - timestamps->encode_started_time)
178 .InMilliseconds());
sergeyu752c6e62015-09-30 06:40:27179
Jinho Bang138fde32018-01-18 23:13:42180 return std::make_unique<PacketWithTimestamps>(std::move(packet),
ricea68860bd2016-08-22 02:48:56181 std::move(timestamps));
sergeyu752c6e62015-09-30 06:40:27182}
183
dcheng0765c492016-04-06 22:41:53184void VideoFramePump::OnFrameEncoded(
185 std::unique_ptr<PacketWithTimestamps> packet) {
sergeyu1afb35a12015-02-13 18:45:30186 DCHECK(thread_checker_.CalledOnValidThread());
sergeyu91f93b62015-02-05 20:14:30187
sergeyu752c6e62015-09-30 06:40:27188 capture_scheduler_.OnFrameEncoded(packet->packet.get());
sergeyu91f93b62015-02-05 20:14:30189
sergeyu752c6e62015-09-30 06:40:27190 if (send_pending_) {
sergeyuaa6fa2342015-12-22 23:26:48191 pending_packets_.push_back(std::move(packet));
sergeyu752c6e62015-09-30 06:40:27192 } else {
sergeyuaa6fa2342015-12-22 23:26:48193 SendPacket(std::move(packet));
sergeyu752c6e62015-09-30 06:40:27194 }
195}
sergeyu91f93b62015-02-05 20:14:30196
dcheng0765c492016-04-06 22:41:53197void VideoFramePump::SendPacket(std::unique_ptr<PacketWithTimestamps> packet) {
sergeyu752c6e62015-09-30 06:40:27198 DCHECK(thread_checker_.CalledOnValidThread());
199 DCHECK(!send_pending_);
sergeyu91f93b62015-02-05 20:14:30200
sergeyu752c6e62015-09-30 06:40:27201 packet->timestamps->can_send_time = base::TimeTicks::Now();
202 UpdateFrameTimers(packet->packet.get(), packet->timestamps.get());
203
204 send_pending_ = true;
Erik Jensen56d7f2e2019-02-20 01:38:56205 video_stub_->ProcessVideoPacket(
206 std::move(packet->packet),
207 base::BindOnce(&VideoFramePump::OnVideoPacketSent,
208 weak_factory_.GetWeakPtr()));
[email protected]cb3b1f9312010-06-07 19:58:23209}
210
sergeyu752c6e62015-09-30 06:40:27211void VideoFramePump::UpdateFrameTimers(VideoPacket* packet,
212 FrameTimestamps* timestamps) {
sergeyue84cc622016-10-15 06:54:03213 if (!timestamps->input_event_timestamps.is_null()) {
214 packet->set_capture_pending_time_ms(
215 (timestamps->capture_started_time -
216 timestamps->input_event_timestamps.host_timestamp)
217 .InMilliseconds());
sergeyu752c6e62015-09-30 06:40:27218 packet->set_latest_event_timestamp(
sergeyue84cc622016-10-15 06:54:03219 timestamps->input_event_timestamps.client_timestamp.ToInternalValue());
sergeyu752c6e62015-09-30 06:40:27220 }
221
222 packet->set_capture_overhead_time_ms(
223 (timestamps->capture_ended_time - timestamps->capture_started_time)
224 .InMilliseconds() -
225 packet->capture_time_ms());
226
227 packet->set_encode_pending_time_ms(
228 (timestamps->encode_started_time - timestamps->capture_ended_time)
229 .InMilliseconds());
230
231 packet->set_send_pending_time_ms(
232 (timestamps->can_send_time - timestamps->encode_ended_time)
233 .InMilliseconds());
234}
235
sergeyu10ce97b2015-02-05 23:53:14236void VideoFramePump::OnVideoPacketSent() {
sergeyu1afb35a12015-02-13 18:45:30237 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]9302fce2012-03-28 03:57:57238
sergeyu752c6e62015-09-30 06:40:27239 send_pending_ = false;
sergeyu1afb35a12015-02-13 18:45:30240 capture_scheduler_.OnFrameSent();
241 keep_alive_timer_.Reset();
sergeyu752c6e62015-09-30 06:40:27242
243 // Send next packet if any.
244 if (!pending_packets_.empty()) {
avi954c9c1d2017-01-11 16:52:37245 std::unique_ptr<PacketWithTimestamps> next =
246 std::move(pending_packets_.front());
247 pending_packets_.erase(pending_packets_.begin());
sergeyuaa6fa2342015-12-22 23:26:48248 SendPacket(std::move(next));
sergeyu752c6e62015-09-30 06:40:27249 }
[email protected]5bc71832010-12-09 01:34:08250}
251
sergeyu10ce97b2015-02-05 23:53:14252void VideoFramePump::SendKeepAlivePacket() {
sergeyu1afb35a12015-02-13 18:45:30253 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]3e555342014-05-26 04:30:35254
[email protected]3e555342014-05-26 04:30:35255 video_stub_->ProcessVideoPacket(
Jinho Bang138fde32018-01-18 23:13:42256 std::make_unique<VideoPacket>(),
Erik Jensen56d7f2e2019-02-20 01:38:56257 base::BindOnce(&VideoFramePump::OnKeepAlivePacketSent,
258 weak_factory_.GetWeakPtr()));
[email protected]3e555342014-05-26 04:30:35259}
260
sergeyu10ce97b2015-02-05 23:53:14261void VideoFramePump::OnKeepAlivePacketSent() {
sergeyu1afb35a12015-02-13 18:45:30262 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]3e555342014-05-26 04:30:35263
sergeyu1afb35a12015-02-13 18:45:30264 keep_alive_timer_.Reset();
[email protected]d65e15bd2012-06-02 22:16:41265}
266
sergeyu4d208002015-11-23 22:27:43267} // namespace protocol
[email protected]cb3b1f9312010-06-07 19:58:23268} // namespace remoting