diff --git a/host/Capture/NvFBC.cpp b/host/Capture/NvFBC.cpp new file mode 100644 index 00000000..34888e45 --- /dev/null +++ b/host/Capture/NvFBC.cpp @@ -0,0 +1,135 @@ +#include "NvFBC.h" + +#include + +#include "common\debug.h" +#include "Util.h" + +#ifdef _WIN64 +#define NVFBC_LIBRARY_NAME "NvFBC64.dll" +#else +#define NVFBC_LIBRARY_NAME "NvFBC.dll" +#endif + +namespace Capture +{ + + NvFBC::NvFBC() : + m_hDLL(NULL) + { + } + + NvFBC::~NvFBC() + { + } + + bool NvFBC::Initialize() + { + if (m_initialized) + DeInitialize(); + + std::string nvfbc = Util::GetSystemRoot() + "\\" + NVFBC_LIBRARY_NAME; + m_hDLL = LoadLibraryA(nvfbc.c_str()); + if (!m_hDLL) + { + DEBUG_ERROR("Failed to load the NvFBC library: %d - %s", GetLastError(), nvfbc.c_str()); + return false; + } + + m_fnCreateEx = (NvFBC_CreateFunctionExType )GetProcAddress(m_hDLL, "NvFBC_CreateEx" ); + m_fnSetGlobalFlags = (NvFBC_SetGlobalFlagsType )GetProcAddress(m_hDLL, "NvFBC_SetGlobalFlags"); + m_fnGetStatusEx = (NvFBC_GetStatusExFunctionType)GetProcAddress(m_hDLL, "NvFBC_GetStatusEx" ); + m_fnEnable = (NvFBC_EnableFunctionType )GetProcAddress(m_hDLL, "NvFBC_Enable" ); + + if (!m_fnCreateEx || !m_fnSetGlobalFlags || !m_fnGetStatusEx || !m_fnEnable) + { + DEBUG_ERROR("Unable to locate required entry points in %s", nvfbc.c_str()); + DeInitialize(); + return false; + } + + NvFBCStatusEx status; + ZeroMemory(&status, sizeof(NvFBCStatusEx)); + status.dwVersion = NVFBC_STATUS_VER; + status.dwAdapterIdx = 0; + + if (m_fnGetStatusEx(&status) != NVFBC_SUCCESS) + { + DEBUG_ERROR("Failed to get NvFBC status"); + DeInitialize(); + return false; + } + + if (!status.bIsCapturePossible) + { + DEBUG_ERROR("Capture is not possible, unsupported device or driver"); + DeInitialize(); + return false; + } + + if (!status.bCanCreateNow) + { + DEBUG_ERROR("Can not create an instance of NvFBC at this time"); + DeInitialize(); + return false; + } + + NvFBCCreateParams params; + ZeroMemory(¶ms, sizeof(NvFBCCreateParams)); + params.dwVersion = NVFBC_CREATE_PARAMS_VER; + params.dwInterfaceType = NVFBC_TO_SYS; + params.pDevice = NULL; + params.dwAdapterIdx = 0; + + // do not remove this + #include "NvFBCSpecial.h" + + if (m_fnCreateEx(¶ms) != NVFBC_SUCCESS) + { + DEBUG_ERROR("Failed to create an instance of NvFBC"); + DeInitialize(); + return false; + } + + m_maxCaptureWidth = params.dwMaxDisplayWidth; + m_maxCaptureHeight = params.dwMaxDisplayHeight; + + + m_initialized = true; + return true; + } + + void NvFBC::DeInitialize() + { + m_fnCreateEx = NULL; + m_fnSetGlobalFlags = NULL; + m_fnGetStatusEx = NULL; + m_fnEnable = NULL; + + FreeLibrary(m_hDLL); + m_hDLL = NULL; + + m_initialized = false; + } + + FrameType NvFBC::GetFrameType() + { + return FRAME_TYPE_RGB; + } + + FrameComp NvFBC::GetFrameCompression() + { + return FRAME_COMP_NONE; + } + + size_t NvFBC::GetMaxFrameSize() + { + return 0; + } + + bool NvFBC::GrabFrame(void * buffer, size_t bufferSize, size_t * outLen) + { + return false; + } + +}; \ No newline at end of file diff --git a/host/Capture/NvFBC.h b/host/Capture/NvFBC.h new file mode 100644 index 00000000..9899d8a9 --- /dev/null +++ b/host/Capture/NvFBC.h @@ -0,0 +1,36 @@ +#pragma once +#include "ICapture.h" + +#define W32_LEAN_AND_MEAN +#include + +#include +#include + +namespace Capture +{ + class NvFBC : public ICapture + { + public: + NvFBC(); + ~NvFBC(); + + bool Initialize(); + void DeInitialize(); + enum FrameType GetFrameType(); + enum FrameComp GetFrameCompression(); + size_t GetMaxFrameSize(); + bool GrabFrame(void * buffer, size_t bufferSize, size_t * outLen); + + private: + bool m_initialized; + HMODULE m_hDLL; + + NvFBC_CreateFunctionExType m_fnCreateEx; + NvFBC_SetGlobalFlagsType m_fnSetGlobalFlags; + NvFBC_GetStatusExFunctionType m_fnGetStatusEx; + NvFBC_EnableFunctionType m_fnEnable; + + DWORD m_maxCaptureWidth, m_maxCaptureHeight; + }; +}; \ No newline at end of file diff --git a/host/Capture/NvFBCSpecial.h b/host/Capture/NvFBCSpecial.h new file mode 100644 index 00000000..e69de29b diff --git a/host/CaptureFactory.h b/host/CaptureFactory.h index 89dff3b5..dd9e75fa 100644 --- a/host/CaptureFactory.h +++ b/host/CaptureFactory.h @@ -4,12 +4,13 @@ #include #include "ICapture.h" +#include "Capture\NvFBC.h" static class CaptureFactory { public: static ICapture * GetCaptureDevice() { - return NULL; + return new Capture::NvFBC(); } }; \ No newline at end of file diff --git a/host/ICapture.h b/host/ICapture.h index 54af9377..ed18f7d3 100644 --- a/host/ICapture.h +++ b/host/ICapture.h @@ -1,12 +1,12 @@ #pragma once -#include +#include "common/KVMGFXHeader.h" __interface ICapture { public: bool Initialize(); - bool DeInitialize(); + void DeInitialize(); enum FrameType GetFrameType(); enum FrameComp GetFrameCompression(); size_t GetMaxFrameSize(); diff --git a/host/IVSHMEM.cpp b/host/IVSHMEM.cpp index d5c88bee..e4e7782d 100644 --- a/host/IVSHMEM.cpp +++ b/host/IVSHMEM.cpp @@ -2,8 +2,8 @@ #include #include -#include -#include +#include "vendor\kvm-guest-drivers-windows\ivshmem\Public.h" +#include "common\debug.h" IVSHMEM * IVSHMEM::m_instance = NULL; diff --git a/host/Service.cpp b/host/Service.cpp index d8ab84a7..a83deeb4 100644 --- a/host/Service.cpp +++ b/host/Service.cpp @@ -1,8 +1,8 @@ #include "Service.h" #include "IVSHMEM.h" -#include -#include +#include "common\debug.h" +#include "common\KVMGFXHeader.h" #include "CaptureFactory.h" @@ -26,6 +26,14 @@ bool Service::Initialize() if (m_initialized) DeInitialize(); + m_capture = CaptureFactory::GetCaptureDevice(); + if (!m_capture || !m_capture->Initialize()) + { + DEBUG_ERROR("Failed to initialize capture interface"); + DeInitialize(); + return false; + } + if (!m_ivshmem->Initialize()) { DEBUG_ERROR("IVSHMEM failed to initalize"); @@ -56,14 +64,6 @@ bool Service::Initialize() return false; } - m_capture = CaptureFactory::GetCaptureDevice(); - if (!m_capture || !m_capture->Initialize()) - { - DEBUG_ERROR("Failed to initialize capture interface"); - DeInitialize(); - return false; - } - KVMGFXHeader * header = static_cast(m_memory); ZeroMemory(header, sizeof(KVMGFXHeader)); memcpy(header->magic, KVMGFX_HEADER_MAGIC, sizeof(KVMGFX_HEADER_MAGIC)); @@ -77,17 +77,18 @@ bool Service::Initialize() void Service::DeInitialize() { + if (m_readyEvent != INVALID_HANDLE_VALUE) + CloseHandle(m_readyEvent); + + m_memory = NULL; + m_ivshmem->DeInitialize(); + if (m_capture) { m_capture->DeInitialize(); m_capture = NULL; } - if (m_readyEvent != INVALID_HANDLE_VALUE) - CloseHandle(m_readyEvent); - - m_memory = NULL; - m_ivshmem->DeInitialize(); m_initialized = false; } diff --git a/host/Util.h b/host/Util.h new file mode 100644 index 00000000..7ab2560a --- /dev/null +++ b/host/Util.h @@ -0,0 +1,41 @@ +#pragma once +#include + +#include "common\debug.h" + +static class Util +{ +public: + static std::string GetSystemRoot() + { + std::string defaultPath; + + size_t pathSize; + char *libPath; + + if (_dupenv_s(&libPath, &pathSize, "SystemRoot") != 0) + { + DEBUG_ERROR("Unable to get the SystemRoot environment variable"); + return defaultPath; + } + + if (!pathSize) + { + DEBUG_ERROR("The SystemRoot environment variable is not set"); + return defaultPath; + } +#ifdef _WIN64 + defaultPath = std::string(libPath) + "\\System32"; +#else + if (IsWow64()) + { + defaultPath = std::string(libPath) + "\\Syswow64"; + } + else + { + defaultPath = std::string(libPath) + "\\System32"; + } +#endif + return defaultPath; + } +}; \ No newline at end of file diff --git a/host/kvm-ivshmem-host.vcxproj b/host/kvm-ivshmem-host.vcxproj index 53a210c5..dc6f1ce8 100644 --- a/host/kvm-ivshmem-host.vcxproj +++ b/host/kvm-ivshmem-host.vcxproj @@ -69,19 +69,19 @@ true - $(VC_IncludePath);$(WindowsSDK_IncludePath);..\ + $(VC_IncludePath);$(WindowsSDK_IncludePath);;C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc true - $(VC_IncludePath);$(WindowsSDK_IncludePath);..\ + $(VC_IncludePath);$(WindowsSDK_IncludePath);;C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc false - $(VC_IncludePath);$(WindowsSDK_IncludePath);..\ + $(VC_IncludePath);$(WindowsSDK_IncludePath);;C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc false - $(VC_IncludePath);$(WindowsSDK_IncludePath);..\ + $(VC_IncludePath);$(WindowsSDK_IncludePath);;C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\inc @@ -91,11 +91,13 @@ Disabled WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);DEBUG true + ..\;.\;%(AdditionalIncludeDirectories) Console true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;%(AdditionalDependencies) + C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\lib\NvAPI\$(PlatformTarget);%(AdditionalLibraryDirectories) @@ -106,11 +108,13 @@ Disabled _DEBUG;_WINDOWS;%(PreprocessorDefinitions);DEBUG true + ..\;.\;%(AdditionalIncludeDirectories) Console true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;%(AdditionalDependencies) + C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\lib\NvAPI\$(PlatformTarget);%(AdditionalLibraryDirectories) @@ -123,6 +127,7 @@ true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true + ..\;.\;%(AdditionalIncludeDirectories) Windows @@ -130,6 +135,7 @@ true true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;%(AdditionalDependencies) + C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\lib\NvAPI\$(PlatformTarget);%(AdditionalLibraryDirectories) @@ -142,6 +148,7 @@ true NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true + ..\;.\;%(AdditionalIncludeDirectories) Windows @@ -149,18 +156,22 @@ true true kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;%(AdditionalDependencies) + C:\Program Files %28x86%29\NVIDIA Corporation\NVIDIA Capture SDK\lib\NvAPI\$(PlatformTarget);%(AdditionalLibraryDirectories) + + + diff --git a/host/kvm-ivshmem-host.vcxproj.filters b/host/kvm-ivshmem-host.vcxproj.filters index 9221acdf..379721b9 100644 --- a/host/kvm-ivshmem-host.vcxproj.filters +++ b/host/kvm-ivshmem-host.vcxproj.filters @@ -13,6 +13,12 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {3a65593b-37a9-448d-acf0-6339dea46ed1} + + + {0a865d22-907e-44ea-a230-ad7ede7edeb0} + @@ -24,6 +30,9 @@ Source Files + + Source Files\Capture + @@ -38,5 +47,11 @@ Header Files + + Header Files\Capture + + + Header Files + \ No newline at end of file diff --git a/host/main.cpp b/host/main.cpp index d9950f9c..9f69b60d 100644 --- a/host/main.cpp +++ b/host/main.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include "common\debug.h" #include "Service.h"