Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error code 7fffbffe #6

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions src/ScreenCapture/ScreenCapture.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// ScreenCapture.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <pch.h>
#include <iostream>
#include <stdio.h>

#include <winrt/Windows.Graphics.Capture.h>
#include <windows.graphics.capture.interop.h>
#include <windows.graphics.capture.h>
Expand All @@ -24,7 +21,6 @@ extern "C"
{
HRESULT __stdcall CreateDirect3D11DeviceFromDXGIDevice(::IDXGIDevice* dxgiDevice,
::IInspectable** graphicsDevice);

}

inline auto CreateCaptureItemForMonitor(HMONITOR hmon)
Expand All @@ -48,28 +44,28 @@ class EnumInfo

inline EnumInfo FindMonitor(int x, int y, int width, int height, bool verbose) {

EnumInfo result{NULL, x, y, width, height, verbose};
EnumInfo result{ NULL, x, y, width, height, verbose };
EnumDisplayMonitors(nullptr, nullptr, [](HMONITOR hmon, HDC, LPRECT, LPARAM lparam)
{
EnumInfo* info = (EnumInfo*)lparam;
MONITORINFOEX monitorInfo = { sizeof(monitorInfo) };
GetMonitorInfo(hmon, &monitorInfo);
if (monitorInfo.rcMonitor.left <= info->x && monitorInfo.rcMonitor.right >= info->x + info->w &&
monitorInfo.rcMonitor.top <= info->y && monitorInfo.rcMonitor.bottom >= info->y + info->h)
{
info->hmon = hmon;
{
info->hmon = hmon;
info->x -= monitorInfo.rcMonitor.left;
info->y -= monitorInfo.rcMonitor.top;
return FALSE;
}
return FALSE;
}
if (info->verbose) {
printf("Found monitor at (%d, %d) size (%d x %d)\n",
monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top,
monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top);
}
return TRUE;
}, (LPARAM)& result);
}, (LPARAM)&result);

return result;
}
Expand Down Expand Up @@ -104,6 +100,8 @@ extern "C" {

int __declspec(dllexport) __stdcall StartCapture(int x, int y, int width, int height, bool captureCursor)
{
printf("StartCapture called with parameters: x=%d, y=%d, width=%d, height=%d, captureCursor=%d\n", x, y, width, height, captureCursor);

auto mon = FindMonitor(x, y, width, height, false);
if (mon.hmon == nullptr)
{
Expand All @@ -116,24 +114,37 @@ extern "C" {
StopCapture();
winrt::com_ptr<ID3D11Device> d3dDevice;
HRESULT hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, D3D11_SDK_VERSION, d3dDevice.put(), nullptr, nullptr);
winrt::check_hresult(hr);
if (FAILED(hr)) {
printf("D3D11CreateDevice failed with HRESULT: %ld\n", hr);
return hr;
}
printf("D3D11CreateDevice succeeded.\n");

auto dxgiDevice = d3dDevice.as<IDXGIDevice>();
printf("Created IDXGIDevice.\n");

auto device = CreateDirect3DDevice(dxgiDevice.get());
printf("Created Direct3DDevice.\n");

winrt::GraphicsCaptureItem item{ nullptr };
item = CreateCaptureItemForMonitor(mon.hmon);
if (!item) {
printf("CreateCaptureItemForMonitor failed.\n");
return -1;
}
printf("CreateCaptureItemForMonitor succeeded.\n");

RECT bounds = { mon.x, mon.y, mon.x + width, mon.y + height };
m_capture = std::make_unique<SimpleCapture>();
printf("Starting capture with bounds: (%d, %d) to (%d, %d)\n", bounds.left, bounds.top, bounds.right, bounds.bottom);
return m_capture->StartCapture(device, item, winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized, bounds, captureCursor);

}
catch (winrt::hresult_error const& ex) {
int hr = (int)(ex.code());
printf("Capture failed %d\n", hr);
printf("Capture failed with HRESULT: %ld, Message: %ws\n", hr, ex.message().c_str());
return hr;
}
return 0;
}
}
}
79 changes: 45 additions & 34 deletions src/ScreenCapture/SimpleCapture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ namespace winrt
using namespace Windows::UI::Composition;
}


