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

Side by Side Diff: chrome/browser/media/native_desktop_media_list.cc

Issue 1808273002: Use DesktopCaptureDeviceAura for all aura windows in Windows and Linux (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 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 | « chrome/browser/media/native_desktop_media_list.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "chrome/browser/media/native_desktop_media_list.h" 5 #include "chrome/browser/media/native_desktop_media_list.h"
6 6
7 #include "base/hash.h" 7 #include "base/hash.h"
8 #include "base/strings/utf_string_conversions.h" 8 #include "base/strings/utf_string_conversions.h"
9 #include "base/threading/sequenced_worker_pool.h" 9 #include "base/threading/sequenced_worker_pool.h"
10 #include "chrome/browser/media/desktop_media_list_observer.h" 10 #include "chrome/browser/media/desktop_media_list_observer.h"
11 #include "chrome/browser/ui/browser.h" 11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/browser_list.h" 12 #include "chrome/browser/ui/browser_list.h"
13 #include "chrome/browser/ui/browser_window.h" 13 #include "chrome/browser/ui/browser_window.h"
14 #include "chrome/grit/generated_resources.h" 14 #include "chrome/grit/generated_resources.h"
15 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
16 #include "media/base/video_util.h" 16 #include "media/base/video_util.h"
17 #include "third_party/libyuv/include/libyuv/scale_argb.h" 17 #include "third_party/libyuv/include/libyuv/scale_argb.h"
18 #include "third_party/skia/include/core/SkBitmap.h" 18 #include "third_party/skia/include/core/SkBitmap.h"
19 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" 19 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
20 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" 20 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
21 #include "third_party/webrtc/modules/desktop_capture/window_capturer.h" 21 #include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
22 #include "ui/aura/window.h" 22 #include "ui/aura/window.h"
23 #include "ui/aura/window_tree_host.h" 23 #include "ui/aura/window_tree_host.h"
24 #include "ui/base/l10n/l10n_util.h" 24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/gfx/native_widget_types.h" 25 #include "ui/gfx/native_widget_types.h"
26 #include "ui/snapshot/snapshot.h" 26 #include "ui/snapshot/snapshot.h"
27 27
28 #if defined(OS_WIN)
29 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
30 #endif
31
32 #if defined(USE_X11) && !defined(OS_CHROMEOS)
33 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
34 #endif
35
28 using content::BrowserThread; 36 using content::BrowserThread;
29 using content::DesktopMediaID; 37 using content::DesktopMediaID;
30 38
31 namespace { 39 namespace {
32 40
33 // Update the list every second. 41 // Update the list every second.
34 const int kDefaultUpdatePeriod = 1000; 42 const int kDefaultUpdatePeriod = 1000;
35 43
36 // Returns a hash of a DesktopFrame content to detect when image for a desktop 44 // Returns a hash of a DesktopFrame content to detect when image for a desktop
37 // media source has changed. 45 // media source has changed.
(...skipping 29 matching lines...) Expand all
67 pixels_data[result.rowBytes() * y + x * result.bytesPerPixel() + 3] = 75 pixels_data[result.rowBytes() * y + x * result.bytesPerPixel() + 3] =
68 0xff; 76 0xff;
69 } 77 }
70 } 78 }
71 79
72 result.unlockPixels(); 80 result.unlockPixels();
73 81
74 return gfx::ImageSkia::CreateFrom1xBitmap(result); 82 return gfx::ImageSkia::CreateFrom1xBitmap(result);
75 } 83 }
76 84
77 #if defined(USE_AURA)
78
79 NativeDesktopMediaList::NativeAuraIdMap GetBrowserNativeAuraIdMap() {
80 NativeDesktopMediaList::NativeAuraIdMap id_map;
81 for (auto* browser : *BrowserList::GetInstance()) {
82 aura::Window* aura_window = browser->window()->GetNativeWindow();
83 if (!aura_window)
84 continue;
85 aura::WindowTreeHost* host = aura_window->GetHost();
86 if (!host)
87 continue;
88 gfx::AcceleratedWidget widget = host->GetAcceleratedWidget();
89 #if defined(OS_WIN)
90 DesktopMediaID::Id native_id = reinterpret_cast<DesktopMediaID::Id>(widget);
91 #else
92 DesktopMediaID::Id native_id = widget;
93 #endif
94 DesktopMediaID media_id = DesktopMediaID::RegisterAuraWindow(
95 DesktopMediaID::TYPE_WINDOW, aura_window);
96 id_map[native_id] = media_id.aura_id;
97 }
98
99 return id_map;
100 }
101
102 #endif // defined(USE_AURA)
103
104 } // namespace 85 } // namespace
105 86
106 class NativeDesktopMediaList::Worker 87 class NativeDesktopMediaList::Worker
107 : public webrtc::DesktopCapturer::Callback { 88 : public webrtc::DesktopCapturer::Callback {
108 public: 89 public:
109 Worker(base::WeakPtr<NativeDesktopMediaList> media_list, 90 Worker(base::WeakPtr<NativeDesktopMediaList> media_list,
110 scoped_ptr<webrtc::ScreenCapturer> screen_capturer, 91 scoped_ptr<webrtc::ScreenCapturer> screen_capturer,
111 scoped_ptr<webrtc::WindowCapturer> window_capturer); 92 scoped_ptr<webrtc::WindowCapturer> window_capturer);
112 ~Worker() override; 93 ~Worker() override;
113 94
114 void Refresh(const gfx::Size& thumbnail_size, 95 void Refresh(const DesktopMediaID::Id& view_dialog_id);
115 const DesktopMediaID::Id& view_dialog_id, 96
116 const NativeAuraIdMap& native_aura_id_map); 97 void UpdateSources(const std::vector<SourceDescription>& sources,
98 const gfx::Size& thumbnail_size);
117 99
118 private: 100 private:
119 typedef std::map<DesktopMediaID, uint32_t> ImageHashesMap; 101 typedef std::map<DesktopMediaID, uint32_t> ImageHashesMap;
120 102
121 // webrtc::DesktopCapturer::Callback interface. 103 // webrtc::DesktopCapturer::Callback interface.
122 void OnCaptureCompleted(webrtc::DesktopFrame* frame) override; 104 void OnCaptureCompleted(webrtc::DesktopFrame* frame) override;
123 105
124 base::WeakPtr<NativeDesktopMediaList> media_list_; 106 base::WeakPtr<NativeDesktopMediaList> media_list_;
125 107
126 scoped_ptr<webrtc::ScreenCapturer> screen_capturer_; 108 scoped_ptr<webrtc::ScreenCapturer> screen_capturer_;
(...skipping 15 matching lines...) Expand all
142 window_capturer_(std::move(window_capturer)) { 124 window_capturer_(std::move(window_capturer)) {
143 if (screen_capturer_) 125 if (screen_capturer_)
144 screen_capturer_->Start(this); 126 screen_capturer_->Start(this);
145 if (window_capturer_) 127 if (window_capturer_)
146 window_capturer_->Start(this); 128 window_capturer_->Start(this);
147 } 129 }
148 130
149 NativeDesktopMediaList::Worker::~Worker() {} 131 NativeDesktopMediaList::Worker::~Worker() {}
150 132
151 void NativeDesktopMediaList::Worker::Refresh( 133 void NativeDesktopMediaList::Worker::Refresh(
152 const gfx::Size& thumbnail_size, 134 const DesktopMediaID::Id& view_dialog_id) {
153 const DesktopMediaID::Id& view_dialog_id,
154 const NativeAuraIdMap& native_aura_id_map) {
155 std::vector<SourceDescription> sources; 135 std::vector<SourceDescription> sources;
156 std::vector<DesktopMediaID> aura_media_ids;
157 136
158 if (screen_capturer_) { 137 if (screen_capturer_) {
159 webrtc::ScreenCapturer::ScreenList screens; 138 webrtc::ScreenCapturer::ScreenList screens;
160 if (screen_capturer_->GetScreenList(&screens)) { 139 if (screen_capturer_->GetScreenList(&screens)) {
161 bool mutiple_screens = screens.size() > 1; 140 bool mutiple_screens = screens.size() > 1;
162 base::string16 title; 141 base::string16 title;
163 for (size_t i = 0; i < screens.size(); ++i) { 142 for (size_t i = 0; i < screens.size(); ++i) {
164 if (mutiple_screens) { 143 if (mutiple_screens) {
165 title = l10n_util::GetStringFUTF16Int( 144 title = l10n_util::GetStringFUTF16Int(
166 IDS_DESKTOP_MEDIA_PICKER_MULTIPLE_SCREEN_NAME, 145 IDS_DESKTOP_MEDIA_PICKER_MULTIPLE_SCREEN_NAME,
167 static_cast<int>(i + 1)); 146 static_cast<int>(i + 1));
168 } else { 147 } else {
169 title = l10n_util::GetStringUTF16( 148 title = l10n_util::GetStringUTF16(
170 IDS_DESKTOP_MEDIA_PICKER_SINGLE_SCREEN_NAME); 149 IDS_DESKTOP_MEDIA_PICKER_SINGLE_SCREEN_NAME);
171 } 150 }
172 sources.push_back(SourceDescription(DesktopMediaID( 151 sources.push_back(SourceDescription(DesktopMediaID(
173 DesktopMediaID::TYPE_SCREEN, screens[i].id), title)); 152 DesktopMediaID::TYPE_SCREEN, screens[i].id), title));
174 } 153 }
175 } 154 }
176 } 155 }
177 156
178 if (window_capturer_) { 157 if (window_capturer_) {
179 webrtc::WindowCapturer::WindowList windows; 158 webrtc::WindowCapturer::WindowList windows;
180 if (window_capturer_->GetWindowList(&windows)) { 159 if (window_capturer_->GetWindowList(&windows)) {
181 for (webrtc::WindowCapturer::WindowList::iterator it = windows.begin(); 160 for (webrtc::WindowCapturer::WindowList::iterator it = windows.begin();
182 it != windows.end(); ++it) { 161 it != windows.end(); ++it) {
183 // Skip the picker dialog window. 162 // Skip the picker dialog window.
184 if (it->id != view_dialog_id) { 163 if (it->id == view_dialog_id)
185 DesktopMediaID media_id(DesktopMediaID::TYPE_WINDOW, it->id); 164 continue;
186 #if defined(USE_AURA) 165
187 // Associate aura id with native id. 166 DesktopMediaID media_id(DesktopMediaID::TYPE_WINDOW, it->id);
188 auto aura_id = native_aura_id_map.find(media_id.id); 167 sources.push_back(
189 if (aura_id != native_aura_id_map.end()) { 168 SourceDescription(media_id, base::UTF8ToUTF16(it->title)));
190 media_id.aura_id = aura_id->second;
191 aura_media_ids.push_back(media_id);
192 }
193 #endif
194 sources.push_back(
195 SourceDescription(media_id, base::UTF8ToUTF16(it->title)));
196 }
197 } 169 }
198 } 170 }
199 } 171 }
200 172
173 // AddAuraIdToMediaId() registers aura windows which needs to be done in UI
174 // thread. It calls Worker::UpdateSources() to complete refresh.
175 BrowserThread::PostTask(
176 BrowserThread::UI, FROM_HERE,
177 base::Bind(&NativeDesktopMediaList::AddAuraIdToMediaId, media_list_,
178 sources));
179 }
180
181 void NativeDesktopMediaList::Worker::UpdateSources(
Sergey Ulanov 2016/03/17 21:59:18 Call this UpdateThumbnails()?
GeorgeZ 2016/03/18 16:44:08 Done.
182 const std::vector<SourceDescription>& sources,
183 const gfx::Size& thumbnail_size) {
201 // Update list of windows before updating thumbnails. 184 // Update list of windows before updating thumbnails.
202 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 185 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
203 base::Bind(&NativeDesktopMediaList::UpdateSourcesList, 186 base::Bind(&NativeDesktopMediaList::UpdateSourcesList,
Sergey Ulanov 2016/03/17 21:59:18 UpdateSources() has been posted from the UI thread
GeorgeZ 2016/03/18 16:44:08 Good suggestion and make code and logic concise.
204 media_list_, sources)); 187 media_list_, sources));
205 188
206 ImageHashesMap new_image_hashes; 189 ImageHashesMap new_image_hashes;
190 std::vector<DesktopMediaID> aura_media_ids;
207 191
208 // Get a thumbnail for each source. 192 // Get a thumbnail for each source.
209 for (size_t i = 0; i < sources.size(); ++i) { 193 for (const auto& source : sources) {
210 SourceDescription& source = sources[i];
211
212 switch (source.id.type) { 194 switch (source.id.type) {
213 case DesktopMediaID::TYPE_SCREEN: 195 case DesktopMediaID::TYPE_SCREEN:
214 if (!screen_capturer_->SelectScreen(source.id.id)) 196 if (!screen_capturer_->SelectScreen(source.id.id))
215 continue; 197 continue;
216 screen_capturer_->Capture(webrtc::DesktopRegion()); 198 screen_capturer_->Capture(webrtc::DesktopRegion());
217 break; 199 break;
218 200
219 case DesktopMediaID::TYPE_WINDOW: 201 case DesktopMediaID::TYPE_WINDOW:
220 #if defined(USE_AURA) 202 #if defined(USE_AURA)
221 // Aura window thumbmail capture is skipped here. It will be done 203 // Aura window thumbmail capture is skipped here. It will be done
222 // asynchronously in the UI thread. 204 // asynchronously in the UI thread.
223 if (source.id.aura_id > DesktopMediaID::kNullId) 205 if (source.id.aura_id > DesktopMediaID::kNullId) {
206 aura_media_ids.push_back(source.id);
224 continue; 207 continue;
208 }
225 #endif 209 #endif
226 if (!window_capturer_->SelectWindow(source.id.id)) 210 if (!window_capturer_->SelectWindow(source.id.id))
227 continue; 211 continue;
228 window_capturer_->Capture(webrtc::DesktopRegion()); 212 window_capturer_->Capture(webrtc::DesktopRegion());
229 break; 213 break;
230 214
231 default: 215 default:
232 NOTREACHED(); 216 NOTREACHED();
233 } 217 }
234 218
235 // Expect that DesktopCapturer to always captures frames synchronously. 219 // Expect that DesktopCapturer to always captures frames synchronously.
236 // |current_frame_| may be NULL if capture failed (e.g. because window has 220 // |current_frame_| may be NULL if capture failed (e.g. because window has
237 // been closed). 221 // been closed).
238 if (current_frame_) { 222 if (current_frame_) {
239 uint32_t frame_hash = GetFrameHash(current_frame_.get()); 223 uint32_t frame_hash = GetFrameHash(current_frame_.get());
240 new_image_hashes[source.id] = frame_hash; 224 new_image_hashes[source.id] = frame_hash;
241 225
242 // Scale the image only if it has changed. 226 // Scale the image only if it has changed.
243 ImageHashesMap::iterator it = image_hashes_.find(source.id); 227 ImageHashesMap::iterator it = image_hashes_.find(source.id);
244 if (it == image_hashes_.end() || it->second != frame_hash) { 228 if (it == image_hashes_.end() || it->second != frame_hash) {
245 gfx::ImageSkia thumbnail = 229 gfx::ImageSkia thumbnail =
246 ScaleDesktopFrame(std::move(current_frame_), thumbnail_size); 230 ScaleDesktopFrame(std::move(current_frame_), thumbnail_size);
247 BrowserThread::PostTask( 231 BrowserThread::PostTask(
248 BrowserThread::UI, FROM_HERE, 232 BrowserThread::UI, FROM_HERE,
249 base::Bind(&NativeDesktopMediaList::OnSourceThumbnailCaptured, 233 base::Bind(&NativeDesktopMediaList::UpdateSourceThumbnail,
250 media_list_, i, thumbnail)); 234 media_list_, source.id, thumbnail));
251 } 235 }
252 } 236 }
253 } 237 }
254 238
255 image_hashes_.swap(new_image_hashes); 239 image_hashes_.swap(new_image_hashes);
256 240
257 // Aura thumbnail captures have to be done in UI thread. After they are done, 241 // Aura thumbnail captures have to be done in UI thread. After they are done,
258 // a refresh will be scheduled. 242 // a refresh will be scheduled.
259 BrowserThread::PostTask( 243 BrowserThread::PostTask(
260 BrowserThread::UI, FROM_HERE, 244 BrowserThread::UI, FROM_HERE,
(...skipping 20 matching lines...) Expand all
281 worker_.reset(new Worker(weak_factory_.GetWeakPtr(), 265 worker_.reset(new Worker(weak_factory_.GetWeakPtr(),
282 std::move(screen_capturer), 266 std::move(screen_capturer),
283 std::move(window_capturer))); 267 std::move(window_capturer)));
284 } 268 }
285 269
286 NativeDesktopMediaList::~NativeDesktopMediaList() { 270 NativeDesktopMediaList::~NativeDesktopMediaList() {
287 capture_task_runner_->DeleteSoon(FROM_HERE, worker_.release()); 271 capture_task_runner_->DeleteSoon(FROM_HERE, worker_.release());
288 } 272 }
289 273
290 void NativeDesktopMediaList::Refresh() { 274 void NativeDesktopMediaList::Refresh() {
291 NativeAuraIdMap native_aura_id_map;
292 #if defined(USE_AURA) 275 #if defined(USE_AURA)
293 native_aura_id_map = GetBrowserNativeAuraIdMap();
294 pending_aura_capture_requests_ = 0; 276 pending_aura_capture_requests_ = 0;
295 new_aura_thumbnail_hashes_.clear(); 277 new_aura_thumbnail_hashes_.clear();
296 #endif 278 #endif
297 279
298 capture_task_runner_->PostTask( 280 capture_task_runner_->PostTask(
299 FROM_HERE, 281 FROM_HERE, base::Bind(&Worker::Refresh, base::Unretained(worker_.get()),
300 base::Bind(&Worker::Refresh, base::Unretained(worker_.get()), 282 view_dialog_id_.id));
301 thumbnail_size_, view_dialog_id_.id, native_aura_id_map));
302 } 283 }
303 284
304 void NativeDesktopMediaList::OnSourceThumbnailCaptured( 285 void NativeDesktopMediaList::AddAuraIdToMediaId(
305 int index, 286 std::vector<SourceDescription> sources) {
306 const gfx::ImageSkia& image) { 287 #if defined(USE_AURA)
307 UpdateSourceThumbnail(GetSource(index).id, image); 288 for (auto& source : sources) {
289 #if defined(OS_WIN)
290 aura::Window* aura_window =
291 views::DesktopWindowTreeHostWin::GetContentWindowForHWND(
292 reinterpret_cast<HWND>(source.id.id));
293 #else
Sergey Ulanov 2016/03/17 21:59:18 // defined(OS_WIN)
GeorgeZ 2016/03/18 16:44:07 Done.
294 // For linux.
295 aura::Window* aura_window =
296 views::DesktopWindowTreeHostX11::GetContentWindowForXID(source.id.id);
297 #endif
Sergey Ulanov 2016/03/17 21:59:18 // !defined(OS_WIN)
GeorgeZ 2016/03/18 16:44:07 Done.
298 // Associate aura id with native id.
299 if (aura_window) {
300 DesktopMediaID aura_id = DesktopMediaID::RegisterAuraWindow(
301 DesktopMediaID::TYPE_WINDOW, aura_window);
302 source.id.aura_id = aura_id.aura_id;
Sergey Ulanov 2016/03/17 21:59:18 Also initiate thumbnail capture here instead of in
GeorgeZ 2016/03/18 16:44:07 I have to schedule next refresh after both aura wi
303 }
304 }
305 #endif
Sergey Ulanov 2016/03/17 21:59:18 // defined(USE_AURA)
GeorgeZ 2016/03/18 16:44:07 Done.
306 capture_task_runner_->PostTask(
307 FROM_HERE,
308 base::Bind(&Worker::UpdateSources, base::Unretained(worker_.get()),
309 sources, thumbnail_size_));
308 } 310 }
309 311
310 void NativeDesktopMediaList::FinishRefreshOnUiThreadAndScheduleNext( 312 void NativeDesktopMediaList::FinishRefreshOnUiThreadAndScheduleNext(
311 const std::vector<DesktopMediaID>& aura_ids) { 313 const std::vector<DesktopMediaID>& aura_ids) {
312 // Schedule a refresh here when there is no aura thumbanil capture or schedule 314 // Schedule a refresh here when there is no aura thumbanil capture or schedule
313 // a refresh in OnAuraThumbnailCaptured() after all aura thumbnails are 315 // a refresh in OnAuraThumbnailCaptured() after all aura thumbnails are
314 // captured. 316 // captured.
315 if (aura_ids.size() == 0) { 317 if (aura_ids.size() == 0) {
316 ScheduleNextRefresh(); 318 ScheduleNextRefresh();
317 return; 319 return;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 // After all aura windows are processed, schedule next refresh; 360 // After all aura windows are processed, schedule next refresh;
359 pending_aura_capture_requests_--; 361 pending_aura_capture_requests_--;
360 DCHECK_GE(pending_aura_capture_requests_, 0); 362 DCHECK_GE(pending_aura_capture_requests_, 0);
361 if (pending_aura_capture_requests_ == 0) { 363 if (pending_aura_capture_requests_ == 0) {
362 previous_aura_thumbnail_hashes_ = std::move(new_aura_thumbnail_hashes_); 364 previous_aura_thumbnail_hashes_ = std::move(new_aura_thumbnail_hashes_);
363 ScheduleNextRefresh(); 365 ScheduleNextRefresh();
364 } 366 }
365 } 367 }
366 368
367 #endif // defined(USE_AURA) 369 #endif // defined(USE_AURA)
OLDNEW
« no previous file with comments | « chrome/browser/media/native_desktop_media_list.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698