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

Side by Side Diff: remoting/protocol/webrtc_video_capturer_adapter.cc

Issue 1574543002: Faster YUV conversion in WebrtcVideoCapturerAdapter. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 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
« no previous file with comments | « remoting/protocol/webrtc_video_capturer_adapter.h ('k') | remoting/remoting.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/protocol/webrtc_video_capturer_adapter.h" 5 #include "remoting/protocol/webrtc_video_capturer_adapter.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h"
10 #include "third_party/libyuv/include/libyuv/convert.h"
9 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" 11 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
10 12
11 namespace remoting { 13 namespace remoting {
14 namespace protocol {
12 15
13 // Number of frames to be captured per second. 16 // Number of frames to be captured per second.
14 const int kFramesPerSec = 30; 17 const int kFramesPerSec = 30;
15 18
16 WebrtcVideoCapturerAdapter::WebrtcVideoCapturerAdapter( 19 WebrtcVideoCapturerAdapter::WebrtcVideoCapturerAdapter(
17 scoped_ptr<webrtc::DesktopCapturer> capturer) 20 scoped_ptr<webrtc::DesktopCapturer> capturer)
18 : desktop_capturer_(std::move(capturer)) { 21 : desktop_capturer_(std::move(capturer)) {
19 DCHECK(desktop_capturer_); 22 DCHECK(desktop_capturer_);
20 23
21 thread_checker_.DetachFromThread();
22
23 // Disable video adaptation since we don't intend to use it. 24 // Disable video adaptation since we don't intend to use it.
24 set_enable_video_adapter(false); 25 set_enable_video_adapter(false);
25 } 26 }
26 27
27 WebrtcVideoCapturerAdapter::~WebrtcVideoCapturerAdapter() { 28 WebrtcVideoCapturerAdapter::~WebrtcVideoCapturerAdapter() {
28 DCHECK(!capture_timer_); 29 DCHECK(!capture_timer_);
29 } 30 }
30 31
31 webrtc::SharedMemory* WebrtcVideoCapturerAdapter::CreateSharedMemory(
32 size_t size) {
33 return nullptr;
34 }
35
36 void WebrtcVideoCapturerAdapter::OnCaptureCompleted(
37 webrtc::DesktopFrame* frame) {
38 scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
39
40 // Drop the owned_frame if there were no changes.
41 if (!owned_frame || owned_frame->updated_region().is_empty()) {
42 owned_frame.reset();
43 return;
44 }
45
46 // Convert the webrtc::DesktopFrame to a cricket::CapturedFrame.
47 cricket::CapturedFrame captured_frame;
48 captured_frame.width = owned_frame->size().width();
49 captured_frame.height = owned_frame->size().height();
50 base::TimeTicks current_time = base::TimeTicks::Now();
51 captured_frame.time_stamp =
52 current_time.ToInternalValue() * base::Time::kNanosecondsPerMicrosecond;
53 captured_frame.data = owned_frame->data();
54
55 // The data_size attribute must be set. If multiple formats are supported,
56 // this should be set appropriately for each one.
57 captured_frame.data_size =
58 (captured_frame.width * webrtc::DesktopFrame::kBytesPerPixel * 8 + 7) /
59 8 * captured_frame.height;
60 captured_frame.fourcc = cricket::FOURCC_ARGB;
61
62 SignalFrameCaptured(this, &captured_frame);
63 }
64
65 bool WebrtcVideoCapturerAdapter::GetBestCaptureFormat( 32 bool WebrtcVideoCapturerAdapter::GetBestCaptureFormat(
66 const cricket::VideoFormat& desired, 33 const cricket::VideoFormat& desired,
67 cricket::VideoFormat* best_format) { 34 cricket::VideoFormat* best_format) {
68 DCHECK(thread_checker_.CalledOnValidThread()); 35 DCHECK(thread_checker_.CalledOnValidThread());
69 36
70 // For now, just used the desired width and height. 37 // The |capture_format| passed to Start() is always ignored, so copy
71 best_format->width = desired.width; 38 // |best_format| to |desired_format|.
72 best_format->height = desired.height; 39 *best_format = desired;
73 best_format->fourcc = cricket::FOURCC_ARGB;
74 best_format->interval = FPS_TO_INTERVAL(kFramesPerSec);
75 return true; 40 return true;
76 } 41 }
77 42
78 cricket::CaptureState WebrtcVideoCapturerAdapter::Start( 43 cricket::CaptureState WebrtcVideoCapturerAdapter::Start(
79 const cricket::VideoFormat& capture_format) { 44 const cricket::VideoFormat& capture_format) {
80 DCHECK(thread_checker_.CalledOnValidThread()); 45 DCHECK(thread_checker_.CalledOnValidThread());
81 DCHECK(!capture_timer_); 46 DCHECK(!capture_timer_);
82 DCHECK_EQ(capture_format.fourcc,
83 (static_cast<uint32_t>(cricket::FOURCC_ARGB)));
84 47
85 if (!desktop_capturer_) { 48 if (!desktop_capturer_) {
86 VLOG(1) << "WebrtcVideoCapturerAdapter failed to start."; 49 VLOG(1) << "WebrtcVideoCapturerAdapter failed to start.";
87 return cricket::CS_FAILED; 50 return cricket::CS_FAILED;
88 } 51 }
89 52
90 // This is required to tell the cricket::VideoCapturer base class what the
91 // capture format will be.
92 SetCaptureFormat(&capture_format);
93
94 desktop_capturer_->Start(this); 53 desktop_capturer_->Start(this);
95 54
96 capture_timer_.reset(new base::RepeatingTimer()); 55 capture_timer_.reset(new base::RepeatingTimer());
97 capture_timer_->Start(FROM_HERE, 56 capture_timer_->Start(FROM_HERE,
98 base::TimeDelta::FromMicroseconds( 57 base::TimeDelta::FromSeconds(1) / kFramesPerSec, this,
99 GetCaptureFormat()->interval /
100 (base::Time::kNanosecondsPerMicrosecond)),
101 this,
102 &WebrtcVideoCapturerAdapter::CaptureNextFrame); 58 &WebrtcVideoCapturerAdapter::CaptureNextFrame);
103 59
104 return cricket::CS_RUNNING; 60 return cricket::CS_RUNNING;
105 } 61 }
106 62
107 // Similar to the base class implementation with some important differences: 63 // Similar to the base class implementation with some important differences:
108 // 1. Does not call either Stop() or Start(), as those would affect the state of 64 // 1. Does not call either Stop() or Start(), as those would affect the state of
109 // |desktop_capturer_|. 65 // |desktop_capturer_|.
110 // 2. Does not support unpausing after stopping the capturer. It is unclear 66 // 2. Does not support unpausing after stopping the capturer. It is unclear
111 // if that flow needs to be supported. 67 // if that flow needs to be supported.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 desktop_capturer_.reset(); 119 desktop_capturer_.reset();
164 120
165 SetCaptureFormat(nullptr); 121 SetCaptureFormat(nullptr);
166 SetCaptureState(cricket::CS_STOPPED); 122 SetCaptureState(cricket::CS_STOPPED);
167 123
168 VLOG(1) << "WebrtcVideoCapturerAdapter stopped."; 124 VLOG(1) << "WebrtcVideoCapturerAdapter stopped.";
169 } 125 }
170 126
171 bool WebrtcVideoCapturerAdapter::IsRunning() { 127 bool WebrtcVideoCapturerAdapter::IsRunning() {
172 DCHECK(thread_checker_.CalledOnValidThread()); 128 DCHECK(thread_checker_.CalledOnValidThread());
173
174 return capture_timer_->IsRunning(); 129 return capture_timer_->IsRunning();
175 } 130 }
176 131
177 bool WebrtcVideoCapturerAdapter::IsScreencast() const { 132 bool WebrtcVideoCapturerAdapter::IsScreencast() const {
178 return true; 133 return true;
179 } 134 }
180 135
181 bool WebrtcVideoCapturerAdapter::GetPreferredFourccs( 136 bool WebrtcVideoCapturerAdapter::GetPreferredFourccs(
182 std::vector<uint32_t>* fourccs) { 137 std::vector<uint32_t>* fourccs) {
138 return false;
139 }
140
141 webrtc::SharedMemory* WebrtcVideoCapturerAdapter::CreateSharedMemory(
142 size_t size) {
143 return nullptr;
144 }
145
146 void WebrtcVideoCapturerAdapter::OnCaptureCompleted(
147 webrtc::DesktopFrame* frame) {
183 DCHECK(thread_checker_.CalledOnValidThread()); 148 DCHECK(thread_checker_.CalledOnValidThread());
184 if (!fourccs) 149
185 return false; 150 DCHECK(capture_pending_);
186 fourccs->push_back(cricket::FOURCC_ARGB); 151 capture_pending_ = false;
187 return true; 152
153 scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
154
155 // Drop the frame if there were no changes.
156 if (!owned_frame || owned_frame->updated_region().is_empty())
157 return;
158
159 size_t width = frame->size().width();
160 size_t height = frame->size().height();
161 if (!yuv_frame_ || yuv_frame_->GetWidth() != width ||
162 yuv_frame_->GetHeight() != height) {
163 scoped_ptr<cricket::WebRtcVideoFrame> webrtc_frame(
164 new cricket::WebRtcVideoFrame());
165 webrtc_frame->InitToEmptyBuffer(width, height, 1, 1, 0);
166 yuv_frame_ = std::move(webrtc_frame);
167
168 // Set updated_region so the whole frame is converted to YUV below.
169 frame->mutable_updated_region()->SetRect(
170 webrtc::DesktopRect::MakeWH(width, height));
171 }
172
173 // TODO(sergeyu): This will copy the buffer if it's being used. Optimize it by
174 // keeping a queue of frames.
175 CHECK(yuv_frame_->MakeExclusive());
176
177 yuv_frame_->SetTimeStamp(base::TimeTicks::Now().ToInternalValue() *
178 base::Time::kNanosecondsPerMicrosecond);
179
180 for (webrtc::DesktopRegion::Iterator i(frame->updated_region()); !i.IsAtEnd();
181 i.Advance()) {
182 int left = i.rect().left();
183 int top = i.rect().top();
184 int width = i.rect().width();
185 int height = i.rect().height();
186
187 if (left % 2 == 1) {
188 --left;
189 ++width;
190 }
191 if (top % 2 == 1) {
192 --top;
193 ++height;
194 }
195 libyuv::ARGBToI420(
196 frame->data() + frame->stride() * top +
197 left * webrtc::DesktopFrame::kBytesPerPixel,
198 frame->stride(),
199 yuv_frame_->GetYPlane() + yuv_frame_->GetYPitch() * top + left,
200 yuv_frame_->GetYPitch(),
201 yuv_frame_->GetUPlane() + yuv_frame_->GetUPitch() * top / 2 + left / 2,
202 yuv_frame_->GetUPitch(),
203 yuv_frame_->GetVPlane() + yuv_frame_->GetVPitch() * top / 2 + left / 2,
204 yuv_frame_->GetVPitch(), width, height);
205 }
206
207 SignalVideoFrame(this, yuv_frame_.get());
188 } 208 }
189 209
190 void WebrtcVideoCapturerAdapter::CaptureNextFrame() { 210 void WebrtcVideoCapturerAdapter::CaptureNextFrame() {
191 // If we are paused, then don't capture. 211 DCHECK(thread_checker_.CalledOnValidThread());
192 if (!IsRunning()) 212
213 if (capture_pending_)
193 return; 214 return;
194 215 capture_pending_ = true;
195 desktop_capturer_->Capture(webrtc::DesktopRegion()); 216 desktop_capturer_->Capture(webrtc::DesktopRegion());
196 } 217 }
197 218
219 } // namespace protocol
198 } // namespace remoting 220 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/protocol/webrtc_video_capturer_adapter.h ('k') | remoting/remoting.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698