[host] NvFBC is now functional

This commit is contained in:
Geoffrey McRae 2017-11-01 01:46:47 +11:00
parent 85f39b7070
commit ffbd89fb77
8 changed files with 143 additions and 24 deletions

2
host/.gitignore vendored
View File

@ -1,4 +1,4 @@
a## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.
## ##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

View File

@ -15,7 +15,9 @@ namespace Capture
{ {
NvFBC::NvFBC() : NvFBC::NvFBC() :
m_hDLL(NULL) m_initialized(false),
m_hDLL(NULL),
m_nvFBC(NULL)
{ {
} }
@ -81,8 +83,6 @@ namespace Capture
params.pDevice = NULL; params.pDevice = NULL;
params.dwAdapterIdx = 0; params.dwAdapterIdx = 0;
// do not remove this
#include "NvFBCSpecial.h"
if (m_fnCreateEx(&params) != NVFBC_SUCCESS) if (m_fnCreateEx(&params) != NVFBC_SUCCESS)
{ {
@ -91,44 +91,135 @@ namespace Capture
return false; return false;
} }
m_maxCaptureWidth = params.dwMaxDisplayWidth; m_maxCaptureWidth = params.dwMaxDisplayWidth;
m_maxCaptureHeight = params.dwMaxDisplayHeight; m_maxCaptureHeight = params.dwMaxDisplayHeight;
m_nvFBC = static_cast<NvFBCToSys *>(params.pNvFBC);
NVFBC_TOSYS_SETUP_PARAMS setupParams;
ZeroMemory(&setupParams, sizeof(NVFBC_TOSYS_SETUP_PARAMS));
setupParams.dwVersion = NVFBC_TOSYS_SETUP_PARAMS_VER;
setupParams.eMode = NVFBC_TOSYS_RGB;
setupParams.bWithHWCursor = TRUE;
setupParams.bDiffMap = FALSE;
setupParams.ppBuffer = (void **)&m_frameBuffer;
setupParams.ppDiffMap = NULL;
m_initialized = true; if (m_nvFBC->NvFBCToSysSetUp(&setupParams) != NVFBC_SUCCESS)
return true; {
DEBUG_ERROR("NvFBCToSysSetUp Failed");
DeInitialize();
return false;
}
// this is required according to NVidia sample code
Sleep(100);
ZeroMemory(&m_grabFrameParams, sizeof(NVFBC_TOSYS_GRAB_FRAME_PARAMS));
ZeroMemory(&m_grabInfo, sizeof(NvFBCFrameGrabInfo));
m_grabFrameParams.dwVersion = NVFBC_TOSYS_GRAB_FRAME_PARAMS_VER;
m_grabFrameParams.dwFlags = NVFBC_TOSYS_NOFLAGS;
m_grabFrameParams.dwStartX = 0;
m_grabFrameParams.dwStartY = 0;
m_grabFrameParams.eGMode = NVFBC_TOSYS_SOURCEMODE_SCALE;
m_grabFrameParams.pNvFBCFrameGrabInfo = &m_grabInfo;
m_initialized = true;
return true;
} }
void NvFBC::DeInitialize() void NvFBC::DeInitialize()
{ {
m_fnCreateEx = NULL; m_frameBuffer = NULL;
m_fnSetGlobalFlags = NULL;
m_fnGetStatusEx = NULL;
m_fnEnable = NULL;
FreeLibrary(m_hDLL); if (m_nvFBC)
m_hDLL = NULL; {
m_nvFBC->NvFBCToSysRelease();
m_nvFBC = NULL;
}
m_maxCaptureWidth = 0;
m_maxCaptureHeight = 0;
m_fnCreateEx = NULL;
m_fnSetGlobalFlags = NULL;
m_fnGetStatusEx = NULL;
m_fnEnable = NULL;
if (m_hDLL)
{
FreeLibrary(m_hDLL);
m_hDLL = NULL;
}
m_initialized = false; m_initialized = false;
} }
FrameType NvFBC::GetFrameType() FrameType NvFBC::GetFrameType()
{ {
if (!m_initialized)
return FRAME_TYPE_INVALID;
return FRAME_TYPE_RGB; return FRAME_TYPE_RGB;
} }
FrameComp NvFBC::GetFrameCompression() FrameComp NvFBC::GetFrameCompression()
{ {
if (!m_initialized)
return FRAME_COMP_NONE;
return FRAME_COMP_NONE; return FRAME_COMP_NONE;
} }
size_t NvFBC::GetMaxFrameSize() size_t NvFBC::GetMaxFrameSize()
{ {
return 0; if (!m_initialized)
return false;
return m_maxCaptureWidth * m_maxCaptureHeight * 3;
} }
bool NvFBC::GrabFrame(void * buffer, size_t bufferSize, size_t * outLen) bool NvFBC::GrabFrame(struct FrameInfo & frame)
{ {
if (!m_initialized)
return false;
const HWND hDesktop = GetDesktopWindow();
RECT desktop;
GetWindowRect(hDesktop, &desktop);
m_grabFrameParams.dwTargetWidth = desktop.right;
m_grabFrameParams.dwTargetHeight = desktop.bottom;
for(int i = 0; i < 2; ++i)
{
NVFBCRESULT status = m_nvFBC->NvFBCToSysGrabFrame(&m_grabFrameParams);
if (status == NVFBC_SUCCESS)
{
frame.width = m_grabInfo.dwWidth;
frame.height = m_grabInfo.dwHeight;
frame.stride = m_grabInfo.dwBufferWidth;
frame.outSize = m_grabInfo.dwBufferWidth * m_grabInfo.dwHeight * 3;
memcpy(frame.buffer, m_frameBuffer, frame.outSize);
return true;
}
if (status == NVFBC_ERROR_DYNAMIC_DISABLE)
{
DEBUG_ERROR("NvFBC was disabled by someone else");
return false;
}
if (status == NVFBC_ERROR_INVALIDATED_SESSION)
{
DEBUG_WARN("Session was invalidated, attempting to restart");
DeInitialize();
if (!Initialize())
{
DEBUG_ERROR("Failed to re-iniaialize");
return false;
}
}
}
DEBUG_ERROR("Failed to grab frame");
return false; return false;
} }

