Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: remoting/host/video_frame_pump.cc

Issue 1462063004: Move VideoFramePump to remoting/protocol (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « remoting/host/video_frame_pump.h ('k') | remoting/host/video_frame_pump_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "remoting/host/video_frame_pump.h"
6
7 #include <algorithm>
8
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"
20
21 namespace remoting {
22
23 // Interval between empty keep-alive frames. These frames are sent only when the
24 // stream is paused or inactive for some other reason (e.g. when blocked on
25 // capturer). To prevent PseudoTCP from resetting congestion window this value
26 // must be smaller than the minimum RTO used in PseudoTCP, which is 250ms.
27 static const int kKeepAlivePacketIntervalMs = 200;
28
29 static bool g_enable_timestamps = false;
30
31 VideoFramePump::FrameTimestamps::FrameTimestamps() {}
32 VideoFramePump::FrameTimestamps::~FrameTimestamps() {}
33
34 VideoFramePump::PacketWithTimestamps::PacketWithTimestamps(
35 scoped_ptr<VideoPacket> packet,
36 scoped_ptr<FrameTimestamps> timestamps)
37 : packet(packet.Pass()), timestamps(timestamps.Pass()) {}
38
39 VideoFramePump::PacketWithTimestamps::~PacketWithTimestamps() {}
40
41 // static
42 void VideoFramePump::EnableTimestampsForTests() {
43 g_enable_timestamps = true;
44 }
45
46 VideoFramePump::VideoFramePump(
47 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
48 scoped_ptr<webrtc::DesktopCapturer> capturer,
49 scoped_ptr<VideoEncoder> encoder,
50 protocol::VideoStub* video_stub)
51 : encode_task_runner_(encode_task_runner),
52 capturer_(capturer.Pass()),
53 encoder_(encoder.Pass()),
54 video_stub_(video_stub),
55 keep_alive_timer_(
56 FROM_HERE,
57 base::TimeDelta::FromMilliseconds(kKeepAlivePacketIntervalMs),
58 base::Bind(&VideoFramePump::SendKeepAlivePacket,
59 base::Unretained(this)),
60 false),
61 capture_scheduler_(base::Bind(&VideoFramePump::CaptureNextFrame,
62 base::Unretained(this))),
63 weak_factory_(this) {
64 DCHECK(encoder_);
65 DCHECK(video_stub_);
66
67 capturer_->Start(this);
68 capture_scheduler_.Start();
69 }
70
71 VideoFramePump::~VideoFramePump() {
72 encode_task_runner_->DeleteSoon(FROM_HERE, encoder_.release());
73 }
74
75 void VideoFramePump::Pause(bool pause) {
76 DCHECK(thread_checker_.CalledOnValidThread());
77
78 capture_scheduler_.Pause(pause);
79 }
80
81 void VideoFramePump::OnInputEventReceived(int64_t event_timestamp) {
82 DCHECK(thread_checker_.CalledOnValidThread());
83
84 if (!next_frame_timestamps_)
85 next_frame_timestamps_.reset(new FrameTimestamps());
86 next_frame_timestamps_->input_event_client_timestamp = event_timestamp;
87 next_frame_timestamps_->input_event_received_time = base::TimeTicks::Now();
88 }
89
90 void VideoFramePump::SetLosslessEncode(bool want_lossless) {
91 DCHECK(thread_checker_.CalledOnValidThread());
92
93 encode_task_runner_->PostTask(
94 FROM_HERE, base::Bind(&VideoEncoder::SetLosslessEncode,
95 base::Unretained(encoder_.get()), want_lossless));
96 }
97
98 void VideoFramePump::SetLosslessColor(bool want_lossless) {
99 DCHECK(thread_checker_.CalledOnValidThread());
100
101 encode_task_runner_->PostTask(
102 FROM_HERE, base::Bind(&VideoEncoder::SetLosslessColor,
103 base::Unretained(encoder_.get()), want_lossless));
104 }
105
106 webrtc::SharedMemory* VideoFramePump::CreateSharedMemory(size_t size) {
107 DCHECK(thread_checker_.CalledOnValidThread());
108 return nullptr;
109 }
110
111 void VideoFramePump::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
112 DCHECK(thread_checker_.CalledOnValidThread());
113
114 capture_scheduler_.OnCaptureCompleted();
115
116 captured_frame_timestamps_->capture_ended_time = base::TimeTicks::Now();
117
118 // Even when |frame| is nullptr we still need to post it to the encode thread
119 // to make sure frames are freed in the same order they are received and
120 // that we don't start capturing frame n+2 before frame n is freed.
121 base::PostTaskAndReplyWithResult(
122 encode_task_runner_.get(), FROM_HERE,
123 base::Bind(&VideoFramePump::EncodeFrame, encoder_.get(),
124 base::Passed(make_scoped_ptr(frame)),
125 base::Passed(&captured_frame_timestamps_)),
126 base::Bind(&VideoFramePump::OnFrameEncoded, weak_factory_.GetWeakPtr()));
127 }
128
129 void VideoFramePump::CaptureNextFrame() {
130 DCHECK(thread_checker_.CalledOnValidThread());
131
132 // |next_frame_timestamps_| is not set if no input events were received since
133 // the previous frame. In that case create FrameTimestamps instance without
134 // setting |input_event_client_timestamp| and |input_event_received_time|.
135 if (!next_frame_timestamps_)
136 next_frame_timestamps_.reset(new FrameTimestamps());
137
138 captured_frame_timestamps_ = next_frame_timestamps_.Pass();
139 captured_frame_timestamps_->capture_started_time = base::TimeTicks::Now();
140
141 capturer_->Capture(webrtc::DesktopRegion());
142 }
143
144 // static
145 scoped_ptr<VideoFramePump::PacketWithTimestamps> VideoFramePump::EncodeFrame(
146 VideoEncoder* encoder,
147 scoped_ptr<webrtc::DesktopFrame> frame,
148 scoped_ptr<FrameTimestamps> timestamps) {
149 timestamps->encode_started_time = base::TimeTicks::Now();
150
151 scoped_ptr<VideoPacket> packet;
152 // If |frame| is non-NULL then let the encoder process it.
153 if (frame)
154 packet = encoder->Encode(*frame);
155
156 // If |frame| is NULL, or the encoder returned nothing, return an empty
157 // packet.
158 if (!packet)
159 packet.reset(new VideoPacket());
160
161 if (frame)
162 packet->set_capture_time_ms(frame->capture_time_ms());
163
164 timestamps->encode_ended_time = base::TimeTicks::Now();
165 packet->set_encode_time_ms(
166 (timestamps->encode_ended_time - timestamps->encode_started_time)
167 .InMilliseconds());
168
169 return make_scoped_ptr(
170 new PacketWithTimestamps(packet.Pass(), timestamps.Pass()));
171 }
172
173 void VideoFramePump::OnFrameEncoded(scoped_ptr<PacketWithTimestamps> packet) {
174 DCHECK(thread_checker_.CalledOnValidThread());
175
176 capture_scheduler_.OnFrameEncoded(packet->packet.get());
177
178 if (send_pending_) {
179 pending_packets_.push_back(packet.Pass());
180 } else {
181 SendPacket(packet.Pass());
182 }
183 }
184
185 void VideoFramePump::SendPacket(scoped_ptr<PacketWithTimestamps> packet) {
186 DCHECK(thread_checker_.CalledOnValidThread());
187 DCHECK(!send_pending_);
188
189 packet->timestamps->can_send_time = base::TimeTicks::Now();
190 UpdateFrameTimers(packet->packet.get(), packet->timestamps.get());
191
192 send_pending_ = true;
193 video_stub_->ProcessVideoPacket(packet->packet.Pass(),
194 base::Bind(&VideoFramePump::OnVideoPacketSent,
195 weak_factory_.GetWeakPtr()));
196 }
197
198 void VideoFramePump::UpdateFrameTimers(VideoPacket* packet,
199 FrameTimestamps* timestamps) {
200 if (g_enable_timestamps)
201 packet->set_timestamp(timestamps->capture_ended_time.ToInternalValue());
202
203
204 if (!timestamps->input_event_received_time.is_null()) {
205 packet->set_capture_pending_time_ms((timestamps->capture_started_time -
206 timestamps->input_event_received_time)
207 .InMilliseconds());
208 packet->set_latest_event_timestamp(
209 timestamps->input_event_client_timestamp);
210 }
211
212 packet->set_capture_overhead_time_ms(
213 (timestamps->capture_ended_time - timestamps->capture_started_time)
214 .InMilliseconds() -
215 packet->capture_time_ms());
216
217 packet->set_encode_pending_time_ms(
218 (timestamps->encode_started_time - timestamps->capture_ended_time)
219 .InMilliseconds());
220
221 packet->set_send_pending_time_ms(
222 (timestamps->can_send_time - timestamps->encode_ended_time)
223 .InMilliseconds());
224 }
225
226 void VideoFramePump::OnVideoPacketSent() {
227 DCHECK(thread_checker_.CalledOnValidThread());
228
229 send_pending_ = false;
230 capture_scheduler_.OnFrameSent();
231 keep_alive_timer_.Reset();
232
233 // Send next packet if any.
234 if (!pending_packets_.empty()) {
235 scoped_ptr<PacketWithTimestamps> next(pending_packets_.front());
236 pending_packets_.weak_erase(pending_packets_.begin());
237 SendPacket(next.Pass());
238 }
239 }
240
241 void VideoFramePump::SendKeepAlivePacket() {
242 DCHECK(thread_checker_.CalledOnValidThread());
243
244 video_stub_->ProcessVideoPacket(
245 make_scoped_ptr(new VideoPacket()),
246 base::Bind(&VideoFramePump::OnKeepAlivePacketSent,
247 weak_factory_.GetWeakPtr()));
248 }
249
250 void VideoFramePump::OnKeepAlivePacketSent() {
251 DCHECK(thread_checker_.CalledOnValidThread());
252
253 keep_alive_timer_.Reset();
254 }
255
256 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/video_frame_pump.h ('k') | remoting/host/video_frame_pump_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698