Roll src/third_party/WebKit f36d5e0:68b67cd (svn 193299:193303)
[chromium-blink-merge.git] / remoting / host / video_frame_pump.cc
blob526615c9215c7dad07d90ed84dcca9f7f42dc080
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 // Helper used to encode frames on the encode thread.
27 // TODO(sergeyu): This functions doesn't do much beside calling
28 // VideoEncoder::Encode(). It's only needed to handle empty frames properly and
29 // that logic can be moved to VideoEncoder implementations.
30 scoped_ptr<VideoPacket> EncodeFrame(VideoEncoder* encoder,
31 scoped_ptr<webrtc::DesktopFrame> frame) {
32 // If there is nothing to encode then send an empty packet.
33 if (!frame || frame->updated_region().is_empty())
34 return make_scoped_ptr(new VideoPacket());
36 return encoder->Encode(*frame);
39 } // namespace
41 // Interval between empty keep-alive frames. These frames are sent only when the
42 // stream is paused or inactive for some other reason (e.g. when blocked on
43 // capturer). To prevent PseudoTCP from resetting congestion window this value
44 // must be smaller than the minimum RTO used in PseudoTCP, which is 250ms.
45 static const int kKeepAlivePacketIntervalMs = 200;
47 static bool g_enable_timestamps = false;
49 // static
50 void VideoFramePump::EnableTimestampsForTests() {
51 g_enable_timestamps = true;
54 VideoFramePump::VideoFramePump(
55 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
56 scoped_ptr<webrtc::DesktopCapturer> capturer,
57 scoped_ptr<VideoEncoder> encoder,
58 protocol::VideoStub* video_stub)
59 : encode_task_runner_(encode_task_runner),
60 capturer_(capturer.Pass()),
61 encoder_(encoder.Pass()),
62 video_stub_(video_stub),
63 keep_alive_timer_(
64 FROM_HERE,
65 base::TimeDelta::FromMilliseconds(kKeepAlivePacketIntervalMs),
66 base::Bind(&VideoFramePump::SendKeepAlivePacket,
67 base::Unretained(this)),
68 false),
69 capture_scheduler_(base::Bind(&VideoFramePump::CaptureNextFrame,
70 base::Unretained(this))),
71 latest_event_timestamp_(0),
72 weak_factory_(this) {
73 DCHECK(encoder_);
74 DCHECK(video_stub_);
76 capturer_->Start(this);
77 capture_scheduler_.Start();
80 VideoFramePump::~VideoFramePump() {
81 encode_task_runner_->DeleteSoon(FROM_HERE, encoder_.release());
84 void VideoFramePump::Pause(bool pause) {
85 DCHECK(thread_checker_.CalledOnValidThread());
87 capture_scheduler_.Pause(pause);
90 void VideoFramePump::SetLatestEventTimestamp(int64 latest_event_timestamp) {
91 DCHECK(thread_checker_.CalledOnValidThread());
93 latest_event_timestamp_ = latest_event_timestamp;
96 void VideoFramePump::SetLosslessEncode(bool want_lossless) {
97 DCHECK(thread_checker_.CalledOnValidThread());
99 encode_task_runner_->PostTask(
100 FROM_HERE, base::Bind(&VideoEncoder::SetLosslessEncode,
101 base::Unretained(encoder_.get()), want_lossless));
104 void VideoFramePump::SetLosslessColor(bool want_lossless) {
105 DCHECK(thread_checker_.CalledOnValidThread());
107 encode_task_runner_->PostTask(
108 FROM_HERE, base::Bind(&VideoEncoder::SetLosslessColor,
109 base::Unretained(encoder_.get()), want_lossless));
112 webrtc::SharedMemory* VideoFramePump::CreateSharedMemory(size_t size) {
113 DCHECK(thread_checker_.CalledOnValidThread());
114 return nullptr;
117 void VideoFramePump::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
118 DCHECK(thread_checker_.CalledOnValidThread());
120 capture_scheduler_.OnCaptureCompleted();
122 // Even when |frame| is nullptr we still need to post it to the encode thread
123 // to make sure frames are freed in the same order they are received and
124 // that we don't start capturing frame n+2 before frame n is freed.
125 base::PostTaskAndReplyWithResult(
126 encode_task_runner_.get(), FROM_HERE,
127 base::Bind(&EncodeFrame, encoder_.get(),
128 base::Passed(make_scoped_ptr(frame))),
129 base::Bind(&VideoFramePump::SendEncodedFrame, weak_factory_.GetWeakPtr(),
130 latest_event_timestamp_, base::TimeTicks::Now()));
133 void VideoFramePump::CaptureNextFrame() {
134 DCHECK(thread_checker_.CalledOnValidThread());
136 capturer_->Capture(webrtc::DesktopRegion());
139 void VideoFramePump::SendEncodedFrame(int64 latest_event_timestamp,
140 base::TimeTicks timestamp,
141 scoped_ptr<VideoPacket> packet) {
142 DCHECK(thread_checker_.CalledOnValidThread());
144 if (g_enable_timestamps)
145 packet->set_timestamp(timestamp.ToInternalValue());
147 packet->set_latest_event_timestamp(latest_event_timestamp);
149 capture_scheduler_.OnFrameEncoded(packet.get());
151 video_stub_->ProcessVideoPacket(packet.Pass(),
152 base::Bind(&VideoFramePump::OnVideoPacketSent,
153 weak_factory_.GetWeakPtr()));
156 void VideoFramePump::OnVideoPacketSent() {
157 DCHECK(thread_checker_.CalledOnValidThread());
159 capture_scheduler_.OnFrameSent();
160 keep_alive_timer_.Reset();
163 void VideoFramePump::SendKeepAlivePacket() {
164 DCHECK(thread_checker_.CalledOnValidThread());
166 video_stub_->ProcessVideoPacket(
167 make_scoped_ptr(new VideoPacket()),
168 base::Bind(&VideoFramePump::OnKeepAlivePacketSent,
169 weak_factory_.GetWeakPtr()));
172 void VideoFramePump::OnKeepAlivePacketSent() {
173 DCHECK(thread_checker_.CalledOnValidThread());
175 keep_alive_timer_.Reset();
178 } // namespace remoting