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

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: 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 "base/logging.h"
8 #include "remoting/proto/video.pb.h"
9
10 namespace remoting {
11 namespace protocol {
12
13 // The frame scheduler currently uses a simple polling technique
14 // at 30 FPS to capture, encode and send frames over webrtc transport.
15 // An improved solution will use target bitrate feedback to pace out
16 // the capture rate.
17 WebRtcFrameScheduler::WebRtcFrameScheduler(
18 scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner,
19 scoped_ptr<webrtc::DesktopCapturer> capturer,
20 WebrtcTransport* webrtc_transport,
21 scoped_ptr<VideoEncoder> encoder)
22 : key_frame_request_(false),
Sergey Ulanov 2016/03/31 22:06:19 initialize boolean values in the header please.
Irfan 2016/04/05 21:23:27 Done.
23 capture_pending_(false),
24 encode_pending_(false),
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::SetSizeCallback(const SizeCallback& callback) {
60 size_callback_ = callback;
61 }
62
63 void WebRtcFrameScheduler::SetKeyFrameRequest() {
64 VLOG(1) << "Request key frame";
65 base::AutoLock lock(lock_);
66 key_frame_request_ = true;
67 }
68
69 bool WebRtcFrameScheduler::ClearAndGetKeyFrameRequest() {
70 base::AutoLock lock(lock_);
71 bool key_frame_request = key_frame_request_;
72 key_frame_request_ = false;
73 return key_frame_request;
74 }
75
76 webrtc::SharedMemory* WebRtcFrameScheduler::CreateSharedMemory(size_t size) {
77 DCHECK(thread_checker_.CalledOnValidThread());
78 return nullptr;
79 }
80
81 void WebRtcFrameScheduler::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
82 DCHECK(thread_checker_.CalledOnValidThread());
83
84 VLOG(1) << "Capture overhead "
85 << (base::TimeTicks::Now() - last_capture_ticks_).InMilliseconds();
86 capture_pending_ = false;
87
88 scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
89
90 if (encode_pending_) {
91 // TODO(isheriff): consider queuing here
92 VLOG(1) << "Dropping captured frame since encoder is still busy";
93 return;
94 }
95 if (!frame || frame->updated_region().is_empty())
96 return;
97
98 if (!frame_size_.equals(frame->size())) {
99 frame_size_ = frame->size();
100 size_callback_.Run(frame_size_);
101 }
102 encode_pending_ = true;
103 task_tracker_.PostTaskAndReply(
104 encode_task_runner_.get(), FROM_HERE,
105 base::Bind(&WebRtcFrameScheduler::EncodeFrame, base::Unretained(this),
Sergey Ulanov 2016/03/31 22:06:19 I don't think base::Unretained() is safe here. The
Irfan 2016/04/05 21:23:27 Done.
106 base::Passed(std::move(owned_frame))),
107 base::Bind(&WebRtcFrameScheduler::OnFrameEncoded,
108 weak_factory_.GetWeakPtr()));
109 }
110
111 void WebRtcFrameScheduler::CaptureNextFrame() {
112 DCHECK(thread_checker_.CalledOnValidThread());
113
114 if (capture_pending_ || encode_pending_) {
115 VLOG(1) << "Capture/encode still pending..";
116 return;
117 }
118 capture_pending_ = true;
119 VLOG(1) << "Capture next frame after "
120 << (base::TimeTicks::Now() - last_capture_ticks_).InMilliseconds();
121 last_capture_ticks_ = base::TimeTicks::Now();
122 capturer_->Capture(webrtc::DesktopRegion());
123 }
124
125 void WebRtcFrameScheduler::EncodeFrame(scoped_ptr<webrtc::DesktopFrame> frame) {
126 base::TimeTicks current = base::TimeTicks::Now();
127 uint32_t flags = 0;
128 if (ClearAndGetKeyFrameRequest())
129 flags |= VideoEncoder::kRequestKeyFrame;
130
131 scoped_ptr<VideoPacket> packet = encoder_->Encode(*frame, flags);
132 if (!packet) {
Sergey Ulanov 2016/03/31 22:06:19 nit: remove brackets for consistency with other si
Irfan 2016/04/05 21:23:27 Done.
133 return;
134 }
135 VLOG(1) << "Encode duration "
136 << (base::TimeTicks::Now() - current).InMilliseconds()
137 << " payload size " << packet->data().size();
138 int64_t capture_timestamp_ms =
139 (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds();
140 current = base::TimeTicks::Now();
141
142 // TODO(isheriff): Investigate why first frame fails to send at times.
143 // This gets resolved through a PLI request.
144 webrtc_transport_->video_encoder_factory()->SendEncodedFrame(
145 capture_timestamp_ms,
146 reinterpret_cast<uint8_t*>(const_cast<char*>(packet->data().data())),
147 packet->data().size(), packet->format().screen_width(),
148 packet->format().screen_height(), packet->key_frame());
149 VLOG(1) << "Send duration "
150 << (base::TimeTicks::Now() - current).InMilliseconds();
151 }
152
153 void WebRtcFrameScheduler::OnFrameEncoded() {
154 DCHECK(thread_checker_.CalledOnValidThread());
155 encode_pending_ = false;
156 }
157
158 } // namespace protocol
159 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698