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

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

Powered by Google App Engine
This is Rietveld 408576698