mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-03-22 07:37:29 +08:00
[feat] load wgc from wgc_plugin.dll at runtime and drop direct'windowsapp' linking, refs #74
This commit is contained in:
@@ -108,7 +108,7 @@ std::string GetHostName() {
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||||
std::cerr << "WSAStartup failed." << std::endl;
|
LOG_ERROR("WSAStartup failed");
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
if (gethostname(hostname, sizeof(hostname)) == SOCKET_ERROR) {
|
if (gethostname(hostname, sizeof(hostname)) == SOCKET_ERROR) {
|
||||||
|
|||||||
@@ -62,4 +62,4 @@ std::shared_ptr<spdlog::logger> get_logger() {
|
|||||||
|
|
||||||
return g_logger;
|
return g_logger;
|
||||||
}
|
}
|
||||||
} // namespace crossdesk
|
} // namespace crossdesk
|
||||||
|
|||||||
@@ -1,17 +1,108 @@
|
|||||||
#include "screen_capturer_win.h"
|
#include "screen_capturer_win.h"
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <filesystem>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
#include "screen_capturer_dxgi.h"
|
#include "screen_capturer_dxgi.h"
|
||||||
#include "screen_capturer_gdi.h"
|
#include "screen_capturer_gdi.h"
|
||||||
#include "screen_capturer_wgc.h"
|
#include "wgc_plugin_api.h"
|
||||||
|
|
||||||
namespace crossdesk {
|
namespace crossdesk {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class WgcPluginCapturer final : public ScreenCapturer {
|
||||||
|
public:
|
||||||
|
using CreateFn = ScreenCapturer* (*)();
|
||||||
|
using DestroyFn = void (*)(ScreenCapturer*);
|
||||||
|
|
||||||
|
static std::unique_ptr<ScreenCapturer> Create() {
|
||||||
|
std::filesystem::path plugin_path;
|
||||||
|
wchar_t module_path[MAX_PATH] = {0};
|
||||||
|
const DWORD len = GetModuleFileNameW(nullptr, module_path, MAX_PATH);
|
||||||
|
if (len == 0 || len >= MAX_PATH) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
plugin_path =
|
||||||
|
std::filesystem::path(module_path).parent_path() / L"wgc_plugin.dll";
|
||||||
|
|
||||||
|
HMODULE module = LoadLibraryW(plugin_path.c_str());
|
||||||
|
if (!module) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto create_fn = reinterpret_cast<CreateFn>(
|
||||||
|
GetProcAddress(module, "CrossDeskCreateWgcCapturer"));
|
||||||
|
auto destroy_fn = reinterpret_cast<DestroyFn>(
|
||||||
|
GetProcAddress(module, "CrossDeskDestroyWgcCapturer"));
|
||||||
|
if (!create_fn || !destroy_fn) {
|
||||||
|
FreeLibrary(module);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScreenCapturer* impl = create_fn();
|
||||||
|
if (!impl) {
|
||||||
|
FreeLibrary(module);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::unique_ptr<ScreenCapturer>(
|
||||||
|
new WgcPluginCapturer(module, impl, destroy_fn));
|
||||||
|
}
|
||||||
|
|
||||||
|
~WgcPluginCapturer() override {
|
||||||
|
if (impl_) {
|
||||||
|
destroy_fn_(impl_);
|
||||||
|
impl_ = nullptr;
|
||||||
|
}
|
||||||
|
if (module_) {
|
||||||
|
FreeLibrary(module_);
|
||||||
|
module_ = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int Init(const int fps, cb_desktop_data cb) override {
|
||||||
|
return impl_ ? impl_->Init(fps, std::move(cb)) : -1;
|
||||||
|
}
|
||||||
|
int Destroy() override { return impl_ ? impl_->Destroy() : 0; }
|
||||||
|
int Start(bool show_cursor) override {
|
||||||
|
return impl_ ? impl_->Start(show_cursor) : -1;
|
||||||
|
}
|
||||||
|
int Stop() override { return impl_ ? impl_->Stop() : 0; }
|
||||||
|
int Pause(int monitor_index) override {
|
||||||
|
return impl_ ? impl_->Pause(monitor_index) : -1;
|
||||||
|
}
|
||||||
|
int Resume(int monitor_index) override {
|
||||||
|
return impl_ ? impl_->Resume(monitor_index) : -1;
|
||||||
|
}
|
||||||
|
std::vector<DisplayInfo> GetDisplayInfoList() override {
|
||||||
|
return impl_ ? impl_->GetDisplayInfoList() : std::vector<DisplayInfo>{};
|
||||||
|
}
|
||||||
|
int SwitchTo(int monitor_index) override {
|
||||||
|
return impl_ ? impl_->SwitchTo(monitor_index) : -1;
|
||||||
|
}
|
||||||
|
int ResetToInitialMonitor() override {
|
||||||
|
return impl_ ? impl_->ResetToInitialMonitor() : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
WgcPluginCapturer(HMODULE module, ScreenCapturer* impl, DestroyFn destroy_fn)
|
||||||
|
: module_(module), impl_(impl), destroy_fn_(destroy_fn) {}
|
||||||
|
|
||||||
|
HMODULE module_ = nullptr;
|
||||||
|
ScreenCapturer* impl_ = nullptr;
|
||||||
|
DestroyFn destroy_fn_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
ScreenCapturerWin::ScreenCapturerWin() {}
|
ScreenCapturerWin::ScreenCapturerWin() {}
|
||||||
ScreenCapturerWin::~ScreenCapturerWin() { Destroy(); }
|
ScreenCapturerWin::~ScreenCapturerWin() { Destroy(); }
|
||||||
|
|
||||||
@@ -40,18 +131,21 @@ int ScreenCapturerWin::Init(const int fps, cb_desktop_data cb) {
|
|||||||
|
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
impl_ = std::make_unique<ScreenCapturerWgc>();
|
impl_ = WgcPluginCapturer::Create();
|
||||||
ret = impl_->Init(fps_, cb_);
|
impl_is_wgc_plugin_ = (impl_ != nullptr);
|
||||||
|
ret = impl_ ? impl_->Init(fps_, cb_) : -1;
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
LOG_INFO("Windows capturer: using WGC");
|
LOG_INFO("Windows capturer: using WGC plugin");
|
||||||
BuildCanonicalFromImpl();
|
BuildCanonicalFromImpl();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_WARN("Windows capturer: WGC init failed (ret={}), try DXGI", ret);
|
LOG_WARN("Windows capturer: WGC plugin init failed (ret={}), try DXGI", ret);
|
||||||
impl_.reset();
|
impl_.reset();
|
||||||
|
impl_is_wgc_plugin_ = false;
|
||||||
|
|
||||||
impl_ = std::make_unique<ScreenCapturerDxgi>();
|
impl_ = std::make_unique<ScreenCapturerDxgi>();
|
||||||
|
impl_is_wgc_plugin_ = false;
|
||||||
ret = impl_->Init(fps_, cb_);
|
ret = impl_->Init(fps_, cb_);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
LOG_INFO("Windows capturer: using DXGI Desktop Duplication");
|
LOG_INFO("Windows capturer: using DXGI Desktop Duplication");
|
||||||
@@ -63,6 +157,7 @@ int ScreenCapturerWin::Init(const int fps, cb_desktop_data cb) {
|
|||||||
impl_.reset();
|
impl_.reset();
|
||||||
|
|
||||||
impl_ = std::make_unique<ScreenCapturerGdi>();
|
impl_ = std::make_unique<ScreenCapturerGdi>();
|
||||||
|
impl_is_wgc_plugin_ = false;
|
||||||
ret = impl_->Init(fps_, cb_);
|
ret = impl_->Init(fps_, cb_);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
LOG_INFO("Windows capturer: using GDI BitBlt");
|
LOG_INFO("Windows capturer: using GDI BitBlt");
|
||||||
@@ -79,6 +174,7 @@ int ScreenCapturerWin::Destroy() {
|
|||||||
if (impl_) {
|
if (impl_) {
|
||||||
impl_->Destroy();
|
impl_->Destroy();
|
||||||
impl_.reset();
|
impl_.reset();
|
||||||
|
impl_is_wgc_plugin_ = false;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(alias_mutex_);
|
std::lock_guard<std::mutex> lock(alias_mutex_);
|
||||||
@@ -102,13 +198,14 @@ int ScreenCapturerWin::Start(bool show_cursor) {
|
|||||||
int s = cand->Start(show_cursor);
|
int s = cand->Start(show_cursor);
|
||||||
if (s == 0) {
|
if (s == 0) {
|
||||||
impl_ = std::move(cand);
|
impl_ = std::move(cand);
|
||||||
|
impl_is_wgc_plugin_ = false;
|
||||||
RebuildAliasesFromImpl();
|
RebuildAliasesFromImpl();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (dynamic_cast<ScreenCapturerWgc*>(impl_.get())) {
|
if (impl_is_wgc_plugin_) {
|
||||||
if (try_init_start(std::make_unique<ScreenCapturerDxgi>())) {
|
if (try_init_start(std::make_unique<ScreenCapturerDxgi>())) {
|
||||||
LOG_INFO("Windows capturer: fallback to DXGI");
|
LOG_INFO("Windows capturer: fallback to DXGI");
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class ScreenCapturerWin : public ScreenCapturer {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<ScreenCapturer> impl_;
|
std::unique_ptr<ScreenCapturer> impl_;
|
||||||
|
bool impl_is_wgc_plugin_ = false;
|
||||||
int fps_ = 60;
|
int fps_ = 60;
|
||||||
cb_desktop_data cb_;
|
cb_desktop_data cb_;
|
||||||
cb_desktop_data cb_orig_;
|
cb_desktop_data cb_orig_;
|
||||||
|
|||||||
29
src/screen_capturer/windows/wgc_plugin_api.h
Normal file
29
src/screen_capturer/windows/wgc_plugin_api.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* @Author: DI JUNKUN
|
||||||
|
* @Date: 2026-03-20
|
||||||
|
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _WGC_PLUGIN_API_H_
|
||||||
|
#define _WGC_PLUGIN_API_H_
|
||||||
|
|
||||||
|
#include "screen_capturer.h"
|
||||||
|
|
||||||
|
namespace crossdesk {
|
||||||
|
class ScreenCapturer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(CROSSDESK_WGC_PLUGIN_BUILD)
|
||||||
|
#define CROSSDESK_WGC_PLUGIN_API __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define CROSSDESK_WGC_PLUGIN_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
CROSSDESK_WGC_PLUGIN_API crossdesk::ScreenCapturer*
|
||||||
|
CrossDeskCreateWgcCapturer();
|
||||||
|
CROSSDESK_WGC_PLUGIN_API void CrossDeskDestroyWgcCapturer(
|
||||||
|
crossdesk::ScreenCapturer* capturer);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
13
src/screen_capturer/windows/wgc_plugin_entry.cpp
Normal file
13
src/screen_capturer/windows/wgc_plugin_entry.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include "screen_capturer_wgc.h"
|
||||||
|
#include "wgc_plugin_api.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
crossdesk::ScreenCapturer* CrossDeskCreateWgcCapturer() {
|
||||||
|
return new crossdesk::ScreenCapturerWgc();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrossDeskDestroyWgcCapturer(crossdesk::ScreenCapturer* capturer) {
|
||||||
|
delete capturer;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,15 +4,14 @@
|
|||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "rd_log.h"
|
#include "rd_log.h"
|
||||||
|
|
||||||
#define CHECK_INIT \
|
#define CHECK_INIT \
|
||||||
if (!is_initialized_) { \
|
if (!is_initialized_) { \
|
||||||
std::cout << "AE_NEED_INIT" << std::endl; \
|
LOG_ERROR("AE_NEED_INIT"); \
|
||||||
return 4; \
|
return 4; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHECK_CLOSED \
|
#define CHECK_CLOSED \
|
||||||
@@ -324,7 +323,7 @@ int WgcSessionImpl::Initialize() {
|
|||||||
if (is_initialized_) return 0;
|
if (is_initialized_) return 0;
|
||||||
|
|
||||||
if (!(d3d11_direct_device_ = CreateD3D11Device())) {
|
if (!(d3d11_direct_device_ = CreateD3D11Device())) {
|
||||||
std::cout << "AE_D3D_CREATE_DEVICE_FAILED" << std::endl;
|
LOG_ERROR("AE_D3D_CREATE_DEVICE_FAILED");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Submodule submodules/minirtc updated: 03a6449a11...6023fedf06
20
xmake.lua
20
xmake.lua
@@ -37,7 +37,7 @@ add_requires("tinyfiledialogs 3.15.1")
|
|||||||
|
|
||||||
if is_os("windows") then
|
if is_os("windows") then
|
||||||
add_requires("libyuv", "miniaudio 0.11.21")
|
add_requires("libyuv", "miniaudio 0.11.21")
|
||||||
add_links("Shell32", "windowsapp", "dwmapi", "User32", "kernel32",
|
add_links("Shell32", "dwmapi", "User32", "kernel32",
|
||||||
"SDL3-static", "gdi32", "winmm", "setupapi", "version",
|
"SDL3-static", "gdi32", "winmm", "setupapi", "version",
|
||||||
"Imm32", "iphlpapi", "d3d11", "dxgi")
|
"Imm32", "iphlpapi", "d3d11", "dxgi")
|
||||||
add_cxflags("/WX")
|
add_cxflags("/WX")
|
||||||
@@ -88,7 +88,9 @@ target("screen_capturer")
|
|||||||
add_includedirs("src/screen_capturer", {public = true})
|
add_includedirs("src/screen_capturer", {public = true})
|
||||||
if is_os("windows") then
|
if is_os("windows") then
|
||||||
add_packages("libyuv")
|
add_packages("libyuv")
|
||||||
add_files("src/screen_capturer/windows/*.cpp")
|
add_files("src/screen_capturer/windows/screen_capturer_dxgi.cpp",
|
||||||
|
"src/screen_capturer/windows/screen_capturer_gdi.cpp",
|
||||||
|
"src/screen_capturer/windows/screen_capturer_win.cpp")
|
||||||
add_includedirs("src/screen_capturer/windows", {public = true})
|
add_includedirs("src/screen_capturer/windows", {public = true})
|
||||||
elseif is_os("macosx") then
|
elseif is_os("macosx") then
|
||||||
add_files("src/screen_capturer/macosx/*.cpp",
|
add_files("src/screen_capturer/macosx/*.cpp",
|
||||||
@@ -199,6 +201,20 @@ target("gui")
|
|||||||
add_files("src/gui/windows/*.mm")
|
add_files("src/gui/windows/*.mm")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if is_os("windows") then
|
||||||
|
target("wgc_plugin")
|
||||||
|
set_kind("shared")
|
||||||
|
add_packages("libyuv")
|
||||||
|
add_deps("rd_log")
|
||||||
|
add_defines("CROSSDESK_WGC_PLUGIN_BUILD=1")
|
||||||
|
add_links("windowsapp")
|
||||||
|
add_files("src/screen_capturer/windows/screen_capturer_wgc.cpp",
|
||||||
|
"src/screen_capturer/windows/wgc_session_impl.cpp",
|
||||||
|
"src/screen_capturer/windows/wgc_plugin_entry.cpp")
|
||||||
|
add_includedirs("src/common", "src/screen_capturer",
|
||||||
|
"src/screen_capturer/windows")
|
||||||
|
end
|
||||||
|
|
||||||
target("crossdesk")
|
target("crossdesk")
|
||||||
set_kind("binary")
|
set_kind("binary")
|
||||||
add_deps("rd_log", "common", "gui")
|
add_deps("rd_log", "common", "gui")
|
||||||
|
|||||||
Reference in New Issue
Block a user