blob: 6ff904a8e3550cc59931072beb77a76f3bf10b23 [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(
88 FROM_HERE, base::Bind(&VideoEncoder::SetLosslessEncode,
89 base::Unretained(encoder_.get()), want_lossless));
90}
91
sergeyu10ce97b2015-02-05 23:53:1492void VideoFramePump::SetLosslessColor(bool want_lossless) {
sergeyu1afb35a12015-02-13 18:45:3093 DCHECK(thread_checker_.CalledOnValidThread());
sergeyu91f93b62015-02-05 20:14:3094
95 encode_task_runner_->PostTask(
96 FROM_HERE, base::Bind(&VideoEncoder::SetLosslessColor,
97 base::Unretained(encoder_.get()), want_lossless));
98}
99
sergeyuad51be82016-06-22 06:04:39100void VideoFramePump::SetObserver(Observer* observer) {
sergeyua609b7a2015-11-30 06:25:39101 DCHECK(thread_checker_.CalledOnValidThread());
sergeyuad51be82016-06-22 06:04:39102 observer_ = observer;
sergeyua609b7a2015-11-30 06:25:39103}
104
sergeyu546cbaa2016-06-17 20:39:32105void VideoFramePump::OnCaptureResult(
106 webrtc::DesktopCapturer::Result result,
107 std::unique_ptr<webrtc::DesktopFrame> frame) {
sergeyu1afb35a12015-02-13 18:45:30108 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]489682932012-11-08 19:36:14109
sergeyu1afb35a12015-02-13 18:45:30110 capture_scheduler_.OnCaptureCompleted();
sergeyu91f93b62015-02-05 20:14:30111
sergeyu752c6e62015-09-30 06:40:27112 captured_frame_timestamps_->capture_ended_time = base::TimeTicks::Now();
113
sergeyu7785d5a2016-04-01 21:55:00114 if (frame) {
115 webrtc::DesktopVector dpi =
116 frame->dpi().is_zero() ? webrtc::DesktopVector(kDefaultDpi, kDefaultDpi)
117 : frame->dpi();
118 if (!frame_size_.equals(frame->size()) || !frame_dpi_.equals(dpi)) {
119 frame_size_ = frame->size();
120 frame_dpi_ = dpi;
sergeyuad51be82016-06-22 06:04:39121 if (observer_)
122 observer_->OnVideoSizeChanged(this, frame_size_, frame_dpi_);
sergeyu7785d5a2016-04-01 21:55:00123 }
sergeyua609b7a2015-11-30 06:25:39124 }
125
sergeyu91f93b62015-02-05 20:14:30126 // Even when |frame| is nullptr we still need to post it to the encode thread
127 // to make sure frames are freed in the same order they are received and
128 // that we don't start capturing frame n+2 before frame n is freed.
129 base::PostTaskAndReplyWithResult(
130 encode_task_runner_.get(), FROM_HERE,
sergeyu752c6e62015-09-30 06:40:27131 base::Bind(&VideoFramePump::EncodeFrame, encoder_.get(),
sergeyu546cbaa2016-06-17 20:39:32132 base::Passed(&frame),
sergeyu752c6e62015-09-30 06:40:27133 base::Passed(&captured_frame_timestamps_)),
134 base::Bind(&VideoFramePump::OnFrameEncoded, weak_factory_.GetWeakPtr()));
sergeyu91f93b62015-02-05 20:14:30135}
136
sergeyu1afb35a12015-02-13 18:45:30137void VideoFramePump::CaptureNextFrame() {
138 DCHECK(thread_checker_.CalledOnValidThread());
139
sergeyue84cc622016-10-15 06:54:03140 captured_frame_timestamps_.reset(new FrameTimestamps());
sergeyu752c6e62015-09-30 06:40:27141 captured_frame_timestamps_->capture_started_time = base::TimeTicks::Now();
142
sergeyue84cc622016-10-15 06:54:03143 if (event_timestamps_source_) {
144 captured_frame_timestamps_->input_event_timestamps =
145 event_timestamps_source_->TakeLastEventTimestamps();
146 }
147
zijiehe27bcc912016-10-18 05:57:56148 capturer_->CaptureFrame();
sergeyu1afb35a12015-02-13 18:45:30149}
150
sergeyu752c6e62015-09-30 06:40:27151// static
dcheng0765c492016-04-06 22:41:53152std::unique_ptr<VideoFramePump::PacketWithTimestamps>
153VideoFramePump::EncodeFrame(VideoEncoder* encoder,
154 std::unique_ptr<webrtc::DesktopFrame> frame,
155 std::unique_ptr<FrameTimestamps> timestamps) {
sergeyu752c6e62015-09-30 06:40:27156 timestamps->encode_started_time = base::TimeTicks::Now();
157
dcheng0765c492016-04-06 22:41:53158 std::unique_ptr<VideoPacket> packet;
sergeyu752c6e62015-09-30 06:40:27159 // If |frame| is non-NULL then let the encoder process it.
160 if (frame)
sergeyu2becb6012016-09-13 18:41:32161 packet = encoder->Encode(*frame);
sergeyu752c6e62015-09-30 06:40:27162
163 // If |frame| is NULL, or the encoder returned nothing, return an empty
164 // packet.
165 if (!packet)
166 packet.reset(new VideoPacket());
167
168 if (frame)
169 packet->set_capture_time_ms(frame->capture_time_ms());
170
171 timestamps->encode_ended_time = base::TimeTicks::Now();
anandc6928da072015-10-31 01:33:49172 packet->set_encode_time_ms(
173 (timestamps->encode_ended_time - timestamps->encode_started_time)
174 .InMilliseconds());
sergeyu752c6e62015-09-30 06:40:27175
Jinho Bang138fde32018-01-18 23:13:42176 return std::make_unique<PacketWithTimestamps>(std::move(packet),
ricea68860bd2016-08-22 02:48:56177 std::move(timestamps));
sergeyu752c6e62015-09-30 06:40:27178}
179
dcheng0765c492016-04-06 22:41:53180void VideoFramePump::OnFrameEncoded(
181 std::unique_ptr<PacketWithTimestamps> packet) {
sergeyu1afb35a12015-02-13 18:45:30182 DCHECK(thread_checker_.CalledOnValidThread());
sergeyu91f93b62015-02-05 20:14:30183
sergeyu752c6e62015-09-30 06:40:27184 capture_scheduler_.OnFrameEncoded(packet->packet.get());
sergeyu91f93b62015-02-05 20:14:30185
sergeyu752c6e62015-09-30 06:40:27186 if (send_pending_) {
sergeyuaa6fa2342015-12-22 23:26:48187 pending_packets_.push_back(std::move(packet));
sergeyu752c6e62015-09-30 06:40:27188 } else {
sergeyuaa6fa2342015-12-22 23:26:48189 SendPacket(std::move(packet));
sergeyu752c6e62015-09-30 06:40:27190 }
191}
sergeyu91f93b62015-02-05 20:14:30192
dcheng0765c492016-04-06 22:41:53193void VideoFramePump::SendPacket(std::unique_ptr<PacketWithTimestamps> packet) {
sergeyu752c6e62015-09-30 06:40:27194 DCHECK(thread_checker_.CalledOnValidThread());
195 DCHECK(!send_pending_);
sergeyu91f93b62015-02-05 20:14:30196
sergeyu752c6e62015-09-30 06:40:27197 packet->timestamps->can_send_time = base::TimeTicks::Now();
198 UpdateFrameTimers(packet->packet.get(), packet->timestamps.get());
199
200 send_pending_ = true;
sergeyuaa6fa2342015-12-22 23:26:48201 video_stub_->ProcessVideoPacket(std::move(packet->packet),
sergeyu1afb35a12015-02-13 18:45:30202 base::Bind(&VideoFramePump::OnVideoPacketSent,
203 weak_factory_.GetWeakPtr()));
[email protected]cb3b1f9312010-06-07 19:58:23204}
205
sergeyu752c6e62015-09-30 06:40:27206void VideoFramePump::UpdateFrameTimers(VideoPacket* packet,
207 FrameTimestamps* timestamps) {
sergeyue84cc622016-10-15 06:54:03208 if (!timestamps->input_event_timestamps.is_null()) {
209 packet->set_capture_pending_time_ms(
210 (timestamps->capture_started_time -
211 timestamps->input_event_timestamps.host_timestamp)
212 .InMilliseconds());
sergeyu752c6e62015-09-30 06:40:27213 packet->set_latest_event_timestamp(
sergeyue84cc622016-10-15 06:54:03214 timestamps->input_event_timestamps.client_timestamp.ToInternalValue());
sergeyu752c6e62015-09-30 06:40:27215 }
216
217 packet->set_capture_overhead_time_ms(
218 (timestamps->capture_ended_time - timestamps->capture_started_time)
219 .InMilliseconds() -
220 packet->capture_time_ms());
221
222 packet->set_encode_pending_time_ms(
223 (timestamps->encode_started_time - timestamps->capture_ended_time)
224 .InMilliseconds());
225
226 packet->set_send_pending_time_ms(
227 (timestamps->can_send_time - timestamps->encode_ended_time)
228 .InMilliseconds());
229}
230
sergeyu10ce97b2015-02-05 23:53:14231void VideoFramePump::OnVideoPacketSent() {
sergeyu1afb35a12015-02-13 18:45:30232 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]9302fce2012-03-28 03:57:57233
sergeyu752c6e62015-09-30 06:40:27234 send_pending_ = false;
sergeyu1afb35a12015-02-13 18:45:30235 capture_scheduler_.OnFrameSent();
236 keep_alive_timer_.Reset();
sergeyu752c6e62015-09-30 06:40:27237
238 // Send next packet if any.
239 if (!pending_packets_.empty()) {
avi954c9c1d2017-01-11 16:52:37240 std::unique_ptr<PacketWithTimestamps> next =
241 std::move(pending_packets_.front());
242 pending_packets_.erase(pending_packets_.begin());
sergeyuaa6fa2342015-12-22 23:26:48243 SendPacket(std::move(next));
sergeyu752c6e62015-09-30 06:40:27244 }
[email protected]5bc71832010-12-09 01:34:08245}
246
sergeyu10ce97b2015-02-05 23:53:14247void VideoFramePump::SendKeepAlivePacket() {
sergeyu1afb35a12015-02-13 18:45:30248 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]3e555342014-05-26 04:30:35249
[email protected]3e555342014-05-26 04:30:35250 video_stub_->ProcessVideoPacket(
Jinho Bang138fde32018-01-18 23:13:42251 std::make_unique<VideoPacket>(),
sergeyu1afb35a12015-02-13 18:45:30252 base::Bind(&VideoFramePump::OnKeepAlivePacketSent,
253 weak_factory_.GetWeakPtr()));
[email protected]3e555342014-05-26 04:30:35254}
255
sergeyu10ce97b2015-02-05 23:53:14256void VideoFramePump::OnKeepAlivePacketSent() {
sergeyu1afb35a12015-02-13 18:45:30257 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]3e555342014-05-26 04:30:35258
sergeyu1afb35a12015-02-13 18:45:30259 keep_alive_timer_.Reset();
[email protected]d65e15bd2012-06-02 22:16:41260}
261
sergeyu4d208002015-11-23 22:27:43262} // namespace protocol
[email protected]cb3b1f9312010-06-07 19:58:23263} // namespace remoting