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

Side by Side Diff: remoting/protocol/webrtc_frame_scheduler.cc

Issue 1846893002: Interface with webrtc through encoded frames (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed sergey comment Created 4 years, 8 months 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/protocol/webrtc_frame_scheduler.h ('k') | remoting/protocol/webrtc_transport.h » ('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 2016 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/protocol/webrtc_frame_scheduler.h"
6
7 #include <memory>
8
9 #include "base/logging.h"
10 #include "remoting/base/constants.h"
11 #include "remoting/proto/video.pb.h"
12
13 namespace remoting {
14 namespace protocol {
15
16 // The frame scheduler currently uses a simple polling technique
17 // at 30 FPS to capture, encode and send frames over webrtc transport.
18 // An improved solution will use target bitrate feedback to pace out
19 // the capture rate.
20 WebRtcFrameScheduler::WebRtcFrameScheduler(
21 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
22 std::unique_ptr<webrtc::DesktopCapturer> capturer,
23 WebrtcTransport* webrtc_transport,
24 std::unique_ptr<VideoEncoder> encoder)
25 : encode_task_runner_(encode_task_runner),
26 capturer_(std::move(capturer)),
27 webrtc_transport_(webrtc_transport),
28 encoder_(std::move(encoder)),
29 weak_factory_(this) {
30 DCHECK(encode_task_runner_);
31 DCHECK(capturer_);
32 DCHECK(webrtc_transport_);
33 DCHECK(encoder_);
34 // Does not really start anything. Registers callback on this class.
35 capturer_->Start(this);
36 capture_timer_.reset(new base::RepeatingTimer());
37 }
38
39 WebRtcFrameScheduler::~WebRtcFrameScheduler() {
40 encode_task_runner_->DeleteSoon(FROM_HERE, encoder_.release());
41 }
42
43 void WebRtcFrameScheduler::Start() {
44 // Register for PLI requests.
45 webrtc_transport_->video_encoder_factory()->SetKeyFrameRequestCallback(
46 base::Bind(&WebRtcFrameScheduler::SetKeyFrameRequest,
47 base::Unretained(this)));
48 capture_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(1) / 30, this,
49 &WebRtcFrameScheduler::CaptureNextFrame);
50 }
51
52 void WebRtcFrameScheduler::Stop() {
53 // Clear PLI request callback.
54 webrtc_transport_->video_encoder_factory()->SetKeyFrameRequestCallback(
55 base::Closure());
56 // Cancel any pending encode.
57 task_tracker_.TryCancelAll();
58 capture_timer_->Stop();
59 }
60
61 void WebRtcFrameScheduler::Pause(bool pause) {
62 if (pause) {
63 Stop();
64 } else {
65 Start();
66 }
67 }
68
69 void WebRtcFrameScheduler::SetSizeCallback(
70 const VideoStream::SizeCallback& callback) {
71 size_callback_ = callback;
72 }
73
74 void WebRtcFrameScheduler::SetKeyFrameRequest() {
75 VLOG(1) << "Request key frame";
76 base::AutoLock lock(lock_);
77 key_frame_request_ = true;
78 }
79
80 bool WebRtcFrameScheduler::ClearAndGetKeyFrameRequest() {
81 base::AutoLock lock(lock_);
82 bool key_frame_request = key_frame_request_;
83 key_frame_request_ = false;
84 return key_frame_request;
85 }
86
87 webrtc::SharedMemory* WebRtcFrameScheduler::CreateSharedMemory(size_t size) {
88 DCHECK(thread_checker_.CalledOnValidThread());
89 return nullptr;
90 }
91
92 void WebRtcFrameScheduler::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
93 DCHECK(thread_checker_.CalledOnValidThread());
94
95 VLOG(1) << "Capture overhead "
96 << (base::TimeTicks::Now() - last_capture_ticks_).InMilliseconds();
97 capture_pending_ = false;
98
99 std::unique_ptr<webrtc::DesktopFrame> owned_frame(frame);
100
101 if (encode_pending_) {
102 // TODO(isheriff): consider queuing here
103 VLOG(1) << "Dropping captured frame since encoder is still busy";
104 return;
105 }
106 if (!frame || frame->updated_region().is_empty())
107 return;
108
109 webrtc::DesktopVector dpi =
110 frame->dpi().is_zero() ? webrtc::DesktopVector(kDefaultDpi, kDefaultDpi)
111 : frame->dpi();
112
113 if (!frame_size_.equals(frame->size()) || !frame_dpi_.equals(dpi)) {
114 frame_size_ = frame->size();
115 frame_dpi_ = dpi;
116 if (!size_callback_.is_null())
117 size_callback_.Run(frame_size_, frame_dpi_);
118 }
119 encode_pending_ = true;
120 task_tracker_.PostTaskAndReplyWithResult(
121 encode_task_runner_.get(), FROM_HERE,
122 base::Bind(&WebRtcFrameScheduler::EncodeFrame, encoder_.get(),
123 base::Passed(std::move(owned_frame)),
124 ClearAndGetKeyFrameRequest()),
125 base::Bind(&WebRtcFrameScheduler::OnFrameEncoded,
126 weak_factory_.GetWeakPtr()));
127 }
128
129 void WebRtcFrameScheduler::CaptureNextFrame() {
130 DCHECK(thread_checker_.CalledOnValidThread());
131
132 if (capture_pending_ || encode_pending_) {
133 VLOG(1) << "Capture/encode still pending..";
134 return;
135 }
136 capture_pending_ = true;
137 VLOG(1) << "Capture next frame after "
138 << (base::TimeTicks::Now() - last_capture_ticks_).InMilliseconds();
139 last_capture_ticks_ = base::TimeTicks::Now();
140 capturer_->Capture(webrtc::DesktopRegion());
141 }
142
143 // static
144 std::unique_ptr<VideoPacket> WebRtcFrameScheduler::EncodeFrame(
145 VideoEncoder* encoder,
146 std::unique_ptr<webrtc::DesktopFrame> frame,
147 bool key_frame_request) {
148 uint32_t flags = 0;
149 if (key_frame_request)
150 flags |= VideoEncoder::REQUEST_KEY_FRAME;
151
152 base::TimeTicks current = base::TimeTicks::Now();
153 std::unique_ptr<VideoPacket> packet = encoder->Encode(*frame, flags);
154 if (!packet)
155 return nullptr;
156
157 VLOG(1) << "Encode duration "
158 << (base::TimeTicks::Now() - current).InMilliseconds()
159 << " payload size " << packet->data().size();
160 return packet;
161 }
162
163 void WebRtcFrameScheduler::OnFrameEncoded(std::unique_ptr<VideoPacket> packet) {
164 DCHECK(thread_checker_.CalledOnValidThread());
165 encode_pending_ = false;
166 if (!packet)
167 return;
168 int64_t capture_timestamp_ms =
169 (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds();
170 base::TimeTicks current = base::TimeTicks::Now();
171 // TODO(isheriff): Investigate why first frame fails to send at times.
172 // This gets resolved through a PLI request.
173 webrtc_transport_->video_encoder_factory()->SendEncodedFrame(
174 capture_timestamp_ms, std::move(packet));
175
176 VLOG(1) << "Send duration "
177 << (base::TimeTicks::Now() - current).InMilliseconds();
178 }
179
180 } // namespace protocol
181 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/protocol/webrtc_frame_scheduler.h ('k') | remoting/protocol/webrtc_transport.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698