OLD | NEW |
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/desktop_media_picker_model.h" | 5 #include "chrome/browser/media/desktop_media_picker_model.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/hash.h" | 9 #include "base/hash.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 return gfx::ImageSkia::CreateFrom1xBitmap(result); | 73 return gfx::ImageSkia::CreateFrom1xBitmap(result); |
74 } | 74 } |
75 | 75 |
76 } // namespace | 76 } // namespace |
77 | 77 |
78 DesktopMediaPickerModel::Source::Source(DesktopMediaID id, const string16& name) | 78 DesktopMediaPickerModel::Source::Source(DesktopMediaID id, const string16& name) |
79 : id(id), | 79 : id(id), |
80 name(name) { | 80 name(name) { |
81 } | 81 } |
82 | 82 |
83 DesktopMediaPickerModel::SourceDescription::SourceDescription( | 83 DesktopMediaPickerModelImpl::SourceDescription::SourceDescription( |
84 DesktopMediaID id, | 84 DesktopMediaID id, |
85 const string16& name) | 85 const string16& name) |
86 : id(id), | 86 : id(id), |
87 name(name) { | 87 name(name) { |
88 } | 88 } |
89 | 89 |
90 class DesktopMediaPickerModel::Worker | 90 class DesktopMediaPickerModelImpl::Worker |
91 : public webrtc::DesktopCapturer::Callback { | 91 : public webrtc::DesktopCapturer::Callback { |
92 public: | 92 public: |
93 Worker(base::WeakPtr<DesktopMediaPickerModel> model, | 93 Worker(base::WeakPtr<DesktopMediaPickerModelImpl> model, |
94 scoped_ptr<webrtc::ScreenCapturer> screen_capturer, | 94 scoped_ptr<webrtc::ScreenCapturer> screen_capturer, |
95 scoped_ptr<webrtc::WindowCapturer> window_capturer); | 95 scoped_ptr<webrtc::WindowCapturer> window_capturer); |
96 virtual ~Worker(); | 96 virtual ~Worker(); |
97 | 97 |
98 void Refresh(const gfx::Size& thumbnail_size); | 98 void Refresh(const gfx::Size& thumbnail_size); |
99 | 99 |
100 private: | 100 private: |
101 typedef std::map<DesktopMediaID, uint32> ImageHashesMap; | 101 typedef std::map<DesktopMediaID, uint32> ImageHashesMap; |
102 | 102 |
103 // webrtc::DesktopCapturer::Callback interface. | 103 // webrtc::DesktopCapturer::Callback interface. |
104 virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE; | 104 virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE; |
105 virtual void OnCaptureCompleted(webrtc::DesktopFrame* frame) OVERRIDE; | 105 virtual void OnCaptureCompleted(webrtc::DesktopFrame* frame) OVERRIDE; |
106 | 106 |
107 base::WeakPtr<DesktopMediaPickerModel> model_; | 107 base::WeakPtr<DesktopMediaPickerModelImpl> model_; |
108 | 108 |
109 scoped_ptr<webrtc::ScreenCapturer> screen_capturer_; | 109 scoped_ptr<webrtc::ScreenCapturer> screen_capturer_; |
110 scoped_ptr<webrtc::WindowCapturer> window_capturer_; | 110 scoped_ptr<webrtc::WindowCapturer> window_capturer_; |
111 | 111 |
112 scoped_ptr<webrtc::DesktopFrame> current_frame_; | 112 scoped_ptr<webrtc::DesktopFrame> current_frame_; |
113 | 113 |
114 ImageHashesMap image_hashes_; | 114 ImageHashesMap image_hashes_; |
115 | 115 |
116 DISALLOW_COPY_AND_ASSIGN(Worker); | 116 DISALLOW_COPY_AND_ASSIGN(Worker); |
117 }; | 117 }; |
118 | 118 |
119 DesktopMediaPickerModel::Worker::Worker( | 119 DesktopMediaPickerModelImpl::Worker::Worker( |
120 base::WeakPtr<DesktopMediaPickerModel> model, | 120 base::WeakPtr<DesktopMediaPickerModelImpl> model, |
121 scoped_ptr<webrtc::ScreenCapturer> screen_capturer, | 121 scoped_ptr<webrtc::ScreenCapturer> screen_capturer, |
122 scoped_ptr<webrtc::WindowCapturer> window_capturer) | 122 scoped_ptr<webrtc::WindowCapturer> window_capturer) |
123 : model_(model), | 123 : model_(model), |
124 screen_capturer_(screen_capturer.Pass()), | 124 screen_capturer_(screen_capturer.Pass()), |
125 window_capturer_(window_capturer.Pass()) { | 125 window_capturer_(window_capturer.Pass()) { |
126 if (screen_capturer_) | 126 if (screen_capturer_) |
127 screen_capturer_->Start(this); | 127 screen_capturer_->Start(this); |
128 if (window_capturer_) | 128 if (window_capturer_) |
129 window_capturer_->Start(this); | 129 window_capturer_->Start(this); |
130 } | 130 } |
131 | 131 |
132 DesktopMediaPickerModel::Worker::~Worker() {} | 132 DesktopMediaPickerModelImpl::Worker::~Worker() {} |
133 | 133 |
134 void DesktopMediaPickerModel::Worker::Refresh(const gfx::Size& thumbnail_size) { | 134 void DesktopMediaPickerModelImpl::Worker::Refresh( |
| 135 const gfx::Size& thumbnail_size) { |
135 std::vector<SourceDescription> sources; | 136 std::vector<SourceDescription> sources; |
136 | 137 |
137 if (screen_capturer_) { | 138 if (screen_capturer_) { |
138 // TODO(sergeyu): Enumerate each screen when ScreenCapturer supports it. | 139 // TODO(sergeyu): Enumerate each screen when ScreenCapturer supports it. |
139 sources.push_back(SourceDescription(DesktopMediaID( | 140 sources.push_back(SourceDescription(DesktopMediaID( |
140 DesktopMediaID::TYPE_SCREEN, 0), | 141 DesktopMediaID::TYPE_SCREEN, 0), |
141 l10n_util::GetStringUTF16(IDS_DESKTOP_MEDIA_PICKER_SCREEN_NAME))); | 142 l10n_util::GetStringUTF16(IDS_DESKTOP_MEDIA_PICKER_SCREEN_NAME))); |
142 } | 143 } |
143 | 144 |
144 if (window_capturer_) { | 145 if (window_capturer_) { |
145 webrtc::WindowCapturer::WindowList windows; | 146 webrtc::WindowCapturer::WindowList windows; |
146 if (window_capturer_->GetWindowList(&windows)) { | 147 if (window_capturer_->GetWindowList(&windows)) { |
147 for (webrtc::WindowCapturer::WindowList::iterator it = windows.begin(); | 148 for (webrtc::WindowCapturer::WindowList::iterator it = windows.begin(); |
148 it != windows.end(); ++it) { | 149 it != windows.end(); ++it) { |
149 sources.push_back(SourceDescription( | 150 sources.push_back(SourceDescription( |
150 DesktopMediaID(DesktopMediaID::TYPE_WINDOW, it->id), | 151 DesktopMediaID(DesktopMediaID::TYPE_WINDOW, it->id), |
151 base::UTF8ToUTF16(it->title))); | 152 base::UTF8ToUTF16(it->title))); |
152 } | 153 } |
153 } | 154 } |
154 } | 155 } |
155 | 156 |
156 // Sort the list of sources so that they appear in a predictable order. | 157 // Sort the list of sources so that they appear in a predictable order. |
157 std::sort(sources.begin(), sources.end(), CompareSources); | 158 std::sort(sources.begin(), sources.end(), CompareSources); |
158 | 159 |
159 // Update list of windows before updating thumbnails. | 160 // Update list of windows before updating thumbnails. |
160 BrowserThread::PostTask( | 161 BrowserThread::PostTask( |
161 BrowserThread::UI, FROM_HERE, | 162 BrowserThread::UI, FROM_HERE, |
162 base::Bind(&DesktopMediaPickerModel::OnSourcesList, model_, sources)); | 163 base::Bind(&DesktopMediaPickerModelImpl::OnSourcesList, model_, sources)); |
163 | 164 |
164 ImageHashesMap new_image_hashes; | 165 ImageHashesMap new_image_hashes; |
165 | 166 |
166 // Get a thumbnail for each source. | 167 // Get a thumbnail for each source. |
167 for (size_t i = 0; i < sources.size(); ++i) { | 168 for (size_t i = 0; i < sources.size(); ++i) { |
168 SourceDescription& source = sources[i]; | 169 SourceDescription& source = sources[i]; |
169 switch (source.id.type) { | 170 switch (source.id.type) { |
170 case DesktopMediaID::TYPE_SCREEN: | 171 case DesktopMediaID::TYPE_SCREEN: |
171 screen_capturer_->Capture(webrtc::DesktopRegion()); | 172 screen_capturer_->Capture(webrtc::DesktopRegion()); |
172 DCHECK(current_frame_); | 173 DCHECK(current_frame_); |
(...skipping 16 matching lines...) Expand all Loading... |
189 uint32 frame_hash = GetFrameHash(current_frame_.get()); | 190 uint32 frame_hash = GetFrameHash(current_frame_.get()); |
190 new_image_hashes[source.id] = frame_hash; | 191 new_image_hashes[source.id] = frame_hash; |
191 | 192 |
192 // Scale the image only if it has changed. | 193 // Scale the image only if it has changed. |
193 ImageHashesMap::iterator it = image_hashes_.find(source.id); | 194 ImageHashesMap::iterator it = image_hashes_.find(source.id); |
194 if (it == image_hashes_.end() || it->second != frame_hash) { | 195 if (it == image_hashes_.end() || it->second != frame_hash) { |
195 gfx::ImageSkia thumbnail = | 196 gfx::ImageSkia thumbnail = |
196 ScaleDesktopFrame(current_frame_.Pass(), thumbnail_size); | 197 ScaleDesktopFrame(current_frame_.Pass(), thumbnail_size); |
197 BrowserThread::PostTask( | 198 BrowserThread::PostTask( |
198 BrowserThread::UI, FROM_HERE, | 199 BrowserThread::UI, FROM_HERE, |
199 base::Bind(&DesktopMediaPickerModel::OnSourceThumbnail, model_, | 200 base::Bind(&DesktopMediaPickerModelImpl::OnSourceThumbnail, model_, |
200 i, thumbnail)); | 201 i, thumbnail)); |
201 } | 202 } |
202 } | 203 } |
203 } | 204 } |
204 | 205 |
205 image_hashes_.swap(new_image_hashes); | 206 image_hashes_.swap(new_image_hashes); |
206 | 207 |
207 BrowserThread::PostTask( | 208 BrowserThread::PostTask( |
208 BrowserThread::UI, FROM_HERE, | 209 BrowserThread::UI, FROM_HERE, |
209 base::Bind(&DesktopMediaPickerModel::OnRefreshFinished, model_)); | 210 base::Bind(&DesktopMediaPickerModelImpl::OnRefreshFinished, model_)); |
210 } | 211 } |
211 | 212 |
212 webrtc::SharedMemory* DesktopMediaPickerModel::Worker::CreateSharedMemory( | 213 webrtc::SharedMemory* DesktopMediaPickerModelImpl::Worker::CreateSharedMemory( |
213 size_t size) { | 214 size_t size) { |
214 return NULL; | 215 return NULL; |
215 } | 216 } |
216 | 217 |
217 void DesktopMediaPickerModel::Worker::OnCaptureCompleted( | 218 void DesktopMediaPickerModelImpl::Worker::OnCaptureCompleted( |
218 webrtc::DesktopFrame* frame) { | 219 webrtc::DesktopFrame* frame) { |
219 current_frame_.reset(frame); | 220 current_frame_.reset(frame); |
220 } | 221 } |
221 | 222 |
222 DesktopMediaPickerModel::DesktopMediaPickerModel( | 223 DesktopMediaPickerModelImpl::DesktopMediaPickerModelImpl( |
223 scoped_ptr<webrtc::ScreenCapturer> screen_capturer, | 224 scoped_ptr<webrtc::ScreenCapturer> screen_capturer, |
224 scoped_ptr<webrtc::WindowCapturer> window_capturer) | 225 scoped_ptr<webrtc::WindowCapturer> window_capturer) |
225 : screen_capturer_(screen_capturer.Pass()), | 226 : screen_capturer_(screen_capturer.Pass()), |
226 window_capturer_(window_capturer.Pass()), | 227 window_capturer_(window_capturer.Pass()), |
227 update_period_(base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)), | 228 update_period_(base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)), |
228 thumbnail_size_(100, 100), | 229 thumbnail_size_(100, 100), |
229 observer_(NULL), | 230 observer_(NULL), |
230 weak_factory_(this) { | 231 weak_factory_(this) { |
231 base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool(); | 232 base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool(); |
232 capture_task_runner_ = worker_pool->GetSequencedTaskRunner( | 233 capture_task_runner_ = worker_pool->GetSequencedTaskRunner( |
233 worker_pool->GetSequenceToken()); | 234 worker_pool->GetSequenceToken()); |
234 } | 235 } |
235 | 236 |
236 DesktopMediaPickerModel::~DesktopMediaPickerModel() { | 237 DesktopMediaPickerModelImpl::~DesktopMediaPickerModelImpl() { |
237 capture_task_runner_->DeleteSoon(FROM_HERE, worker_.release()); | 238 capture_task_runner_->DeleteSoon(FROM_HERE, worker_.release()); |
238 } | 239 } |
239 | 240 |
240 void DesktopMediaPickerModel::SetUpdatePeriod(base::TimeDelta period) { | 241 void DesktopMediaPickerModelImpl::SetUpdatePeriod(base::TimeDelta period) { |
241 DCHECK(!observer_); | 242 DCHECK(!observer_); |
242 update_period_ = period; | 243 update_period_ = period; |
243 } | 244 } |
244 | 245 |
245 void DesktopMediaPickerModel::SetThumbnailSize( | 246 void DesktopMediaPickerModelImpl::SetThumbnailSize( |
246 const gfx::Size& thumbnail_size) { | 247 const gfx::Size& thumbnail_size) { |
247 thumbnail_size_ = thumbnail_size; | 248 thumbnail_size_ = thumbnail_size; |
248 } | 249 } |
249 | 250 |
250 void DesktopMediaPickerModel::StartUpdating(Observer* observer) { | 251 void DesktopMediaPickerModelImpl::StartUpdating(Observer* observer) { |
251 DCHECK(!observer_); | 252 DCHECK(!observer_); |
252 DCHECK(screen_capturer_ || window_capturer_); | 253 DCHECK(screen_capturer_ || window_capturer_); |
253 | 254 |
254 observer_ = observer; | 255 observer_ = observer; |
255 | 256 |
256 worker_.reset(new Worker(weak_factory_.GetWeakPtr(), | 257 worker_.reset(new Worker(weak_factory_.GetWeakPtr(), |
257 screen_capturer_.Pass(), window_capturer_.Pass())); | 258 screen_capturer_.Pass(), window_capturer_.Pass())); |
258 Refresh(); | 259 Refresh(); |
259 } | 260 } |
260 | 261 |
| 262 int DesktopMediaPickerModelImpl::source_count() const { |
| 263 return sources_.size(); |
| 264 } |
| 265 |
| 266 const DesktopMediaPickerModel::Source& DesktopMediaPickerModelImpl::source( |
| 267 int index) const { |
| 268 return sources_[index]; |
| 269 } |
| 270 |
261 // static | 271 // static |
262 bool DesktopMediaPickerModel::CompareSources(const SourceDescription& a, | 272 bool DesktopMediaPickerModelImpl::CompareSources(const SourceDescription& a, |
263 const SourceDescription& b) { | 273 const SourceDescription& b) { |
264 return a.id < b.id; | 274 return a.id < b.id; |
265 } | 275 } |
266 | 276 |
267 void DesktopMediaPickerModel::Refresh() { | 277 void DesktopMediaPickerModelImpl::Refresh() { |
268 capture_task_runner_->PostTask( | 278 capture_task_runner_->PostTask( |
269 FROM_HERE, base::Bind(&Worker::Refresh, base::Unretained(worker_.get()), | 279 FROM_HERE, base::Bind(&Worker::Refresh, base::Unretained(worker_.get()), |
270 thumbnail_size_)); | 280 thumbnail_size_)); |
271 } | 281 } |
272 | 282 |
273 void DesktopMediaPickerModel::OnSourcesList( | 283 void DesktopMediaPickerModelImpl::OnSourcesList( |
274 const std::vector<SourceDescription>& new_sources) { | 284 const std::vector<SourceDescription>& new_sources) { |
275 // Step through |new_sources| adding and removing entries from |sources_|, and | 285 // Step through |new_sources| adding and removing entries from |sources_|, and |
276 // notifying the |observer_|, until two match. Requires that |sources| and | 286 // notifying the |observer_|, until two match. Requires that |sources| and |
277 // |sources_| have the same ordering. | 287 // |sources_| have the same ordering. |
278 size_t pos = 0; | 288 size_t pos = 0; |
279 while (pos < sources_.size() || pos < new_sources.size()) { | 289 while (pos < sources_.size() || pos < new_sources.size()) { |
280 // If |sources_[pos]| is not in |new_sources| then remove it. | 290 // If |sources_[pos]| is not in |new_sources| then remove it. |
281 if (pos < sources_.size() && | 291 if (pos < sources_.size() && |
282 (pos == new_sources.size() || sources_[pos].id < new_sources[pos].id)) { | 292 (pos == new_sources.size() || sources_[pos].id < new_sources[pos].id)) { |
283 sources_.erase(sources_.begin() + pos); | 293 sources_.erase(sources_.begin() + pos); |
284 observer_->OnSourceRemoved(pos); | 294 observer_->OnSourceRemoved(pos); |
285 continue; | 295 continue; |
286 } | 296 } |
287 | 297 |
288 if (pos == sources_.size() || !(sources_[pos].id == new_sources[pos].id)) { | 298 if (pos == sources_.size() || !(sources_[pos].id == new_sources[pos].id)) { |
289 sources_.insert(sources_.begin() + pos, | 299 sources_.insert(sources_.begin() + pos, |
290 Source(new_sources[pos].id, new_sources[pos].name)); | 300 Source(new_sources[pos].id, new_sources[pos].name)); |
291 observer_->OnSourceAdded(pos); | 301 observer_->OnSourceAdded(pos); |
292 } else if (sources_[pos].name != new_sources[pos].name) { | 302 } else if (sources_[pos].name != new_sources[pos].name) { |
293 sources_[pos].name = new_sources[pos].name; | 303 sources_[pos].name = new_sources[pos].name; |
294 observer_->OnSourceNameChanged(pos); | 304 observer_->OnSourceNameChanged(pos); |
295 } | 305 } |
296 | 306 |
297 ++pos; | 307 ++pos; |
298 } | 308 } |
299 | 309 |
300 DCHECK_EQ(new_sources.size(), sources_.size()); | 310 DCHECK_EQ(new_sources.size(), sources_.size()); |
301 } | 311 } |
302 | 312 |
303 void DesktopMediaPickerModel::OnSourceThumbnail(int index, | 313 void DesktopMediaPickerModelImpl::OnSourceThumbnail(int index, |
304 const gfx::ImageSkia& image) { | 314 const gfx::ImageSkia& image) { |
305 DCHECK_LT(index, static_cast<int>(sources_.size())); | 315 DCHECK_LT(index, static_cast<int>(sources_.size())); |
306 sources_[index].thumbnail = image; | 316 sources_[index].thumbnail = image; |
307 observer_->OnSourceThumbnailChanged(index); | 317 observer_->OnSourceThumbnailChanged(index); |
308 } | 318 } |
309 | 319 |
310 void DesktopMediaPickerModel::OnRefreshFinished() { | 320 void DesktopMediaPickerModelImpl::OnRefreshFinished() { |
311 BrowserThread::PostDelayedTask( | 321 BrowserThread::PostDelayedTask( |
312 BrowserThread::UI, FROM_HERE, | 322 BrowserThread::UI, FROM_HERE, |
313 base::Bind(&DesktopMediaPickerModel::Refresh, weak_factory_.GetWeakPtr()), | 323 base::Bind(&DesktopMediaPickerModelImpl::Refresh, |
| 324 weak_factory_.GetWeakPtr()), |
314 update_period_); | 325 update_period_); |
315 } | 326 } |
OLD | NEW |