Index: chrome/browser/media/native_desktop_media_list.cc |
diff --git a/chrome/browser/media/native_desktop_media_list.cc b/chrome/browser/media/native_desktop_media_list.cc |
deleted file mode 100644 |
index eaa8e0f2ffd47389544ea7b8931c4a5b3115db65..0000000000000000000000000000000000000000 |
--- a/chrome/browser/media/native_desktop_media_list.cc |
+++ /dev/null |
@@ -1,376 +0,0 @@ |
-// Copyright 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/media/native_desktop_media_list.h" |
- |
-#include "base/hash.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "base/threading/sequenced_worker_pool.h" |
-#include "chrome/browser/media/desktop_media_list_observer.h" |
-#include "chrome/grit/generated_resources.h" |
-#include "content/public/browser/browser_thread.h" |
-#include "media/base/video_util.h" |
-#include "third_party/libyuv/include/libyuv/scale_argb.h" |
-#include "third_party/skia/include/core/SkBitmap.h" |
-#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
-#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" |
-#include "third_party/webrtc/modules/desktop_capture/window_capturer.h" |
-#include "ui/aura/window.h" |
-#include "ui/base/l10n/l10n_util.h" |
-#include "ui/snapshot/snapshot.h" |
- |
-#if defined(OS_WIN) |
-#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h" |
-#endif // defined(OS_WIN) |
- |
-#if defined(USE_X11) && !defined(OS_CHROMEOS) |
-#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" |
-#endif // defined(USE_X11) && !defined(OS_CHROMEOS) |
- |
-using content::BrowserThread; |
-using content::DesktopMediaID; |
- |
-namespace { |
- |
-// Update the list every second. |
-const int kDefaultUpdatePeriod = 1000; |
- |
-// Returns a hash of a DesktopFrame content to detect when image for a desktop |
-// media source has changed. |
-uint32_t GetFrameHash(webrtc::DesktopFrame* frame) { |
- int data_size = frame->stride() * frame->size().height(); |
- return base::Hash(reinterpret_cast<char*>(frame->data()), data_size); |
-} |
- |
-gfx::ImageSkia ScaleDesktopFrame(std::unique_ptr<webrtc::DesktopFrame> frame, |
- gfx::Size size) { |
- gfx::Rect scaled_rect = media::ComputeLetterboxRegion( |
- gfx::Rect(0, 0, size.width(), size.height()), |
- gfx::Size(frame->size().width(), frame->size().height())); |
- |
- SkBitmap result; |
- result.allocN32Pixels(scaled_rect.width(), scaled_rect.height(), true); |
- result.lockPixels(); |
- |
- uint8_t* pixels_data = reinterpret_cast<uint8_t*>(result.getPixels()); |
- libyuv::ARGBScale(frame->data(), frame->stride(), |
- frame->size().width(), frame->size().height(), |
- pixels_data, result.rowBytes(), |
- scaled_rect.width(), scaled_rect.height(), |
- libyuv::kFilterBilinear); |
- |
- // Set alpha channel values to 255 for all pixels. |
- // TODO(sergeyu): Fix screen/window capturers to capture alpha channel and |
- // remove this code. Currently screen/window capturers (at least some |
- // implementations) only capture R, G and B channels and set Alpha to 0. |
- // crbug.com/264424 |
- for (int y = 0; y < result.height(); ++y) { |
- for (int x = 0; x < result.width(); ++x) { |
- pixels_data[result.rowBytes() * y + x * result.bytesPerPixel() + 3] = |
- 0xff; |
- } |
- } |
- |
- result.unlockPixels(); |
- |
- return gfx::ImageSkia::CreateFrom1xBitmap(result); |
-} |
- |
-} // namespace |
- |
-class NativeDesktopMediaList::Worker |
- : public webrtc::DesktopCapturer::Callback { |
- public: |
- Worker(base::WeakPtr<NativeDesktopMediaList> media_list, |
- std::unique_ptr<webrtc::ScreenCapturer> screen_capturer, |
- std::unique_ptr<webrtc::WindowCapturer> window_capturer); |
- ~Worker() override; |
- |
- void Refresh(const DesktopMediaID::Id& view_dialog_id); |
- |
- void RefreshThumbnails(const std::vector<DesktopMediaID>& native_ids, |
- const gfx::Size& thumbnail_size); |
- |
- private: |
- typedef std::map<DesktopMediaID, uint32_t> ImageHashesMap; |
- |
- // webrtc::DesktopCapturer::Callback interface. |
- void OnCaptureResult(webrtc::DesktopCapturer::Result result, |
- std::unique_ptr<webrtc::DesktopFrame> frame) override; |
- |
- base::WeakPtr<NativeDesktopMediaList> media_list_; |
- |
- std::unique_ptr<webrtc::ScreenCapturer> screen_capturer_; |
- std::unique_ptr<webrtc::WindowCapturer> window_capturer_; |
- |
- std::unique_ptr<webrtc::DesktopFrame> current_frame_; |
- |
- ImageHashesMap image_hashes_; |
- |
- DISALLOW_COPY_AND_ASSIGN(Worker); |
-}; |
- |
-NativeDesktopMediaList::Worker::Worker( |
- base::WeakPtr<NativeDesktopMediaList> media_list, |
- std::unique_ptr<webrtc::ScreenCapturer> screen_capturer, |
- std::unique_ptr<webrtc::WindowCapturer> window_capturer) |
- : media_list_(media_list), |
- screen_capturer_(std::move(screen_capturer)), |
- window_capturer_(std::move(window_capturer)) { |
- if (screen_capturer_) |
- screen_capturer_->Start(this); |
- if (window_capturer_) |
- window_capturer_->Start(this); |
-} |
- |
-NativeDesktopMediaList::Worker::~Worker() {} |
- |
-void NativeDesktopMediaList::Worker::Refresh( |
- const DesktopMediaID::Id& view_dialog_id) { |
- std::vector<SourceDescription> sources; |
- |
- if (screen_capturer_) { |
- webrtc::ScreenCapturer::ScreenList screens; |
- if (screen_capturer_->GetScreenList(&screens)) { |
- bool mutiple_screens = screens.size() > 1; |
- base::string16 title; |
- for (size_t i = 0; i < screens.size(); ++i) { |
- if (mutiple_screens) { |
- // Just in case 'Screen' is inflected depending on the screen number, |
- // use plural formatter. |
- title = l10n_util::GetPluralStringFUTF16( |
- IDS_DESKTOP_MEDIA_PICKER_MULTIPLE_SCREEN_NAME, |
- static_cast<int>(i + 1)); |
- } else { |
- title = l10n_util::GetStringUTF16( |
- IDS_DESKTOP_MEDIA_PICKER_SINGLE_SCREEN_NAME); |
- } |
- sources.push_back(SourceDescription(DesktopMediaID( |
- DesktopMediaID::TYPE_SCREEN, screens[i].id), title)); |
- } |
- } |
- } |
- |
- if (window_capturer_) { |
- webrtc::WindowCapturer::WindowList windows; |
- if (window_capturer_->GetWindowList(&windows)) { |
- for (webrtc::WindowCapturer::WindowList::iterator it = windows.begin(); |
- it != windows.end(); ++it) { |
- // Skip the picker dialog window. |
- if (it->id == view_dialog_id) |
- continue; |
- |
- DesktopMediaID media_id(DesktopMediaID::TYPE_WINDOW, it->id); |
- sources.push_back( |
- SourceDescription(media_id, base::UTF8ToUTF16(it->title))); |
- } |
- } |
- } |
- |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&NativeDesktopMediaList::RefreshForAuraWindows, media_list_, |
- sources)); |
-} |
- |
-void NativeDesktopMediaList::Worker::RefreshThumbnails( |
- const std::vector<DesktopMediaID>& native_ids, |
- const gfx::Size& thumbnail_size) { |
- ImageHashesMap new_image_hashes; |
- |
- // Get a thumbnail for each native source. |
- for (const auto& id : native_ids) { |
- switch (id.type) { |
- case DesktopMediaID::TYPE_SCREEN: |
- if (!screen_capturer_->SelectScreen(id.id)) |
- continue; |
- screen_capturer_->Capture(webrtc::DesktopRegion()); |
- break; |
- |
- case DesktopMediaID::TYPE_WINDOW: |
- if (!window_capturer_->SelectWindow(id.id)) |
- continue; |
- window_capturer_->Capture(webrtc::DesktopRegion()); |
- break; |
- |
- default: |
- NOTREACHED(); |
- } |
- |
- // Expect that DesktopCapturer to always captures frames synchronously. |
- // |current_frame_| may be NULL if capture failed (e.g. because window has |
- // been closed). |
- if (current_frame_) { |
- uint32_t frame_hash = GetFrameHash(current_frame_.get()); |
- new_image_hashes[id] = frame_hash; |
- |
- // Scale the image only if it has changed. |
- ImageHashesMap::iterator it = image_hashes_.find(id); |
- if (it == image_hashes_.end() || it->second != frame_hash) { |
- gfx::ImageSkia thumbnail = |
- ScaleDesktopFrame(std::move(current_frame_), thumbnail_size); |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&NativeDesktopMediaList::UpdateSourceThumbnail, |
- media_list_, id, thumbnail)); |
- } |
- } |
- } |
- |
- image_hashes_.swap(new_image_hashes); |
- |
- BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind(&NativeDesktopMediaList::UpdateNativeThumbnailsFinished, |
- media_list_)); |
-} |
- |
-void NativeDesktopMediaList::Worker::OnCaptureResult( |
- webrtc::DesktopCapturer::Result result, |
- std::unique_ptr<webrtc::DesktopFrame> frame) { |
- current_frame_ = std::move(frame); |
-} |
- |
-NativeDesktopMediaList::NativeDesktopMediaList( |
- std::unique_ptr<webrtc::ScreenCapturer> screen_capturer, |
- std::unique_ptr<webrtc::WindowCapturer> window_capturer) |
- : DesktopMediaListBase( |
- base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)), |
- weak_factory_(this) { |
- base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool(); |
- capture_task_runner_ = worker_pool->GetSequencedTaskRunner( |
- worker_pool->GetSequenceToken()); |
- |
- worker_.reset(new Worker(weak_factory_.GetWeakPtr(), |
- std::move(screen_capturer), |
- std::move(window_capturer))); |
-} |
- |
-NativeDesktopMediaList::~NativeDesktopMediaList() { |
- capture_task_runner_->DeleteSoon(FROM_HERE, worker_.release()); |
-} |
- |
-void NativeDesktopMediaList::Refresh() { |
-#if defined(USE_AURA) |
- DCHECK_EQ(pending_aura_capture_requests_, 0); |
- DCHECK(!pending_native_thumbnail_capture_); |
- new_aura_thumbnail_hashes_.clear(); |
-#endif |
- |
- capture_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&Worker::Refresh, base::Unretained(worker_.get()), |
- view_dialog_id_.id)); |
-} |
- |
-void NativeDesktopMediaList::RefreshForAuraWindows( |
- std::vector<SourceDescription> sources) { |
-#if defined(USE_AURA) |
- // Associate aura id with native id. |
- for (auto& source : sources) { |
- if (source.id.type != DesktopMediaID::TYPE_WINDOW) |
- continue; |
- |
- aura::Window* aura_window = NULL; |
-#if defined(OS_WIN) |
- aura_window = views::DesktopWindowTreeHostWin::GetContentWindowForHWND( |
- reinterpret_cast<HWND>(source.id.id)); |
-#elif defined(USE_X11) && !defined(OS_CHROMEOS) |
- aura_window = |
- views::DesktopWindowTreeHostX11::GetContentWindowForXID(source.id.id); |
-#endif // defined(USE_X11) && !defined(OS_CHROMEOS) |
- if (aura_window) { |
- DesktopMediaID aura_id = DesktopMediaID::RegisterAuraWindow( |
- DesktopMediaID::TYPE_WINDOW, aura_window); |
- source.id.aura_id = aura_id.aura_id; |
- } |
- } |
-#endif // defined(USE_AURA) |
- |
- UpdateSourcesList(sources); |
- |
- // OnAuraThumbnailCaptured() and UpdateNativeThumbnailsFinished() are |
- // guaranteed to be excuted after RefreshForAuraWindows() and |
- // CaptureAuraWindowThumbnail() in the browser UI thread. |
- // Therefore pending_aura_capture_requests_ will be set the number of aura |
- // windows to be captured and pending_native_thumbnail_capture_ will be set |
- // true if native thumbnail capture is needed before OnAuraThumbnailCaptured() |
- // or UpdateNativeThumbnailsFinished() are called. |
- std::vector<DesktopMediaID> native_ids; |
- for (const auto& source : sources) { |
-#if defined(USE_AURA) |
- if (source.id.aura_id > DesktopMediaID::kNullId) { |
- CaptureAuraWindowThumbnail(source.id); |
- continue; |
- } |
-#endif // defined(USE_AURA) |
- native_ids.push_back(source.id); |
- } |
- |
- if (native_ids.size() > 0) { |
-#if defined(USE_AURA) |
- pending_native_thumbnail_capture_ = true; |
-#endif |
- capture_task_runner_->PostTask( |
- FROM_HERE, |
- base::Bind(&Worker::RefreshThumbnails, base::Unretained(worker_.get()), |
- native_ids, thumbnail_size_)); |
- } |
-} |
- |
-void NativeDesktopMediaList::UpdateNativeThumbnailsFinished() { |
-#if defined(USE_AURA) |
- DCHECK(pending_native_thumbnail_capture_); |
- pending_native_thumbnail_capture_ = false; |
- // Schedule next refresh if native thumbnail captures finished after aura |
- // thumbnail captures. |
- if (pending_aura_capture_requests_ == 0) |
- ScheduleNextRefresh(); |
-#else |
- ScheduleNextRefresh(); |
-#endif // defined(USE_AURA) |
-} |
- |
-#if defined(USE_AURA) |
- |
-void NativeDesktopMediaList::CaptureAuraWindowThumbnail( |
- const DesktopMediaID& id) { |
- gfx::NativeWindow window = DesktopMediaID::GetAuraWindowById(id); |
- if (!window) |
- return; |
- |
- gfx::Rect window_rect(window->bounds().width(), window->bounds().height()); |
- gfx::Rect scaled_rect = media::ComputeLetterboxRegion( |
- gfx::Rect(thumbnail_size_), window_rect.size()); |
- |
- pending_aura_capture_requests_++; |
- ui::GrabWindowSnapshotAndScaleAsync( |
- window, window_rect, scaled_rect.size(), BrowserThread::GetBlockingPool(), |
- base::Bind(&NativeDesktopMediaList::OnAuraThumbnailCaptured, |
- weak_factory_.GetWeakPtr(), id)); |
-} |
- |
-void NativeDesktopMediaList::OnAuraThumbnailCaptured(const DesktopMediaID& id, |
- const gfx::Image& image) { |
- if (!image.IsEmpty()) { |
- // Only new or changed thumbnail need update. |
- new_aura_thumbnail_hashes_[id] = GetImageHash(image); |
- if (!previous_aura_thumbnail_hashes_.count(id) || |
- previous_aura_thumbnail_hashes_[id] != new_aura_thumbnail_hashes_[id]) { |
- UpdateSourceThumbnail(id, image.AsImageSkia()); |
- } |
- } |
- |
- // After all aura windows are processed, schedule next refresh; |
- pending_aura_capture_requests_--; |
- DCHECK_GE(pending_aura_capture_requests_, 0); |
- if (pending_aura_capture_requests_ == 0) { |
- previous_aura_thumbnail_hashes_ = std::move(new_aura_thumbnail_hashes_); |
- // Schedule next refresh if aura thumbnail captures finished after native |
- // thumbnail captures. |
- if (!pending_native_thumbnail_capture_) |
- ScheduleNextRefresh(); |
- } |
-} |
- |
-#endif // defined(USE_AURA) |