Skip to content

Commit 596ae2c

Browse files
deepak1556Cheng Zhao
authored andcommitted
refactor: desktop capturer module (electron#14835)
* Revert "post all desktop capturer apis to worker threads" This reverts commit 5a28759. * refactor: desktop capturer module * Creates the screen and window capturer for the liftime of the app * Fixes incorrect usage of weak ptr * build: add //ui/snapshot to chromium_src deps * fix: handle scenarios when there are no captured sources
1 parent e06bc31 commit 596ae2c

File tree

13 files changed

+466
-830
lines changed

13 files changed

+466
-830
lines changed

atom/browser/api/atom_api_desktop_capturer.cc

Lines changed: 112 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,17 @@
88
#include <utility>
99
#include <vector>
1010

11-
using base::PlatformThreadRef;
12-
1311
#include "atom/common/api/atom_api_native_image.h"
1412
#include "atom/common/native_mate_converters/gfx_converter.h"
1513
#include "base/strings/string_number_conversions.h"
1614
#include "base/strings/utf_string_conversions.h"
17-
#include "base/task_scheduler/post_task.h"
18-
#include "base/threading/thread_task_runner_handle.h"
19-
#include "chrome/browser/media/desktop_media_list.h"
20-
#include "content/public/browser/browser_thread.h"
15+
#include "base/threading/thread_restrictions.h"
16+
#include "chrome/browser/media/webrtc/desktop_media_list.h"
2117
#include "content/public/browser/desktop_capture.h"
2218
#include "native_mate/dictionary.h"
2319
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
2420
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
21+
2522
#if defined(OS_WIN)
2623
#include "third_party/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h"
2724
#include "third_party/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
@@ -51,63 +48,121 @@ struct Converter<atom::api::DesktopCapturer::Source> {
5148

5249
} // namespace mate
5350

54-
namespace {
51+
namespace atom {
5552

56-
void EmitFinished(
57-
const std::vector<atom::api::DesktopCapturer::Source>& sources,
58-
atom::api::DesktopCapturer* cap) {
59-
cap->Emit("finished", sources);
53+
namespace api {
54+
55+
DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) {
56+
Init(isolate);
6057
}
6158

62-
void StartHandlingTask(bool capture_window,
63-
bool capture_screen,
64-
const gfx::Size& thumbnail_size,
65-
atom::api::DesktopCapturer* cap) {
59+
DesktopCapturer::~DesktopCapturer() {}
60+
61+
void DesktopCapturer::StartHandling(bool capture_window,
62+
bool capture_screen,
63+
const gfx::Size& thumbnail_size) {
6664
#if defined(OS_WIN)
6765
if (content::desktop_capture::CreateDesktopCaptureOptions()
6866
.allow_directx_capturer()) {
6967
// DxgiDuplicatorController should be alive in this scope according to
7068
// screen_capturer_win.cc.
7169
auto duplicator = webrtc::DxgiDuplicatorController::Instance();
72-
cap->using_directx_capturer_ =
73-
webrtc::ScreenCapturerWinDirectx::IsSupported();
70+
using_directx_capturer_ = webrtc::ScreenCapturerWinDirectx::IsSupported();
7471
}
7572
#endif // defined(OS_WIN)
76-
std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
77-
capture_screen ? content::desktop_capture::CreateScreenCapturer()
78-
: nullptr);
79-
std::unique_ptr<webrtc::DesktopCapturer> window_capturer(
80-
capture_window ? content::desktop_capture::CreateWindowCapturer()
81-
: nullptr);
82-
cap->media_list_.reset(new NativeDesktopMediaList(
83-
std::move(screen_capturer), std::move(window_capturer)));
84-
85-
cap->media_list_->SetThumbnailSize(thumbnail_size);
86-
cap->media_list_->StartUpdating(cap);
73+
74+
// clear any existing captured sources.
75+
captured_sources_.clear();
76+
77+
// Start listening for captured sources.
78+
capture_window_ = capture_window;
79+
capture_screen_ = capture_screen;
80+
81+
{
82+
// Remove this once
83+
// https://bugs.chromium.org/p/chromium/issues/detail?id=795340 is fixed.
84+
base::ScopedAllowBaseSyncPrimitivesForTesting
85+
scoped_allow_base_sync_primitives;
86+
// Initialize the source list.
87+
// Apply the new thumbnail size and restart capture.
88+
if (capture_window) {
89+
window_capturer_.reset(new NativeDesktopMediaList(
90+
content::DesktopMediaID::TYPE_WINDOW,
91+
content::desktop_capture::CreateWindowCapturer()));
92+
window_capturer_->SetThumbnailSize(thumbnail_size);
93+
window_capturer_->AddObserver(this);
94+
window_capturer_->StartUpdating();
95+
}
96+
97+
if (capture_screen) {
98+
screen_capturer_.reset(new NativeDesktopMediaList(
99+
content::DesktopMediaID::TYPE_SCREEN,
100+
content::desktop_capture::CreateScreenCapturer()));
101+
screen_capturer_->SetThumbnailSize(thumbnail_size);
102+
screen_capturer_->AddObserver(this);
103+
screen_capturer_->StartUpdating();
104+
}
105+
}
106+
}
107+
108+
void DesktopCapturer::OnSourceAdded(DesktopMediaList* list, int index) {}
109+
110+
void DesktopCapturer::OnSourceRemoved(DesktopMediaList* list, int index) {}
111+
112+
void DesktopCapturer::OnSourceMoved(DesktopMediaList* list,
113+
int old_index,
114+
int new_index) {}
115+
116+
void DesktopCapturer::OnSourceNameChanged(DesktopMediaList* list, int index) {}
117+
118+
void DesktopCapturer::OnSourceThumbnailChanged(DesktopMediaList* list,
119+
int index) {}
120+
121+
void DesktopCapturer::OnSourceUnchanged(DesktopMediaList* list) {
122+
UpdateSourcesList(list);
87123
}
88124

89-
void OnRefreshFinishedTask(atom::api::DesktopCapturer* cap) {
90-
const auto media_list_sources = cap->media_list_->GetSources();
91-
std::vector<atom::api::DesktopCapturer::Source> sources;
92-
for (const auto& media_list_source : media_list_sources) {
93-
sources.emplace_back(
94-
atom::api::DesktopCapturer::Source{media_list_source, std::string()});
125+
bool DesktopCapturer::ShouldScheduleNextRefresh(DesktopMediaList* list) {
126+
UpdateSourcesList(list);
127+
return false;
128+
}
129+
130+
void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) {
131+
std::vector<DesktopCapturer::Source> window_sources;
132+
if (capture_window_ &&
133+
list->GetMediaListType() == content::DesktopMediaID::TYPE_WINDOW) {
134+
capture_window_ = false;
135+
const auto& media_list_sources = list->GetSources();
136+
for (const auto& media_list_source : media_list_sources) {
137+
window_sources.emplace_back(
138+
DesktopCapturer::Source{media_list_source, std::string()});
139+
}
140+
std::move(window_sources.begin(), window_sources.end(),
141+
std::back_inserter(captured_sources_));
95142
}
96143

144+
std::vector<DesktopCapturer::Source> screen_sources;
145+
if (capture_screen_ &&
146+
list->GetMediaListType() == content::DesktopMediaID::TYPE_SCREEN) {
147+
capture_screen_ = false;
148+
const auto& media_list_sources = list->GetSources();
149+
for (const auto& media_list_source : media_list_sources) {
150+
screen_sources.emplace_back(
151+
DesktopCapturer::Source{media_list_source, std::string()});
152+
}
97153
#if defined(OS_WIN)
98-
// Gather the same unique screen IDs used by the electron.screen API in order
99-
// to provide an association between it and desktopCapturer/getUserMedia.
100-
// This is only required when using the DirectX capturer, otherwise the IDs
101-
// across the APIs already match.
102-
if (cap->using_directx_capturer_) {
103-
std::vector<std::string> device_names;
104-
// Crucially, this list of device names will be in the same order as
105-
// |media_list_sources|.
106-
webrtc::DxgiDuplicatorController::Instance()->GetDeviceNames(&device_names);
107-
int device_name_index = 0;
108-
for (auto& source : sources) {
109-
if (source.media_list_source.id.type ==
110-
content::DesktopMediaID::TYPE_SCREEN) {
154+
// Gather the same unique screen IDs used by the electron.screen API in
155+
// order to provide an association between it and
156+
// desktopCapturer/getUserMedia. This is only required when using the
157+
// DirectX capturer, otherwise the IDs across the APIs already match.
158+
if (using_directx_capturer_) {
159+
std::vector<std::string> device_names;
160+
// Crucially, this list of device names will be in the same order as
161+
// |media_list_sources|.
162+
webrtc::DxgiDuplicatorController::Instance()->GetDeviceNames(
163+
&device_names);
164+
int device_name_index = 0;
165+
for (auto& source : screen_sources) {
111166
const auto& device_name = device_names[device_name_index++];
112167
std::wstring wide_device_name;
113168
base::UTF8ToWide(device_name.c_str(), device_name.size(),
@@ -118,61 +173,21 @@ void OnRefreshFinishedTask(atom::api::DesktopCapturer* cap) {
118173
source.display_id = base::Int64ToString(device_id);
119174
}
120175
}
121-
}
122176
#elif defined(OS_MACOSX)
123-
// On Mac, the IDs across the APIs match.
124-
for (auto& source : sources) {
125-
if (source.media_list_source.id.type ==
126-
content::DesktopMediaID::TYPE_SCREEN) {
177+
// On Mac, the IDs across the APIs match.
178+
for (auto& source : screen_sources) {
127179
source.display_id = base::Int64ToString(source.media_list_source.id.id);
128180
}
129-
}
130181
#endif // defined(OS_WIN)
131-
// TODO(ajmacd): Add Linux support. The IDs across APIs differ but Chrome only
132-
// supports capturing the entire desktop on Linux. Revisit this if individual
133-
// screen support is added.
134-
135-
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
136-
base::Bind(EmitFinished, sources, cap));
137-
}
138-
139-
} // namespace
140-
141-
namespace atom {
142-
143-
namespace api {
144-
145-
DesktopCapturer::DesktopCapturer(v8::Isolate* isolate) {
146-
Init(isolate);
147-
capture_thread_ = base::CreateSequencedTaskRunnerWithTraits(
148-
{base::WithBaseSyncPrimitives(), base::MayBlock(),
149-
base::TaskPriority::USER_VISIBLE});
150-
}
151-
152-
DesktopCapturer::~DesktopCapturer() {}
153-
154-
void DesktopCapturer::StartHandling(bool capture_window,
155-
bool capture_screen,
156-
const gfx::Size& thumbnail_size) {
157-
capture_thread_->PostTask(
158-
FROM_HERE, base::BindOnce(StartHandlingTask, capture_window,
159-
capture_screen, thumbnail_size, this));
160-
}
161-
162-
void DesktopCapturer::OnSourceAdded(int index) {}
163-
164-
void DesktopCapturer::OnSourceRemoved(int index) {}
165-
166-
void DesktopCapturer::OnSourceMoved(int old_index, int new_index) {}
167-
168-
void DesktopCapturer::OnSourceNameChanged(int index) {}
169-
170-
void DesktopCapturer::OnSourceThumbnailChanged(int index) {}
182+
// TODO(ajmacd): Add Linux support. The IDs across APIs differ but Chrome
183+
// only supports capturing the entire desktop on Linux. Revisit this if
184+
// individual screen support is added.
185+
std::move(screen_sources.begin(), screen_sources.end(),
186+
std::back_inserter(captured_sources_));
187+
}
171188

172-
bool DesktopCapturer::OnRefreshFinished() {
173-
capture_thread_->PostTask(FROM_HERE,
174-
base::BindOnce(OnRefreshFinishedTask, this));
175-
return false;
189+
if (!capture_window_ && !capture_screen_)
190+
Emit("finished", captured_sources_);
176191
}
177192

178193
// static

atom/browser/api/atom_api_desktop_capturer.h

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77

88
#include <memory>
99
#include <string>
10+
#include <vector>
1011

1112
#include "atom/browser/api/event_emitter.h"
12-
#include "chrome/browser/media/desktop_media_list_observer.h"
13-
#include "chrome/browser/media/native_desktop_media_list.h"
13+
#include "chrome/browser/media/webrtc/desktop_media_list_observer.h"
14+
#include "chrome/browser/media/webrtc/native_desktop_media_list.h"
1415
#include "native_mate/handle.h"
1516

1617
namespace atom {
@@ -35,25 +36,32 @@ class DesktopCapturer : public mate::EventEmitter<DesktopCapturer>,
3536
bool capture_screen,
3637
const gfx::Size& thumbnail_size);
3738

38-
std::unique_ptr<DesktopMediaList> media_list_;
39-
#if defined(OS_WIN)
40-
bool using_directx_capturer_ = false;
41-
#endif // defined(OS_WIN)
42-
4339
protected:
4440
explicit DesktopCapturer(v8::Isolate* isolate);
4541
~DesktopCapturer() override;
4642

4743
// DesktopMediaListObserver overrides.
48-
void OnSourceAdded(int index) override;
49-
void OnSourceRemoved(int index) override;
50-
void OnSourceMoved(int old_index, int new_index) override;
51-
void OnSourceNameChanged(int index) override;
52-
void OnSourceThumbnailChanged(int index) override;
53-
bool OnRefreshFinished() override;
44+
void OnSourceAdded(DesktopMediaList* list, int index) override;
45+
void OnSourceRemoved(DesktopMediaList* list, int index) override;
46+
void OnSourceMoved(DesktopMediaList* list,
47+
int old_index,
48+
int new_index) override;
49+
void OnSourceNameChanged(DesktopMediaList* list, int index) override;
50+
void OnSourceThumbnailChanged(DesktopMediaList* list, int index) override;
51+
void OnSourceUnchanged(DesktopMediaList* list) override;
52+
bool ShouldScheduleNextRefresh(DesktopMediaList* list) override;
5453

5554
private:
56-
scoped_refptr<base::SequencedTaskRunner> capture_thread_;
55+
void UpdateSourcesList(DesktopMediaList* list);
56+
57+
std::unique_ptr<DesktopMediaList> window_capturer_;
58+
std::unique_ptr<DesktopMediaList> screen_capturer_;
59+
std::vector<DesktopCapturer::Source> captured_sources_;
60+
bool capture_window_ = false;
61+
bool capture_screen_ = false;
62+
#if defined(OS_WIN)
63+
bool using_directx_capturer_ = false;
64+
#endif // defined(OS_WIN)
5765

5866
DISALLOW_COPY_AND_ASSIGN(DesktopCapturer);
5967
};

chromium_src/BUILD.gn

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# Use of this source code is governed by the MIT license that can be
33
# found in the LICENSE file.
44

5+
import("//electron/buildflags/buildflags.gni")
6+
57
# Builds some of the chrome sources that Electron depends
68
# on unconditionally.
79
source_set("chrome") {
@@ -10,6 +12,22 @@ source_set("chrome") {
1012
"//chrome/browser/ssl/security_state_tab_helper.cc",
1113
"//chrome/browser/ssl/security_state_tab_helper.h",
1214
]
13-
public_deps = [ "//content/public/browser" ]
14-
deps = [ "//components/security_state/content" ]
15+
public_deps = [
16+
"//content/public/browser",
17+
]
18+
deps = [
19+
"//components/security_state/content",
20+
]
21+
22+
if (enable_desktop_capturer) {
23+
sources += [
24+
"//chrome/browser/media/webrtc/desktop_media_list.h",
25+
"//chrome/browser/media/webrtc/desktop_media_list_base.cc",
26+
"//chrome/browser/media/webrtc/desktop_media_list_base.h",
27+
"//chrome/browser/media/webrtc/desktop_media_list_observer.h",
28+
"//chrome/browser/media/webrtc/native_desktop_media_list.cc",
29+
"//chrome/browser/media/webrtc/native_desktop_media_list.h",
30+
]
31+
deps += [ "//ui/snapshot" ]
32+
}
1533
}

0 commit comments

Comments
 (0)