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

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: Address unit test failures due to race 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
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()->ClearKeyFrameRequestCallback();
55 // Cancel any pending encode.
56 task_tracker_.TryCancelAll();
57 capture_timer_->Stop();
58 }
59
60 void WebRtcFrameScheduler::Pause(bool pause) {
61 if (pause) {
62 Stop();
63 } else {
64 Start();
65 }
66 }
67
68 void WebRtcFrameScheduler::SetSizeCallback(
69 const VideoStream::SizeCallback& callback) {
70 size_callback_ = callback;
71 }
72
73 void WebRtcFrameScheduler::SetKeyFrameRequest() {
74 VLOG(1) << "Request key frame";
75 base::AutoLock lock(lock_);
76 key_frame_request_ = true;
77 }
78
79 bool WebRtcFrameScheduler::ClearAndGetKeyFrameRequest() {
80 base::AutoLock lock(lock_);
81 bool key_frame_request = key_frame_request_;
82 key_frame_request_ = false;
83 return key_frame_request;
84 }
85
86 webrtc::SharedMemory* WebRtcFrameScheduler::CreateSharedMemory(size_t size) {
87 DCHECK(thread_checker_.CalledOnValidThread());
88 return nullptr;
89 }
90
91 void WebRtcFrameScheduler::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
92 DCHECK(thread_checker_.CalledOnValidThread());
93
94 VLOG(1) << "Capture overhead "
95 << (base::TimeTicks::Now() - last_capture_ticks_).InMilliseconds();
96 capture_pending_ = false;
97
98 std::unique_ptr<webrtc::DesktopFrame> owned_frame(frame);
99
100 if (encode_pending_) {
101 // TODO(isheriff): consider queuing here
102 VLOG(1) << "Dropping captured frame since encoder is still busy";
103 return;
104 }
105 if (!frame || frame->updated_region().is_empty())
106 return;
107
108 webrtc::DesktopVector dpi =
109 frame->dpi().is_zero() ? webrtc::DesktopVector(kDefaultDpi, kDefaultDpi)
110 : frame->dpi();
111
112 if (!frame_size_.equals(frame->size()) || !frame_dpi_.equals(dpi)) {
113 frame_size_ = frame->size();
114 frame_dpi_ = dpi;
115 if (!size_callback_.is_null())
116 size_callback_.Run(frame_size_, frame_dpi_);
117 }
118 encode_pending_ = true;
119 task_tracker_.PostTaskAndReplyWithResult(
120 encode_task_runner_.get(), FROM_HERE,
121 base::Bind(&WebRtcFrameScheduler::EncodeFrame, encoder_.get(),
122 base::Passed(std::move(owned_frame)),
123 ClearAndGetKeyFrameRequest()),
124 base::Bind(&WebRtcFrameScheduler::OnFrameEncoded,
125 weak_factory_.GetWeakPtr()));
126 }
127
128 void WebRtcFrameScheduler::CaptureNextFrame() {
129 DCHECK(thread_checker_.CalledOnValidThread());
130
131 if (capture_pending_ || encode_pending_) {
132 VLOG(1) << "Capture/encode still pending..";
133 return;
134 }
135 capture_pending_ = true;
136 VLOG(1) << "Capture next frame after "
137 << (base::TimeTicks::Now() - last_capture_ticks_).InMilliseconds();
138 last_capture_ticks_ = base::TimeTicks::Now();
139 capturer_->Capture(webrtc::DesktopRegion());
140 }
141
142 // static
143 std::unique_ptr<VideoPacket> WebRtcFrameScheduler::EncodeFrame(
144 VideoEncoder* encoder,
145 std::unique_ptr<webrtc::DesktopFrame> frame,
146 bool key_frame_request) {
147 uint32_t flags = 0;
148 if (key_frame_request)
149 flags |= VideoEncoder::REQUEST_KEY_FRAME;
150
151 base::TimeTicks current = base::TimeTicks::Now();
152 std::unique_ptr<VideoPacket> packet = encoder->Encode(*frame, flags);
153 if (!packet)
154 return nullptr;
155
156 VLOG(1) << "Encode duration "
157 << (base::TimeTicks::Now() - current).InMilliseconds()
158 << " payload size " << packet->data().size();
159 return packet;
160 }
161
162 void WebRtcFrameScheduler::OnFrameEncoded(std::unique_ptr<VideoPacket> packet) {
163 DCHECK(thread_checker_.CalledOnValidThread());
164 encode_pending_ = false;
165 if (!packet)
166 return;
167 int64_t capture_timestamp_ms =
168 (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds();
169 base::TimeTicks current = base::TimeTicks::Now();
170 // TODO(isheriff): Investigate why first frame fails to send at times.
171 // This gets resolved through a PLI request.
172 webrtc_transport_->video_encoder_factory()->SendEncodedFrame(
173 capture_timestamp_ms, std::move(packet));
174
175 VLOG(1) << "Send duration "
176 << (base::TimeTicks::Now() - current).InMilliseconds();
177 }
178
179 } // namespace protocol
180 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698