namespace util {

struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1"))
Expand Down Expand Up @@ -92,7 +91,7 @@ class CriticalSectionGuard
{
public:
CriticalSectionGuard() { EnterCriticalSection(&m_mutex); }
~CriticalSectionGuard() { LeaveCriticalSection(&m_mutex); }
~CriticalSectionGuard() { LeaveCriticalSection(&m_mutex); }
};

SimpleCapture::SimpleCapture()
Expand All @@ -107,6 +106,8 @@ int SimpleCapture::StartCapture(
RECT bounds,
bool captureCursor)
{
printf("StartCapture: Initializing capture...\n");

m_frameId = 0;
m_buffer = nullptr;
m_size = 0;
Expand All @@ -121,42 +122,52 @@ int SimpleCapture::StartCapture(
auto height = m_bounds.bottom - m_bounds.top;
uint32_t size = width * height * CHANNELS;

m_d3dDevice = util::GetDXGIInterfaceFromObject<ID3D11Device>(m_device);
m_d3dDevice->GetImmediateContext(m_d3dContext.put());
try {
m_d3dDevice = util::GetDXGIInterfaceFromObject<ID3D11Device>(m_device);
printf("StartCapture: Created DXGI interface from device.\n");

m_swapChain = util::CreateDXGISwapChain(m_d3dDevice, static_cast<uint32_t>(m_item.Size().Width), static_cast<uint32_t>(m_item.Size().Height),
static_cast<DXGI_FORMAT>(m_pixelFormat), 2);
m_d3dDevice->GetImmediateContext(m_d3dContext.put());
printf("StartCapture: Obtained immediate context.\n");

// Creating our frame pool with 'Create' instead of 'CreateFreeThreaded'
// means that the frame pool's FrameArrived event is called on the thread
// the frame pool was created on. This also means that the creating thread
// must have a DispatcherQueue. If you use this method, it's best not to do
// it on the UI thread.
m_framePool = winrt::Direct3D11CaptureFramePool::CreateFreeThreaded(m_device, m_pixelFormat, 2, m_item.Size());
m_session = m_framePool.CreateCaptureSession(m_item);
if (!m_session.IsSupported())
{
printf("CreateCaptureSession is not supported on this version of Windows.\n");
return -1;
}
m_session.IsCursorCaptureEnabled(captureCursor);
m_swapChain = util::CreateDXGISwapChain(m_d3dDevice, static_cast<uint32_t>(m_item.Size().Width), static_cast<uint32_t>(m_item.Size().Height),
static_cast<DXGI_FORMAT>(m_pixelFormat), 2);
printf("StartCapture: Created DXGI swap chain.\n");

auto session3 = m_session.as<winrt::Windows::Graphics::Capture::IGraphicsCaptureSession3>();
if (session3 != nullptr) {
session3.IsBorderRequired(false);
}
else {
printf("Cannot disable the capture border on this version of windows\n");
}
m_framePool = winrt::Direct3D11CaptureFramePool::CreateFreeThreaded(m_device, m_pixelFormat, 2, m_item.Size());
m_session = m_framePool.CreateCaptureSession(m_item);
printf("StartCapture: Created frame pool and capture session.\n");

if (!m_session.IsSupported())
{
printf("StartCapture: CreateCaptureSession is not supported on this version of Windows.\n");
return -1;
}
m_session.IsCursorCaptureEnabled(captureCursor);

auto session3 = m_session.try_as<winrt::Windows::Graphics::Capture::IGraphicsCaptureSession3>();
if (session3) {
session3.IsBorderRequired(false);
printf("StartCapture: Disabled capture border.\n");
}
else {
printf("StartCapture: IGraphicsCaptureSession3 not available. Cannot disable capture border.\n");
}

m_lastSize = m_item.Size();
m_frameArrivedToken = m_framePool.FrameArrived({ this, &SimpleCapture::OnFrameArrived });
m_lastSize = m_item.Size();
m_frameArrivedToken = m_framePool.FrameArrived({ this, &SimpleCapture::OnFrameArrived });
printf("StartCapture: Frame arrived event handler set.\n");

m_session.StartCapture();
m_session.StartCapture();
printf("StartCapture: Capture session started.\n");
}
catch (winrt::hresult_error const& ex) {
int hr = (int)(ex.code());
printf("StartCapture: Capture initialization failed with HRESULT: %ld, Message: %ws\n", hr, ex.message().c_str());
return hr;
}
return size;
}


unsigned long long SimpleCapture::ReadNextFrame(char* buffer, unsigned int size)
{
m_buffer = buffer;
Expand Down Expand Up @@ -397,11 +408,11 @@ void SimpleCapture::ReadPixels(ID3D11Texture2D* acquiredDesktopImage) {

// Handle full screen with a single memcpy, technically it can
// handle any height so long as it is full width and starting at top left.
if (x == 0 && y == 0 && w == desc.Width)
if (x == 0 && y == 0 && w == desc.Width)
{
::memcpy(ptr, src, min(m_size, captureSize));
}
else
::memcpy(ptr, src, min(m_size, captureSize));
}
else
{
// Copy the cropped image out of the full monitor frame.
auto expectedSize = w * h * CHANNELS;
Expand Down