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

Side by Side Diff: remoting/protocol/webrtc_video_capturer_adapter.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 2015 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_video_capturer_adapter.h"
6
7 #include <utility>
8
9 #include "remoting/base/constants.h"
10 #include "third_party/libyuv/include/libyuv/convert.h"
11 #include "third_party/webrtc/media/engine/webrtcvideoframe.h"
12 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
13
14 namespace remoting {
15 namespace protocol {
16
17 // Number of frames to be captured per second.
18 const int kFramesPerSec = 30;
19
20 WebrtcVideoCapturerAdapter::WebrtcVideoCapturerAdapter(
21 std::unique_ptr<webrtc::DesktopCapturer> capturer)
22 : desktop_capturer_(std::move(capturer)), weak_factory_(this) {
23 DCHECK(desktop_capturer_);
24
25 // Disable video adaptation since we don't intend to use it.
26 set_enable_video_adapter(false);
27 }
28
29 WebrtcVideoCapturerAdapter::~WebrtcVideoCapturerAdapter() {
30 DCHECK(!capture_timer_);
31 }
32
33 void WebrtcVideoCapturerAdapter::SetSizeCallback(
34 const VideoStream::SizeCallback& size_callback) {
35 DCHECK(thread_checker_.CalledOnValidThread());
36 size_callback_ = size_callback;
37 }
38
39 base::WeakPtr<WebrtcVideoCapturerAdapter>
40 WebrtcVideoCapturerAdapter::GetWeakPtr() {
41 return weak_factory_.GetWeakPtr();
42 }
43
44 bool WebrtcVideoCapturerAdapter::GetBestCaptureFormat(
45 const cricket::VideoFormat& desired,
46 cricket::VideoFormat* best_format) {
47 DCHECK(thread_checker_.CalledOnValidThread());
48
49 // The |capture_format| passed to Start() is always ignored, so copy
50 // |best_format| to |desired_format|.
51 *best_format = desired;
52 return true;
53 }
54
55 cricket::CaptureState WebrtcVideoCapturerAdapter::Start(
56 const cricket::VideoFormat& capture_format) {
57 DCHECK(thread_checker_.CalledOnValidThread());
58 DCHECK(!capture_timer_);
59
60 if (!desktop_capturer_) {
61 VLOG(1) << "WebrtcVideoCapturerAdapter failed to start.";
62 return cricket::CS_FAILED;
63 }
64
65 desktop_capturer_->Start(this);
66
67 capture_timer_.reset(new base::RepeatingTimer());
68 capture_timer_->Start(FROM_HERE,
69 base::TimeDelta::FromSeconds(1) / kFramesPerSec, this,
70 &WebrtcVideoCapturerAdapter::CaptureNextFrame);
71
72 return cricket::CS_RUNNING;
73 }
74
75 bool WebrtcVideoCapturerAdapter::PauseCapturer(bool pause) {
76 DCHECK(thread_checker_.CalledOnValidThread());
77
78 if (pause) {
79 if (paused_)
80 return true;
81
82 bool running = capture_state() == cricket::CS_STARTING ||
83 capture_state() == cricket::CS_RUNNING;
84
85 DCHECK_EQ(running, IsRunning());
86
87 if (!running) {
88 LOG(ERROR)
89 << "Cannot pause WebrtcVideoCapturerAdapter.";
90 return false;
91 }
92
93 capture_timer_->Stop();
94 paused_ = true;
95
96 VLOG(1) << "WebrtcVideoCapturerAdapter paused.";
97
98 return true;
99 } else { // Unpausing.
100 if (!paused_ || !GetCaptureFormat() || !capture_timer_) {
101 LOG(ERROR) << "Cannot unpause WebrtcVideoCapturerAdapter.";
102 return false;
103 }
104
105 capture_timer_->Start(FROM_HERE,
106 base::TimeDelta::FromMicroseconds(
107 GetCaptureFormat()->interval /
108 (base::Time::kNanosecondsPerMicrosecond)),
109 this,
110 &WebrtcVideoCapturerAdapter::CaptureNextFrame);
111 paused_ = false;
112
113 VLOG(1) << "WebrtcVideoCapturerAdapter unpaused.";
114 }
115 return true;
116 }
117
118 void WebrtcVideoCapturerAdapter::Stop() {
119 DCHECK(thread_checker_.CalledOnValidThread());
120 DCHECK_NE(capture_state(), cricket::CS_STOPPED);
121
122 capture_timer_.reset();
123 desktop_capturer_.reset();
124
125 SetCaptureFormat(nullptr);
126 SetCaptureState(cricket::CS_STOPPED);
127
128 VLOG(1) << "WebrtcVideoCapturerAdapter stopped.";
129 }
130
131 bool WebrtcVideoCapturerAdapter::IsRunning() {
132 DCHECK(thread_checker_.CalledOnValidThread());
133 return capture_timer_->IsRunning();
134 }
135
136 bool WebrtcVideoCapturerAdapter::IsScreencast() const {
137 return true;
138 }
139
140 bool WebrtcVideoCapturerAdapter::GetPreferredFourccs(
141 std::vector<uint32_t>* fourccs) {
142 return false;
143 }
144
145 webrtc::SharedMemory* WebrtcVideoCapturerAdapter::CreateSharedMemory(
146 size_t size) {
147 return nullptr;
148 }
149
150 void WebrtcVideoCapturerAdapter::OnCaptureCompleted(
151 webrtc::DesktopFrame* frame) {
152 DCHECK(thread_checker_.CalledOnValidThread());
153
154 DCHECK(capture_pending_);
155 capture_pending_ = false;
156
157 if (!frame)
158 return;
159
160 std::unique_ptr<webrtc::DesktopFrame> owned_frame(frame);
161
162 // TODO(sergeyu): Currently the adapter keeps generating frames even when
163 // nothing is changing on the screen. This is necessary because the video
164 // sender drops frames. Obviously this is a suboptimal. The sending code in
165 // WebRTC needs to have some mechanism to notify when the bandwidth is
166 // exceeded, so the capturer can adapt frame rate.
167
168 webrtc::DesktopVector dpi =
169 frame->dpi().is_zero() ? webrtc::DesktopVector(kDefaultDpi, kDefaultDpi)
170 : frame->dpi();
171 if (!frame_size_.equals(frame->size()) || !frame_dpi_.equals(dpi)) {
172 frame_size_ = frame->size();
173 frame_dpi_ = dpi;
174 if (!size_callback_.is_null())
175 size_callback_.Run(frame_size_, frame_dpi_);
176 }
177
178 if (!yuv_frame_ ||
179 !frame_size_.equals(
180 webrtc::DesktopSize(yuv_frame_->width(), yuv_frame_->height()))) {
181 yuv_frame_ = new rtc::RefCountedObject<webrtc::I420Buffer>(
182 frame_size_.width(), frame_size_.height());
183 // Set updated_region so the whole frame is converted to YUV below.
184 frame->mutable_updated_region()->SetRect(
185 webrtc::DesktopRect::MakeSize(frame_size_));
186 }
187
188 if (!yuv_frame_->HasOneRef()) {
189 // Frame is still used, typically by the encoder. We have to make
190 // a copy before modifying it.
191 // TODO(sergeyu): This will copy the buffer if it's being used.
192 // Optimize it by keeping a queue of frames.
193 yuv_frame_ = webrtc::I420Buffer::Copy(yuv_frame_);
194 }
195
196 for (webrtc::DesktopRegion::Iterator i(frame->updated_region()); !i.IsAtEnd();
197 i.Advance()) {
198 int left = i.rect().left();
199 int top = i.rect().top();
200 int width = i.rect().width();
201 int height = i.rect().height();
202
203 if (left % 2 == 1) {
204 --left;
205 ++width;
206 }
207 if (top % 2 == 1) {
208 --top;
209 ++height;
210 }
211
212 int y_stride = yuv_frame_->stride(webrtc::kYPlane);
213 int u_stride = yuv_frame_->stride(webrtc::kUPlane);
214 int v_stride = yuv_frame_->stride(webrtc::kVPlane);
215 libyuv::ARGBToI420(
216 frame->data() + frame->stride() * top +
217 left * webrtc::DesktopFrame::kBytesPerPixel,
218 frame->stride(),
219 yuv_frame_->MutableData(webrtc::kYPlane) + y_stride * top + left,
220 y_stride, yuv_frame_->MutableData(webrtc::kUPlane) +
221 u_stride * top / 2 + left / 2,
222 u_stride, yuv_frame_->MutableData(webrtc::kVPlane) +
223 v_stride * top / 2 + left / 2,
224 v_stride, width, height);
225 }
226
227 cricket::WebRtcVideoFrame video_frame(
228 yuv_frame_, (base::TimeTicks::Now() - base::TimeTicks()) /
229 base::TimeDelta::FromMicroseconds(1) * 1000,
230 webrtc::kVideoRotation_0);
231
232 OnFrame(this, &video_frame);
233 }
234
235 void WebrtcVideoCapturerAdapter::CaptureNextFrame() {
236 DCHECK(thread_checker_.CalledOnValidThread());
237
238 if (capture_pending_)
239 return;
240 capture_pending_ = true;
241 desktop_capturer_->Capture(webrtc::DesktopRegion());
242 }
243
244 } // namespace protocol
245 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698