6#include <private/qabstractvideobuffer_p.h>
10#include <QtCore/private/qfactorycacheregistration_p.h>
15template <
typename Async>
16auto wait_for(Async
const& async, Windows::Foundation::TimeSpan
const&
timeout);
18#include <winrt/Windows.Foundation.h>
19#include <winrt/Windows.Foundation.Collections.h>
20#include <winrt/Windows.Graphics.Capture.h>
21#include <winrt/Windows.Graphics.DirectX.h>
22#include <winrt/Windows.Graphics.DirectX.Direct3D11.h>
23#include <Windows.Graphics.Capture.h>
24#include <Windows.Graphics.Capture.Interop.h>
25#include <windows.graphics.directx.direct3d11.interop.h>
30#include <lowlevelmonitorconfigurationapi.h>
31#include <physicalmonitorenumerationapi.h>
37#include <private/qmultimediautils_p.h>
38#include <private/qwindowsmultimediautils_p.h>
39#include <private/qcapturablewindow_p.h>
40#include <qpa/qplatformscreen_p.h>
43#include <system_error>
49 using namespace winrt::Windows::Graphics::Capture;
50 using namespace winrt::Windows::Graphics::DirectX;
51 using namespace winrt::Windows::Graphics::DirectX::Direct3D11;
56using namespace Windows::Graphics::DirectX::Direct3D11;
57using namespace std::chrono;
88 DXGI_MAPPED_RECT
rect = {};
91 DXGI_SURFACE_DESC
desc = {};
92 hr = m_surface->GetDesc(&
desc);
117 HRESULT hr = m_surface->Unmap();
126 winrt::com_ptr<IDXGISurface> m_surface;
134 winrt::GraphicsCaptureItem
item,
qreal maxFrameRate)
135 : m_capture(capture),
136 m_devicePool(devicePool),
137 m_session(devicePool.framePool.CreateCaptureSession(
item)),
151 m_session.IsCursorCaptureEnabled(
false);
152 m_session.StartCapture();
161 auto d3dFrame = m_devicePool.
framePool.TryGetNextFrame();
165 if (m_frameSize != d3dFrame.ContentSize()) {
166 m_frameSize = d3dFrame.ContentSize();
168 winrt::DirectXPixelFormat::R8G8B8A8UIntNormalized, 1,
169 d3dFrame.ContentSize());
172 auto d3dSurface = d3dFrame.Surface();
173 winrt::com_ptr<IDirect3DDxgiInterfaceAccess> dxgiInterfaceAccess{ d3dSurface.as<IDirect3DDxgiInterfaceAccess>() };
174 if (!dxgiInterfaceAccess)
177 winrt::com_ptr<IDXGISurface> dxgiSurface;
178 HRESULT hr = dxgiInterfaceAccess->GetInterface(__uuidof(dxgiSurface), dxgiSurface.put_void());
181 "Failed to get DXGI surface interface");
185 DXGI_SURFACE_DESC
desc = {};
186 hr = dxgiSurface->GetDesc(&
desc);
189 "Failed to get DXGI surface description");
193 D3D11_TEXTURE2D_DESC texDesc = {};
194 texDesc.Width =
desc.Width;
195 texDesc.Height =
desc.Height;
196 texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
197 texDesc.Usage = D3D11_USAGE_STAGING;
198 texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
199 texDesc.MiscFlags = 0;
200 texDesc.BindFlags = 0;
201 texDesc.ArraySize = 1;
202 texDesc.MipLevels = 1;
203 texDesc.SampleDesc = { 1, 0 };
205 winrt::com_ptr<ID3D11Texture2D>
texture;
206 hr = m_devicePool.
d3d11dev->CreateTexture2D(&texDesc,
nullptr,
texture.put());
212 winrt::com_ptr<ID3D11DeviceContext>
ctx;
213 m_devicePool.
d3d11dev->GetImmediateContext(
ctx.put());
214 ctx->CopyResource(
texture.as<ID3D11Resource>().get(), dxgiSurface.as<ID3D11Resource>().get());
225 winrt::GraphicsCaptureSession m_session;
226 winrt::Windows::Graphics::SizeInt32 m_frameSize;
231 qCDebug(qLcWindowCaptureUwp) <<
"Creating UWP screen capture";
239 winrt::com_ptr<ID3D11Device> d3d11dev;
241 D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN,
nullptr, 0,
242 nullptr, 0, D3D11_SDK_VERSION, d3d11dev.put(),
nullptr,
nullptr);
244 return {
"Failed to create ID3D11Device device" +
errorString(hr) };
246 winrt::com_ptr<IDXGIDevice> dxgiDevice;
247 hr = d3d11dev->QueryInterface(__uuidof(IDXGIDevice), dxgiDevice.put_void());
249 return {
"Failed to obtain dxgi for D3D11Device face" };
251 winrt::IDirect3DDevice iDirect3DDevice{};
252 hr = CreateDirect3D11DeviceFromDXGIDevice(
253 dxgiDevice.get(),
reinterpret_cast<::IInspectable **
>(winrt::put_abi(iDirect3DDevice)));
255 return {
"Failed to create IDirect3DDevice device" +
errorString(hr) };
257 auto pool = winrt::Direct3D11CaptureFramePool::Create(
258 iDirect3DDevice, winrt::DirectXPixelFormat::R8G8B8A8UIntNormalized, 1,
item.Size());
262 return {
"Failed to create capture frame pool" };
273 return {
"Cannot find nullptr screen" };
276 HMONITOR
handle = winScreen ? winScreen->handle() :
nullptr;
278 winrt::com_ptr<IDXGIFactory1>
factory;
279 HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1),
factory.put_void());
281 return {
"Failed to create IDXGIFactory" +
errorString(hr) };
283 winrt::com_ptr<IDXGIAdapter1> adapter;
284 for (
quint32 i = 0; SUCCEEDED(
factory->EnumAdapters1(
i, adapter.put()));
i++, adapter = {}) {
285 winrt::com_ptr<IDXGIOutput>
output;
287 DXGI_OUTPUT_DESC
desc = {};
296 return {
"Could not find screen adapter " +
screen->
name() };
301 HMONITOR
handle = MonitorFromWindow(wh, MONITOR_DEFAULTTONULL);
303 return {
"Cannot find window screen" };
305 winrt::com_ptr<IDXGIFactory1>
factory;
306 HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1),
factory.put_void());
308 return {
"Failed to create IDXGIFactory" +
errorString(hr) };
310 winrt::com_ptr<IDXGIAdapter1> adapter;
311 for (
quint32 i = 0; SUCCEEDED(
factory->EnumAdapters1(
i, adapter.put()));
i++, adapter = {}) {
312 winrt::com_ptr<IDXGIOutput>
output;
314 DXGI_OUTPUT_DESC
desc = {};
322 return {
"Could not find window screen adapter" };
327 auto factory = winrt::get_activation_factory<winrt::GraphicsCaptureItem>();
328 auto interop =
factory.as<IGraphicsCaptureItemInterop>();
330 winrt::GraphicsCaptureItem
item = {
nullptr};
331 HRESULT hr = interop->CreateForMonitor(
handle, __uuidof(ABI::Windows::Graphics::Capture::IGraphicsCaptureItem), winrt::put_abi(
item));
333 return "Failed to create capture item for monitor" +
errorString(hr);
340 auto factory = winrt::get_activation_factory<winrt::GraphicsCaptureItem>();
341 auto interop =
factory.as<IGraphicsCaptureItemInterop>();
343 winrt::GraphicsCaptureItem
item = {
nullptr};
344 HRESULT hr = interop->CreateForWindow(
handle, __uuidof(ABI::Windows::Graphics::Capture::IGraphicsCaptureItem), winrt::put_abi(
item));
346 return "Failed to create capture item for window" +
errorString(hr);
353 if (hwnd == GetShellWindow())
354 return "Cannot capture the shell window";
359 return "Cannot capture windows without a class name";
361 if (!IsWindowVisible(hwnd))
362 return "Cannot capture invisible windows";
364 if (GetParent(hwnd) != 0)
365 return "Can only capture root windows";
367 LONG style = GetWindowLong(hwnd, GWL_STYLE);
368 if (style & WS_DISABLED)
369 return "Cannot capture disabled windows";
371 LONG exStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
372 if (exStyle & WS_EX_TOOLWINDOW)
373 return "No tooltips";
375 DWORD cloaked = FALSE;
376 HRESULT hr = DwmGetWindowAttribute(hwnd, DWMWA_CLOAKED, &cloaked,
sizeof(cloaked));
377 if (SUCCEEDED(hr) && cloaked == DWM_CLOAKED_SHELL)
378 return "Cannot capture cloaked windows";
386 if (GetNumberOfPhysicalMonitorsFromHMONITOR(
handle, &
count)) {
390 MC_TIMING_REPORT screenTiming = {};
391 if (GetTimingReport(monitor.hPhysicalMonitor, &screenTiming))
392 return qreal(screenTiming.dwVerticalFrequencyInHZ) / 100.;
401 if (
bool(m_grabber) == active)
413 const auto windowHandle =
reinterpret_cast<HWND
>(
handle ?
handle->id : 0);
416 if (!
error.isEmpty()) {
446 m_grabber = std::make_unique<Grabber>(*
this, maybePool.value(), maybeItem.value(), refreshRate);
454 return winrt::GraphicsCaptureSession::IsSupported();
464#include "qffmpegwindowcapture_uwp.moc"
The QAbstractVideoBuffer class is an abstraction for video data. \inmodule QtMultimedia.
static const QCapturableWindowPrivate * handle(const QCapturableWindow &window)
void addFrameCallback(Object &object, Method method)
void errorUpdated(QPlatformSurfaceCapture::Error error, const QString &description)
void setFrameRate(qreal rate)
Grabber(QFFmpegWindowCaptureUwp &capture, DeviceFramePool &devicePool, winrt::GraphicsCaptureItem item, qreal maxFrameRate)
QVideoFrame grabFrame() override
bool setActiveInternal(bool active) override
QFFmpegWindowCaptureUwp()
static bool isSupported()
~QFFmpegWindowCaptureUwp() override
QVideoFrameFormat frameFormat() const override
Native interface to QScreen, to be retrieved from QPlatformIntegration. \inmodule QtGui.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
The QScreen class is used to query screen properties. \inmodule QtGui.
QString name
a user presentable string representing the screen
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
~QUwpTextureVideoBuffer()
QVideoFrame::MapMode mapMode() const override
QUwpTextureVideoBuffer(winrt::com_ptr< IDXGISurface > &&surface)
MapData map(QVideoFrame::MapMode mode) override
Independently maps the planes of a video buffer to memory.
void unmap() override
Releases the memory mapped by the map() function.
The QVideoFrame class represents a frame of video data.
MapMode
Enumerates how a video buffer's data is mapped to system memory.
Combined button and popup list for selecting options.
auto wait_for(Async const &async, Windows::Foundation::TimeSpan const &timeout)
static qreal getMonitorRefreshRateHz(HMONITOR handle)
static QMaybe< Monitor > findScreenForWindow(HWND wh)
static QString isCapturableWindow(HWND hwnd)
static QMaybe< DeviceFramePool > createCaptureFramePool(IDXGIAdapter1 *adapter, const winrt::GraphicsCaptureItem &item)
static QMaybe< winrt::GraphicsCaptureItem > createWindowCaptureItem(HWND handle)
static QMaybe< winrt::GraphicsCaptureItem > createScreenCaptureItem(HMONITOR handle)
static QMaybe< Monitor > findScreen(const QScreen *screen)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLuint64 GLenum void * handle
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLbitfield GLuint64 timeout
[4]
GLint GLsizei GLsizei GLenum format
GLsizei GLsizei GLchar * source
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
QT_BEGIN_NAMESPACE typedef uchar * output
const char className[16]
[1]
QItemEditorFactory * factory
winrt::Direct3D11CaptureFramePool framePool
winrt::IDirect3DDevice iDirect3DDevice
winrt::com_ptr< ID3D11Device > d3d11dev
winrt::com_ptr< IDXGIAdapter1 > adapter