| 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 |