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

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

Powered by Google App Engine
This is Rietveld 408576698