Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / remoting / host / video_frame_pump.cc
blob37d9da7c25e1ff47bc6b8bda8bf9488eac436be7
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/host/video_frame_pump.h"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/task_runner_util.h"
15 #include "base/time/time.h"
16 #include "remoting/proto/control.pb.h"
17 #include "remoting/proto/video.pb.h"
18 #include "remoting/protocol/video_stub.h"
19 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
21 namespace remoting {
23 namespace {
25 scoped_ptr<VideoPacket> EncodeFrame(VideoEncoder* encoder,
26 scoped_ptr<webrtc::DesktopFrame> frame) {
27 scoped_ptr<VideoPacket> packet;
29 // If |frame| is non-NULL then let the encoder process it.
30 if (frame) {
31 packet = encoder->Encode(*frame);
34 // If |frame| is NULL, or the encoder returned nothing, return an empty
35 // packet.
36 if (!packet) {
37 packet.reset(new VideoPacket());
40 return packet.Pass();
43 } // namespace
45 // Interval between empty keep-alive frames. These frames are sent only when the
46 // stream is paused or inactive for some other reason (e.g. when blocked on
47 // capturer). To prevent PseudoTCP from resetting congestion window this value
48 // must be smaller than the minimum RTO used in PseudoTCP, which is 250ms.
49 static const int kKeepAlivePacketIntervalMs = 200;
51 static bool g_enable_timestamps = false;
53 // static
54 void VideoFramePump::EnableTimestampsForTests() {
55 g_enable_timestamps = true;
58 VideoFramePump::VideoFramePump(
59 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
60 scoped_ptr<webrtc::DesktopCapturer> capturer,
61 scoped_ptr<VideoEncoder> encoder,
62 protocol::VideoStub* video_stub)
63 : encode_task_runner_(encode_task_runner),
64 capturer_(capturer.Pass()),
65 encoder_(encoder.Pass()),
66 video_stub_(video_stub),
67 keep_alive_timer_(
68 FROM_HERE,
69 base::TimeDelta::FromMilliseconds(kKeepAlivePacketIntervalMs),
70 base::Bind(&VideoFramePump::SendKeepAlivePacket,
71 base::Unretained(this)),
72 false),
73 capture_scheduler_(base::Bind(&VideoFramePump::CaptureNextFrame,
74 base::Unretained(this))),
75 latest_event_timestamp_(0),
76 weak_factory_(this) {
77 DCHECK(encoder_);
78 DCHECK(video_stub_);
80 capturer_->Start(this);
81 capture_scheduler_.Start();
84 VideoFramePump::~VideoFramePump() {
85 encode_task_runner_->DeleteSoon(FROM_HERE, encoder_.release());
88 void VideoFramePump::Pause(bool pause) {
89 DCHECK(thread_checker_.CalledOnValidThread());
91 capture_scheduler_.Pause(pause);
94 void VideoFramePump::SetLatestEventTimestamp(int64 latest_event_timestamp) {
95 DCHECK(thread_checker_.CalledOnValidThread());
97 latest_event_timestamp_ = latest_event_timestamp;
100 void VideoFramePump::SetLosslessEncode(bool want_lossless) {
101 DCHECK(thread_checker_.CalledOnValidThread());
103 encode_task_runner_->PostTask(
104 FROM_HERE, base::Bind(&VideoEncoder::SetLosslessEncode,
105 base::Unretained(encoder_.get()), want_lossless));
108 void VideoFramePump::SetLosslessColor(bool want_lossless) {
109 DCHECK(thread_checker_.CalledOnValidThread());
111 encode_task_runner_->PostTask(
112 FROM_HERE, base::Bind(&VideoEncoder::SetLosslessColor,
113 base::Unretained(encoder_.get()), want_lossless));
116 webrtc::SharedMemory* VideoFramePump::CreateSharedMemory(size_t size) {
117 DCHECK(thread_checker_.CalledOnValidThread());
118 return nullptr;
121 void VideoFramePump::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
122 DCHECK(thread_checker_.CalledOnValidThread());
124 capture_scheduler_.OnCaptureCompleted();
126 // 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,
131 base::Bind(&EncodeFrame, encoder_.get(),
132 base::Passed(make_scoped_ptr(frame))),
133 base::Bind(&VideoFramePump::SendEncodedFrame, weak_factory_.GetWeakPtr(),
134 latest_event_timestamp_, base::TimeTicks::Now()));
137 void VideoFramePump::CaptureNextFrame() {
138 DCHECK(thread_checker_.CalledOnValidThread());
140 capturer_->Capture(webrtc::DesktopRegion());
143 void VideoFramePump::SendEncodedFrame(int64 latest_event_timestamp,
144 base::TimeTicks timestamp,
145 scoped_ptr<VideoPacket> packet) {
146 DCHECK(thread_checker_.CalledOnValidThread());
148 if (g_enable_timestamps)
149 packet->set_timestamp(timestamp.ToInternalValue());
151 packet->set_latest_event_timestamp(latest_event_timestamp);
153 capture_scheduler_.OnFrameEncoded(packet.get());
155 video_stub_->ProcessVideoPacket(packet.Pass(),
156 base::Bind(&VideoFramePump::OnVideoPacketSent,
157 weak_factory_.GetWeakPtr()));
160 void VideoFramePump::OnVideoPacketSent() {
161 DCHECK(thread_checker_.CalledOnValidThread());
163 capture_scheduler_.OnFrameSent();
164 keep_alive_timer_.Reset();
167 void VideoFramePump::SendKeepAlivePacket() {
168 DCHECK(thread_checker_.CalledOnValidThread());
170 video_stub_->ProcessVideoPacket(
171 make_scoped_ptr(new VideoPacket()),
172 base::Bind(&VideoFramePump::OnKeepAlivePacketSent,
173 weak_factory_.GetWeakPtr()));
176 void VideoFramePump::OnKeepAlivePacketSent() {
177 DCHECK(thread_checker_.CalledOnValidThread());
179 keep_alive_timer_.Reset();
182 } // namespace remoting