View File

@ -20,7 +20,7 @@ namespace Capture
enum FrameType GetFrameType(); enum FrameType GetFrameType();
enum FrameComp GetFrameCompression(); enum FrameComp GetFrameCompression();
size_t GetMaxFrameSize(); size_t GetMaxFrameSize();
bool GrabFrame(void * buffer, size_t bufferSize, size_t * outLen); bool GrabFrame(struct FrameInfo & frame);
private: private:
bool m_initialized; bool m_initialized;
@ -32,5 +32,9 @@ namespace Capture
NvFBC_EnableFunctionType m_fnEnable; NvFBC_EnableFunctionType m_fnEnable;
DWORD m_maxCaptureWidth, m_maxCaptureHeight; DWORD m_maxCaptureWidth, m_maxCaptureHeight;
NvFBCToSys * m_nvFBC;
void * m_frameBuffer;
NvFBCFrameGrabInfo m_grabInfo;
NVFBC_TOSYS_GRAB_FRAME_PARAMS m_grabFrameParams;
}; };
}; };

View File

@ -6,7 +6,7 @@
#include "ICapture.h" #include "ICapture.h"
#include "Capture\NvFBC.h" #include "Capture\NvFBC.h"
static class CaptureFactory class CaptureFactory
{ {
public: public:
static ICapture * GetCaptureDevice() static ICapture * GetCaptureDevice()

View File

@ -2,6 +2,16 @@
#include "common/KVMGFXHeader.h" #include "common/KVMGFXHeader.h"
struct FrameInfo
{
unsigned int width;
unsigned int height;
unsigned int stride;
void * buffer;
size_t bufferSize;
size_t outSize;
};
__interface ICapture __interface ICapture
{ {
public: public:
@ -10,5 +20,5 @@ public:
enum FrameType GetFrameType(); enum FrameType GetFrameType();
enum FrameComp GetFrameCompression(); enum FrameComp GetFrameCompression();
size_t GetMaxFrameSize(); size_t GetMaxFrameSize();
bool GrabFrame(void * buffer, size_t bufferSize, size_t * outLen); bool GrabFrame(struct FrameInfo & frame);
}; };

View File

@ -65,11 +65,16 @@ bool Service::Initialize()
} }
KVMGFXHeader * header = static_cast<KVMGFXHeader*>(m_memory); KVMGFXHeader * header = static_cast<KVMGFXHeader*>(m_memory);
// we save this as it might actually be valid
UINT16 hostID = header->hostID;
ZeroMemory(header, sizeof(KVMGFXHeader)); ZeroMemory(header, sizeof(KVMGFXHeader));
memcpy(header->magic, KVMGFX_HEADER_MAGIC, sizeof(KVMGFX_HEADER_MAGIC)); memcpy(header->magic, KVMGFX_HEADER_MAGIC, sizeof(KVMGFX_HEADER_MAGIC));
header->version = 2; header->version = 2;
header->guestID = m_ivshmem->GetPeerID(); header->guestID = m_ivshmem->GetPeerID();
header->hostID = hostID;
m_initialized = true; m_initialized = true;
return true; return true;
@ -109,17 +114,26 @@ bool Service::Process(HANDLE stopEvent)
// setup the header // setup the header
header->frameType = m_capture->GetFrameType(); header->frameType = m_capture->GetFrameType();
header->compType = m_capture->GetFrameCompression(); header->compType = m_capture->GetFrameCompression();
header->dataLen = 0;
FrameInfo frame;
frame.buffer = data;
frame.bufferSize = m_ivshmem->GetSize() - sizeof(KVMGFXHeader);
// capture a frame of data // capture a frame of data
if (!m_capture->GrabFrame( if (!m_capture->GrabFrame(frame))
data,
m_ivshmem->GetSize() - sizeof(KVMGFXHeader),
&header->dataLen))
{ {
header->dataLen = 0;
DEBUG_ERROR("Capture failed"); DEBUG_ERROR("Capture failed");
return false; return false;
} }
// copy the frame details into the header
header->width = frame.width;
header->height = frame.height;
header->stride = frame.stride;
header->dataLen = frame.outSize;
// tell the host where the cursor is // tell the host where the cursor is
POINT cursorPos; POINT cursorPos;
GetCursorPos(&cursorPos); GetCursorPos(&cursorPos);

View File

@ -3,7 +3,7 @@
#include "common\debug.h" #include "common\debug.h"
static class Util class Util
{ {
public: public:
static std::string GetSystemRoot() static std::string GetSystemRoot()