[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();
const size_t available = m_ivshmem->GetSize() - sizeof(KVMGFXHeader); uint8_t * data = m_memory + dataOffset;
if (m_capture->GetMaxFrameSize() > available) const size_t available = m_ivshmem->GetSize() - sizeof(KVMGFXHeader);
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,10 +149,40 @@ bool Service::Process()
return false; return false;
} }
// wait for the host to notify that is it is ready to proceed
ResetEvent(m_readyEvent);
bool eventDone = false;
while (!eventDone)
{
switch (WaitForSingleObject(m_readyEvent, 1000))
{
case WAIT_ABANDONED:
DEBUG_ERROR("Wait abandoned");
return false;
case WAIT_OBJECT_0:
eventDone = true;
break;
// if we timed out we just continue to ring until we get an answer or we are stopped
case WAIT_TIMEOUT:
continue;
case WAIT_FAILED:
DEBUG_ERROR("Wait failed");
return false;
default:
DEBUG_ERROR("Unknown error");
return false;
}
}
// copy the frame details into the header // copy the frame details into the header
header->width = frame.width; header->width = frame.width;
header->height = frame.height; header->height = frame.height;
header->stride = frame.stride; header->stride = frame.stride;
header->dataPos = dataOffset;
header->dataLen = frame.outSize; header->dataLen = frame.outSize;
// tell the host where the cursor is // tell the host where the cursor is
@ -158,38 +191,14 @@ bool Service::Process()
header->mouseX = cursorPos.x; header->mouseX = cursorPos.x;
header->mouseY = cursorPos.y; header->mouseY = cursorPos.y;
// wait for the host to notify that is it is ready to proceed if (!m_ivshmem->RingDoorbell(header->hostID, 0))
ResetEvent(m_readyEvent);
while(true)
{ {
if (!m_ivshmem->RingDoorbell(header->hostID, 0)) DEBUG_ERROR("Failed to ring doorbell");
{ return false;
DEBUG_ERROR("Failed to ring doorbell");
return false;
}
switch (WaitForSingleObject(m_readyEvent, 1000))
{
case WAIT_ABANDONED:
DEBUG_ERROR("Wait abandoned");
return false;
case WAIT_OBJECT_0:
return true;
// if we timed out we just continue to ring until we get an answer or we are stopped
case WAIT_TIMEOUT:
break;
case WAIT_FAILED:
DEBUG_ERROR("Wait failed");
return false;
default:
DEBUG_ERROR("Unknown error");
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;
}; };