From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Thu, 18 Oct 2018 17:07:01 -0700 Subject: desktop_media_list.patch * Adds a new observer method to DesktopMediaListObserver for desktop capture api. * Backports https://chromium-review.googlesource.com/c/chromium/src/+/1199806 that fixes crash with screen capturer, can be removed in 71.0.3539.0 diff --git a/chrome/browser/media/webrtc/desktop_media_list.h b/chrome/browser/media/webrtc/desktop_media_list.h index 8e02a8a95eb07516162eacdf5b361231d3a02975..3497b85428a52c6019cfb5d30229071f99ecfb20 100644 --- a/chrome/browser/media/webrtc/desktop_media_list.h +++ b/chrome/browser/media/webrtc/desktop_media_list.h @@ -32,6 +32,9 @@ class DesktopMediaList { virtual ~DesktopMediaList() {} + // Allows listening to notifications generated by the model. + virtual void AddObserver(DesktopMediaListObserver* observer) = 0; + // Sets time interval between updates. By default list of sources and their // thumbnail are updated once per second. If called after StartUpdating() then // it will take effect only after the next update. @@ -51,10 +54,11 @@ class DesktopMediaList { // enumerated. After the initial enumeration the model will be refreshed based // on the update period, and notifications generated only for changes in the // model. - virtual void StartUpdating(DesktopMediaListObserver* observer) = 0; + virtual void StartUpdating() = 0; virtual int GetSourceCount() const = 0; virtual const Source& GetSource(int index) const = 0; + virtual const std::vector& GetSources() const = 0; virtual content::DesktopMediaID::Type GetMediaListType() const = 0; }; diff --git a/chrome/browser/media/webrtc/desktop_media_list_base.cc b/chrome/browser/media/webrtc/desktop_media_list_base.cc index 43dd95ef72f5b35b91471950cc114800d54945ab..d4662708f64934372422b853673eaaf8f05e4baf 100644 --- a/chrome/browser/media/webrtc/desktop_media_list_base.cc +++ b/chrome/browser/media/webrtc/desktop_media_list_base.cc @@ -18,6 +18,11 @@ DesktopMediaListBase::DesktopMediaListBase(base::TimeDelta update_period) DesktopMediaListBase::~DesktopMediaListBase() {} +void DesktopMediaListBase::AddObserver(DesktopMediaListObserver* observer) { + DCHECK(!observer_); + observer_ = observer; +} + void DesktopMediaListBase::SetUpdatePeriod(base::TimeDelta period) { DCHECK(!observer_); update_period_ = period; @@ -31,10 +36,7 @@ void DesktopMediaListBase::SetViewDialogWindowId(DesktopMediaID dialog_id) { view_dialog_id_ = dialog_id; } -void DesktopMediaListBase::StartUpdating(DesktopMediaListObserver* observer) { - DCHECK(!observer_); - - observer_ = observer; +void DesktopMediaListBase::StartUpdating() { Refresh(); } @@ -49,6 +51,11 @@ const DesktopMediaList::Source& DesktopMediaListBase::GetSource( return sources_[index]; } +const std::vector& DesktopMediaListBase::GetSources() + const { + return sources_; +} + DesktopMediaID::Type DesktopMediaListBase::GetMediaListType() const { return type_; } @@ -60,6 +67,12 @@ DesktopMediaListBase::SourceDescription::SourceDescription( void DesktopMediaListBase::UpdateSourcesList( const std::vector& new_sources) { + // Notify observer when there was no new source captured. + if (new_sources.empty()) { + observer_->OnSourceUnchanged(this); + return; + } + typedef std::set SourceSet; SourceSet new_source_set; for (size_t i = 0; i < new_sources.size(); ++i) { @@ -132,6 +145,8 @@ void DesktopMediaListBase::UpdateSourceThumbnail(DesktopMediaID id, } void DesktopMediaListBase::ScheduleNextRefresh() { + if (!observer_->ShouldScheduleNextRefresh(this)) + return; BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE, base::BindOnce(&DesktopMediaListBase::Refresh, weak_factory_.GetWeakPtr()), diff --git a/chrome/browser/media/webrtc/desktop_media_list_base.h b/chrome/browser/media/webrtc/desktop_media_list_base.h index 746df1210aa92af5c9d4703112b4bd6c09b94fdf..461e0edf8509569d05c86f466c02b5035183d0df 100644 --- a/chrome/browser/media/webrtc/desktop_media_list_base.h +++ b/chrome/browser/media/webrtc/desktop_media_list_base.h @@ -24,12 +24,14 @@ class DesktopMediaListBase : public DesktopMediaList { ~DesktopMediaListBase() override; // DesktopMediaList interface. + void AddObserver(DesktopMediaListObserver* observer) override; void SetUpdatePeriod(base::TimeDelta period) override; void SetThumbnailSize(const gfx::Size& thumbnail_size) override; void SetViewDialogWindowId(content::DesktopMediaID dialog_id) override; - void StartUpdating(DesktopMediaListObserver* observer) override; + void StartUpdating() override; int GetSourceCount() const override; const Source& GetSource(int index) const override; + const std::vector& GetSources() const override; content::DesktopMediaID::Type GetMediaListType() const override; static uint32_t GetImageHash(const gfx::Image& image); diff --git a/chrome/browser/media/webrtc/desktop_media_list_observer.h b/chrome/browser/media/webrtc/desktop_media_list_observer.h index 47401abc984e6fe26c7f4c5399aa565c687060b0..ca6a527ffac877c27aac94337ec5a7b546e09768 100644 --- a/chrome/browser/media/webrtc/desktop_media_list_observer.h +++ b/chrome/browser/media/webrtc/desktop_media_list_observer.h @@ -18,6 +18,10 @@ class DesktopMediaListObserver { int new_index) = 0; virtual void OnSourceNameChanged(DesktopMediaList* list, int index) = 0; virtual void OnSourceThumbnailChanged(DesktopMediaList* list, int index) = 0; + virtual void OnSourceUnchanged(DesktopMediaList* list) = 0; + // Return value indicates whether the observer should continue listening + // for capture updates. + virtual bool ShouldScheduleNextRefresh(DesktopMediaList* list) = 0; protected: virtual ~DesktopMediaListObserver() {} diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.cc b/chrome/browser/media/webrtc/native_desktop_media_list.cc index 0c9ba953cb3c268930fb101105c22416ed3cae08..c2482774f0747a0300d72d7ef05ed429caaf7d19 100644 --- a/chrome/browser/media/webrtc/native_desktop_media_list.cc +++ b/chrome/browser/media/webrtc/native_desktop_media_list.cc @@ -5,11 +5,15 @@ #include "chrome/browser/media/webrtc/native_desktop_media_list.h" #include "base/hash.h" +#include "base/single_thread_task_runner.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/task_scheduler/post_task.h" +#include "base/threading/thread_restrictions.h" +#include "build/build_config.h" #include "chrome/browser/media/webrtc/desktop_media_list_observer.h" -#include "chrome/grit/generated_resources.h" #include "content/public/browser/browser_thread.h" +#include "electron/grit/electron_resources.h" #include "media/base/video_util.h" #include "third_party/libyuv/include/libyuv/scale_argb.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -76,11 +80,13 @@ gfx::ImageSkia ScaleDesktopFrame(std::unique_ptr frame, class NativeDesktopMediaList::Worker : public webrtc::DesktopCapturer::Callback { public: - Worker(base::WeakPtr media_list, + Worker(scoped_refptr task_runner, + base::WeakPtr media_list, DesktopMediaID::Type type, std::unique_ptr capturer); ~Worker() override; + void Start(); void Refresh(const DesktopMediaID::Id& view_dialog_id); void RefreshThumbnails(const std::vector& native_ids, @@ -93,6 +99,9 @@ class NativeDesktopMediaList::Worker void OnCaptureResult(webrtc::DesktopCapturer::Result result, std::unique_ptr frame) override; + // Task runner used for capturing operations. + scoped_refptr task_runner_; + base::WeakPtr media_list_; DesktopMediaID::Type type_; @@ -106,17 +115,27 @@ class NativeDesktopMediaList::Worker }; NativeDesktopMediaList::Worker::Worker( + scoped_refptr task_runner, base::WeakPtr media_list, DesktopMediaID::Type type, std::unique_ptr capturer) - : media_list_(media_list), type_(type), capturer_(std::move(capturer)) { - capturer_->Start(this); + : task_runner_(task_runner), + media_list_(media_list), + type_(type), + capturer_(std::move(capturer)) {} + +NativeDesktopMediaList::Worker::~Worker() { + DCHECK(task_runner_->BelongsToCurrentThread()); } -NativeDesktopMediaList::Worker::~Worker() {} +void NativeDesktopMediaList::Worker::Start() { + DCHECK(task_runner_->BelongsToCurrentThread()); + capturer_->Start(this); +} void NativeDesktopMediaList::Worker::Refresh( const DesktopMediaID::Id& view_dialog_id) { + DCHECK(task_runner_->BelongsToCurrentThread()); std::vector result; webrtc::DesktopCapturer::SourceList sources; @@ -163,6 +182,7 @@ void NativeDesktopMediaList::Worker::Refresh( void NativeDesktopMediaList::Worker::RefreshThumbnails( const std::vector& native_ids, const gfx::Size& thumbnail_size) { + DCHECK(task_runner_->BelongsToCurrentThread()); ImageHashesMap new_image_hashes; // Get a thumbnail for each native source. @@ -210,17 +230,30 @@ NativeDesktopMediaList::NativeDesktopMediaList( std::unique_ptr capturer) : DesktopMediaListBase(base::TimeDelta::FromMilliseconds( kDefaultNativeDesktopMediaListUpdatePeriod)), + thread_("DesktopMediaListCaptureThread"), weak_factory_(this) { type_ = type; - capture_task_runner_ = base::CreateSequencedTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::USER_VISIBLE}); - worker_.reset( - new Worker(weak_factory_.GetWeakPtr(), type, std::move(capturer))); +#if defined(OS_WIN) || defined(OS_MACOSX) + // On Windows/OSX the thread must be a UI thread. + base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_UI; +#else + base::MessageLoop::Type thread_type = base::MessageLoop::TYPE_DEFAULT; +#endif + thread_.StartWithOptions(base::Thread::Options(thread_type, 0)); + + worker_.reset(new Worker(thread_.task_runner(), weak_factory_.GetWeakPtr(), + type, std::move(capturer))); + + thread_.task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&Worker::Start, base::Unretained(worker_.get()))); } NativeDesktopMediaList::~NativeDesktopMediaList() { - capture_task_runner_->DeleteSoon(FROM_HERE, worker_.release()); + base::ThreadRestrictions::ScopedAllowIO allow_io; + thread_.task_runner()->DeleteSoon(FROM_HERE, worker_.release()); + thread_.Stop(); } void NativeDesktopMediaList::Refresh() { @@ -230,7 +263,7 @@ void NativeDesktopMediaList::Refresh() { new_aura_thumbnail_hashes_.clear(); #endif - capture_task_runner_->PostTask( + thread_.task_runner()->PostTask( FROM_HERE, base::BindOnce(&Worker::Refresh, base::Unretained(worker_.get()), view_dialog_id_.id)); @@ -280,7 +313,7 @@ void NativeDesktopMediaList::RefreshForAuraWindows( #if defined(USE_AURA) pending_native_thumbnail_capture_ = true; #endif - capture_task_runner_->PostTask( + thread_.task_runner()->PostTask( FROM_HERE, base::BindOnce(&Worker::RefreshThumbnails, base::Unretained(worker_.get()), native_ids, thumbnail_size_)); diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.h b/chrome/browser/media/webrtc/native_desktop_media_list.h index e6f0e17b05ee4dc45827dc2dd00d484201f74646..75c9ca04ce481ab79615515da948c29d449865dc 100644 --- a/chrome/browser/media/webrtc/native_desktop_media_list.h +++ b/chrome/browser/media/webrtc/native_desktop_media_list.h @@ -8,7 +8,7 @@ #include #include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner.h" +#include "base/threading/thread.h" #include "chrome/browser/media/webrtc/desktop_media_list_base.h" #include "content/public/browser/desktop_media_id.h" #include "ui/gfx/image/image.h" @@ -44,12 +44,7 @@ class NativeDesktopMediaList : public DesktopMediaListBase { gfx::Image image); #endif - // Task runner used for the |worker_|. - scoped_refptr capture_task_runner_; - - // An object that does all the work of getting list of sources on a background - // thread (see |capture_task_runner_|). Destroyed on |capture_task_runner_| - // after the model is destroyed. + base::Thread thread_; std::unique_ptr worker_; #if defined(USE_AURA)