Skip to content

Commit 8c303c8

Browse files
authored
Windows: Add a DDA grabber for much better performance (#1745)
* Add a DXDI DDA grabber * Change all names to camel case * Handle cropping and pixel decimation * Try more persistently to restart capture after an error occurred. These can happen when changing resolution, or resuming from sleep.
1 parent c0ddca3 commit 8c303c8

File tree

16 files changed

+535
-9
lines changed

16 files changed

+535
-9
lines changed

CHANGELOG.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
### Added
1515

1616
- Support gaps on Matrix Layout (#1696)
17+
- Windows: Added a new grabber that uses the DXGI DDA (Desktop Duplication API). This has much better performance than the DX grabber as it does more of its work on the GPU.
1718

1819
**JSON-API**
1920
- New subscription support for event updates, i.e. `Suspend, Resume, Idle, idleResume, Restart, Quit`.
2021
- Support direct or multiple instance addressing via single requests (#809)
2122
- Support of `serverinfo` subcommands: `getInfo, subscribe, unsubscribe, getSubscriptions, getSubscriptionCommands`
22-
- [Overview](https://github.com/hyperion-project/hyperion.ng/blob/API_Auth/doc/development/JSON-API%20_Commands_Overview.md) of API commands and subscription updates
23+
- [Overview](https://github.com/hyperion-project/hyperion.ng/blob/API_Auth/doc/development/JSON-API%20_Commands_Overview.md) of API commands and subscription updates
2324

2425
### Changed
2526

@@ -35,7 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3536
- Refactored JSON-API to ensure consistent authorization behaviour across sessions and single requests with token authorization.
3637
- Provide additional error details with API responses, esp. on JSON parsing, validation or token errors.
3738
- Generate random TANs for every API request from the Hyperion UI
38-
- Fixed: Handling of IP4 addresses wrapped in IPv6 for external network connections-
39+
- Fixed: Handling of IP4 addresses wrapped in IPv6 for external network connections-
3940

4041
### Removed
4142

@@ -135,7 +136,7 @@ Note: The wizard will configure an APIv2 capable bridge always with Entertainmen
135136
- Support streaming to individual WLED segments (requires WLED 0.13.3+).
136137
To allow segment streaming, enable "Realtime - Use main segment only" in WLED's Sync Interfaces setup screen
137138
- Allow to keep WLED powered on after streaming and restoring state
138-
- Allow to Disable / Enable all instances (#970) by
139+
- Allow to Disable / Enable all instances (#970) by
139140
- Suspend/Resume support for Linux and Windows (#1493,#1282, #978).
140141
Suspend/Resume/Restart is supported via API, UI, Systray and hyperion-remote
141142
- Idle scenario via Screen Locking (Linux/Windows), Screensaver invokation (Linux), hyperion-remote or API

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
6868
set(DEFAULT_AMLOGIC OFF)
6969
set(DEFAULT_DISPMANX OFF)
7070
set(DEFAULT_DX OFF)
71+
set(DEFAULT_DDA OFF)
7172
set(DEFAULT_MF OFF)
7273
set(DEFAULT_OSX OFF)
7374
set(DEFAULT_QT ON )
@@ -121,6 +122,7 @@ if(${CMAKE_SYSTEM} MATCHES "Linux")
121122
set(DEFAULT_CEC ON)
122123
elseif (WIN32)
123124
set(DEFAULT_DX ON)
125+
set(DEFAULT_DDA ON)
124126
set(DEFAULT_MF ON)
125127
else()
126128
set(DEFAULT_FB OFF)
@@ -227,6 +229,7 @@ if(HYPERION_LIGHT)
227229
SET ( DEFAULT_AMLOGIC OFF )
228230
SET ( DEFAULT_DISPMANX OFF )
229231
SET ( DEFAULT_DX OFF )
232+
SET ( DEFAULT_DDA OFF )
230233
SET ( DEFAULT_FB OFF )
231234
SET ( DEFAULT_MF OFF )
232235
SET ( DEFAULT_OSX OFF )
@@ -264,6 +267,9 @@ message(STATUS "ENABLE_DISPMANX = ${ENABLE_DISPMANX}")
264267
option(ENABLE_DX "Enable the DirectX grabber" ${DEFAULT_DX})
265268
message(STATUS "ENABLE_DX = ${ENABLE_DX}")
266269

270+
option(ENABLE_DDA "Enable the DXGI DDA grabber" ${DEFAULT_DDA})
271+
message(STATUS "ENABLE_DDA = ${ENABLE_DDA}")
272+
267273
if(ENABLE_AMLOGIC)
268274
set(ENABLE_FB ON)
269275
else()

HyperionConfig.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
// Define to enable the DirectX grabber
1010
#cmakedefine ENABLE_DX
1111

12+
// Define to enable the DXGI DDA (Desktop Duplication API) grabber
13+
#cmakedefine ENABLE_DDA
14+
1215
// Define to enable the framebuffer grabber
1316
// Define to enable the Audio grabber
1417
#cmakedefine ENABLE_AUDIO

doc/development/CompileHowto.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ We assume a 64bit Windows 10. Install the following;
128128
- [CMake (Windows win64-x64 installer)](https://cmake.org/download/) (Check: Add to PATH)
129129
- [Visual Studio 2022 Community Edition](https://visualstudio.microsoft.com/downloads/#visual-studio-community-2022)
130130
- Select 'Desktop development with C++'
131-
- On the right, just select `MSVC v143 VS 2022 C++ x64/x86-Buildtools` and latest `Windows 10 SDK`. Everything else is not needed.
131+
- On the right, just select `MSVC v143 VS 2022 C++ x64/x86-Buildtools`, `C++ ATL for latest v143 build tools (x86 & x64)` and latest `Windows 10 SDK`. Everything else is not needed.
132132
- [Win64 OpenSSL v1.1.1w](https://slproweb.com/products/Win32OpenSSL.html) ([direct link](https://slproweb.com/download/Win64OpenSSL-1_1_1w.exe))
133133
- [Python 3 (Windows x86-64 executable installer)](https://www.python.org/downloads/windows/) (Check: Add to PATH and Debug Symbols)
134134
- Open a console window and execute `pip install aqtinstall`.

include/grabber/GrabberConfig.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
#include <grabber/directx/directXGrabber.h>
2828
#endif
2929

30+
#ifdef ENABLE_DDA
31+
#include <grabber/dda/DDAGrabber.h>
32+
#endif
33+
3034
#if defined(ENABLE_X11)
3135
#include <grabber/x11/X11Grabber.h>
3236
#endif
@@ -35,10 +39,6 @@
3539
#include <grabber/xcb/XcbGrabber.h>
3640
#endif
3741

38-
#if defined(ENABLE_DX)
39-
#include <grabber/directx/DirectXGrabber.h>
40-
#endif
41-
4242
#if defined(ENABLE_FB)
4343
#include <grabber/framebuffer/FramebufferFrameGrabber.h>
4444
#endif

include/grabber/dda/DDAGrabber.h

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#pragma once
2+
3+
#include <QObject>
4+
#include <QJsonObject>
5+
6+
#include <hyperion/Grabber.h>
7+
#include <utils/ColorRgb.h>
8+
9+
class DDAGrabberImpl;
10+
11+
class DDAGrabber : public Grabber
12+
{
13+
public:
14+
DDAGrabber(int display = 0, int cropLeft = 0, int cropRight = 0, int cropTop = 0, int cropBottom = 0);
15+
16+
virtual ~DDAGrabber();
17+
18+
///
19+
/// Captures a single snapshot of the display and writes the data to the given image. The
20+
/// provided image should have the same dimensions as the configured values (_width and _height)
21+
///
22+
/// @param[out] image The snapped screenshot
23+
///
24+
int grabFrame(Image<ColorRgb> &image);
25+
26+
///
27+
/// @brief Set a new video mode
28+
///
29+
void setVideoMode(VideoMode mode) override;
30+
31+
///
32+
/// @brief Apply new width/height values, overwrite Grabber.h implementation
33+
///
34+
bool setWidthHeight(int /* width */, int /*height*/) override
35+
{
36+
return true;
37+
}
38+
39+
///
40+
/// @brief Apply new pixelDecimation
41+
///
42+
bool setPixelDecimation(int pixelDecimation) override;
43+
44+
///
45+
/// Set the crop values
46+
/// @param cropLeft Left pixel crop
47+
/// @param cropRight Right pixel crop
48+
/// @param cropTop Top pixel crop
49+
/// @param cropBottom Bottom pixel crop
50+
///
51+
void setCropping(int cropLeft, int cropRight, int cropTop, int cropBottom);
52+
53+
///
54+
/// @brief Apply display index
55+
///
56+
bool setDisplayIndex(int index) override;
57+
58+
/// @brief Discover QT screens available (for configuration).
59+
///
60+
/// @param[in] params Parameters used to overwrite discovery default behaviour
61+
///
62+
/// @return A JSON structure holding a list of devices found
63+
///
64+
QJsonObject discover(const QJsonObject &params);
65+
66+
private:
67+
///
68+
/// @brief Setup a new capture display, will free the previous one
69+
/// @return True on success, false if no display is found
70+
///
71+
bool restartCapture();
72+
73+
private:
74+
std::unique_ptr<DDAGrabberImpl> d;
75+
};

include/grabber/dda/DDAWrapper.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include <grabber/dda/DDAGrabber.h>
4+
#include <hyperion/GrabberWrapper.h>
5+
6+
class DDAWrapper : public GrabberWrapper
7+
{
8+
public:
9+
static constexpr const char *GRABBERTYPE = "DDA";
10+
11+
DDAWrapper(int updateRate_Hz = GrabberWrapper::DEFAULT_RATE_HZ, int display = 0,
12+
int pixelDecimation = GrabberWrapper::DEFAULT_PIXELDECIMATION, int cropLeft = 0, int cropRight = 0,
13+
int cropTop = 0, int cropBottom = 0);
14+
15+
DDAWrapper(const QJsonDocument &grabberConfig = QJsonDocument());
16+
17+
virtual ~DDAWrapper(){};
18+
19+
public slots:
20+
virtual void action();
21+
22+
private:
23+
DDAGrabber _grabber;
24+
};

libsrc/api/JsonInfo.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,10 @@ QJsonArray JsonInfo::discoverScreenInputs(const QJsonObject& params) const
592592
discoverGrabber<DirectXGrabber>(screenInputs, params);
593593
#endif
594594

595+
#ifdef ENABLE_DDA
596+
discoverGrabber<DDAGrabber>(screenInputs, params);
597+
#endif
598+
595599
#ifdef ENABLE_X11
596600
discoverGrabber<X11Grabber>(screenInputs, params);
597601
#endif

libsrc/grabber/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ if(ENABLE_DX)
3434
add_subdirectory(directx)
3535
endif(ENABLE_DX)
3636

37+
if(ENABLE_DDA)
38+
add_subdirectory(dda)
39+
endif(ENABLE_DDA)
40+
3741
if(ENABLE_AUDIO)
3842
add_subdirectory(audio)
3943
endif()

libsrc/grabber/dda/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
add_library(dda-grabber
2+
${CMAKE_SOURCE_DIR}/include/grabber/dda/DDAGrabber.h
3+
${CMAKE_SOURCE_DIR}/include/grabber/dda/DDAWrapper.h
4+
${CMAKE_SOURCE_DIR}/libsrc/grabber/dda/DDAGrabber.cpp
5+
${CMAKE_SOURCE_DIR}/libsrc/grabber/dda/DDAWrapper.cpp
6+
)
7+
8+
target_link_libraries(dda-grabber
9+
hyperion
10+
d3d11.lib
11+
dxgi.lib
12+
)

0 commit comments

Comments
 (0)