[host] add initial buffering support

This commit is contained in:
Geoffrey McRae 2017-11-15 17:28:17 +11:00
parent 8140d347ff
commit 5899508a5b
3 changed files with 50 additions and 39 deletions

View File

@ -54,6 +54,7 @@ struct KVMGFXHeader
int32_t mouseX; // the initial mouse X position int32_t mouseX; // the initial mouse X position
int32_t mouseY; // the initial mouse Y position int32_t mouseY; // the initial mouse Y position
uint64_t dataLen; // total lengh of the data after this header uint64_t dataLen; // total lengh of the data after this header
uint64_t dataPos; // offset to the frame
}; };
#pragma pack(push,1) #pragma pack(push,1)

View File

@ -30,7 +30,8 @@ Service::Service() :
m_initialized(false), m_initialized(false),
m_readyEvent(INVALID_HANDLE_VALUE), m_readyEvent(INVALID_HANDLE_VALUE),
m_capture(NULL), m_capture(NULL),
m_memory(NULL) m_memory(NULL),
m_frameIndex(0)
{ {
m_ivshmem = IVSHMEM::Get(); m_ivshmem = IVSHMEM::Get();
} }
@ -66,7 +67,7 @@ bool Service::Initialize()
return false; return false;
} }
m_memory = m_ivshmem->GetMemory(); m_memory = static_cast<uint8_t*>(m_ivshmem->GetMemory());
if (!m_memory) if (!m_memory)
{ {
DEBUG_ERROR("Failed to get IVSHMEM memory"); DEBUG_ERROR("Failed to get IVSHMEM memory");
@ -82,7 +83,7 @@ bool Service::Initialize()
return false; return false;
} }
KVMGFXHeader * header = static_cast<KVMGFXHeader*>(m_memory); KVMGFXHeader * header = reinterpret_cast<KVMGFXHeader*>(m_memory);
// we save this as it might actually be valid // we save this as it might actually be valid
UINT16 hostID = header->hostID; UINT16 hostID = header->hostID;
@ -120,12 +121,14 @@ bool Service::Process()
if (!m_initialized) if (!m_initialized)
return false; return false;
KVMGFXHeader * header = static_cast<KVMGFXHeader *>(m_memory ); KVMGFXHeader * header = reinterpret_cast<KVMGFXHeader *>(m_memory);
void * data = static_cast<void *>(header + 1); const uint64_t dataOffset = sizeof(KVMGFXHeader) + m_frameIndex * m_capture->GetMaxFrameSize();
uint8_t * data = m_memory + dataOffset;
const size_t available = m_ivshmem->GetSize() - sizeof(KVMGFXHeader); const size_t available = m_ivshmem->GetSize() - sizeof(KVMGFXHeader);
if (m_capture->GetMaxFrameSize() > available)
if (dataOffset + m_capture->GetMaxFrameSize() > available)
{ {
DEBUG_ERROR("Frame could exceed buffer size!"); DEBUG_ERROR("Frame can exceed buffer size!");
return false; return false;
} }
@ -146,28 +149,11 @@ bool Service::Process()
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
POINT cursorPos;
GetCursorPos(&cursorPos);
header->mouseX = cursorPos.x;
header->mouseY = cursorPos.y;
// wait for the host to notify that is it is ready to proceed // wait for the host to notify that is it is ready to proceed
ResetEvent(m_readyEvent); ResetEvent(m_readyEvent);
while(true) bool eventDone = false;
while (!eventDone)
{ {
if (!m_ivshmem->RingDoorbell(header->hostID, 0))
{
DEBUG_ERROR("Failed to ring doorbell");
return false;
}
switch (WaitForSingleObject(m_readyEvent, 1000)) switch (WaitForSingleObject(m_readyEvent, 1000))
{ {
case WAIT_ABANDONED: case WAIT_ABANDONED:
@ -175,11 +161,12 @@ bool Service::Process()
return false; return false;
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
return true; eventDone = true;
break;
// if we timed out we just continue to ring until we get an answer or we are stopped // if we timed out we just continue to ring until we get an answer or we are stopped
case WAIT_TIMEOUT: case WAIT_TIMEOUT:
break; continue;
case WAIT_FAILED: case WAIT_FAILED:
DEBUG_ERROR("Wait failed"); DEBUG_ERROR("Wait failed");
@ -191,5 +178,27 @@ bool Service::Process()
} }
} }
// copy the frame details into the header
header->width = frame.width;
header->height = frame.height;
header->stride = frame.stride;
header->dataPos = dataOffset;
header->dataLen = frame.outSize;
// tell the host where the cursor is
POINT cursorPos;
GetCursorPos(&cursorPos);
header->mouseX = cursorPos.x;
header->mouseY = cursorPos.y;
if (!m_ivshmem->RingDoorbell(header->hostID, 0))
{
DEBUG_ERROR("Failed to ring doorbell");
return false;
}
if (++m_frameIndex == 2)
m_frameIndex = 0;
return true; return true;
} }

View File

@ -49,5 +49,6 @@ private:
IVSHMEM * m_ivshmem; IVSHMEM * m_ivshmem;
HANDLE m_readyEvent; HANDLE m_readyEvent;
ICapture * m_capture; ICapture * m_capture;
void * m_memory; uint8_t * m_memory;
int m_frameIndex;
}; };