[host] add timeout return value for repeated frame

This is to allow a repeat frame without incuring an additional
memory copy when the frame is already in shared memory.
This commit is contained in:
Geoffrey McRae 2018-07-26 03:08:52 +10:00
parent 5cabf155ab
commit 343983d9af
3 changed files with 61 additions and 42 deletions

View file

@ -52,6 +52,7 @@ struct FrameInfo
enum GrabStatus enum GrabStatus
{ {
GRAB_STATUS_OK, GRAB_STATUS_OK,
GRAB_STATUS_TIMEOUT,
GRAB_STATUS_REINIT, GRAB_STATUS_REINIT,
GRAB_STATUS_CURSOR, GRAB_STATUS_CURSOR,
GRAB_STATUS_ERROR GRAB_STATUS_ERROR

View file

@ -87,13 +87,6 @@ bool Service::Initialize(ICapture * captureDevice)
return false; return false;
} }
m_timer = CreateWaitableTimer(NULL, TRUE, NULL);
if (!m_timer)
{
DEBUG_ERROR("Failed to create waitable timer");
return false;
}
// Create the cursor thread // Create the cursor thread
m_cursorThread = CreateThread(NULL, 0, _CursorThread, this, 0, NULL); m_cursorThread = CreateThread(NULL, 0, _CursorThread, this, 0, NULL);
m_cursorEvent = CreateEvent (NULL, FALSE, FALSE, L"CursorEvent"); m_cursorEvent = CreateEvent (NULL, FALSE, FALSE, L"CursorEvent");
@ -108,6 +101,7 @@ bool Service::Initialize(ICapture * captureDevice)
ZeroMemory(&m_shmHeader->cursor, sizeof(KVMFRCursor)); ZeroMemory(&m_shmHeader->cursor, sizeof(KVMFRCursor));
m_shmHeader->flags &= ~KVMFR_HEADER_FLAG_RESTART; m_shmHeader->flags &= ~KVMFR_HEADER_FLAG_RESTART;
m_haveFrame = false;
m_initialized = true; m_initialized = true;
return true; return true;
} }
@ -120,47 +114,45 @@ bool Service::InitPointers()
m_shmHeader = reinterpret_cast<KVMFRHeader *>(m_memory); m_shmHeader = reinterpret_cast<KVMFRHeader *>(m_memory);
m_cursorData = (uint8_t *)ALIGN_UP(m_memory + sizeof(KVMFRHeader)); m_cursorData = (uint8_t *)ALIGN_UP(m_memory + sizeof(KVMFRHeader));
m_cursorDataSize = 1048576; // 1MB fixed for cursor size, should be more then enough m_cursorDataSize = 1048576; // 1MB fixed for cursor size, should be more then enough
m_frame[0] = (uint8_t *)ALIGN_UP(m_cursorData + m_cursorDataSize);
m_frameSize = ALIGN_DN((m_ivshmem->GetSize() - (m_frame[0] - m_memory)) >> 1);
m_frame[1] = (uint8_t *)ALIGN_DN(m_frame[0] + m_frameSize);
m_cursorOffset = m_cursorData - m_memory; m_cursorOffset = m_cursorData - m_memory;
m_dataOffset[0] = m_frame[0] - m_memory;
m_dataOffset[1] = m_frame[1] - m_memory; uint8_t * m_frames = (uint8_t *)ALIGN_UP(m_cursorData + m_cursorDataSize);
m_frameSize = ALIGN_DN((m_ivshmem->GetSize() - (m_frames - m_memory)) / MAX_FRAMES);
DEBUG_INFO("Total Available : %3u MB", (unsigned int)(m_ivshmem->GetSize() / 1024 / 1024)); DEBUG_INFO("Total Available : %3u MB", (unsigned int)(m_ivshmem->GetSize() / 1024 / 1024));
DEBUG_INFO("Max Cursor Size : %3u MB", (unsigned int)(m_cursorDataSize / 1024 / 1024)); DEBUG_INFO("Max Cursor Size : %3u MB", (unsigned int)(m_cursorDataSize / 1024 / 1024));
DEBUG_INFO("Max Frame Size : %3u MB", (unsigned int)(m_frameSize / 1024 / 1024)); DEBUG_INFO("Max Frame Size : %3u MB", (unsigned int)(m_frameSize / 1024 / 1024));
DEBUG_INFO("Cursor : %p (0x%08x)", m_cursorData, (int)m_cursorOffset ); DEBUG_INFO("Cursor : %p (0x%08x)", m_cursorData, (int)m_cursorOffset);
DEBUG_INFO("Frame 1 : %p (0x%08x)", m_frame[0] , (int)m_dataOffset[0]);
DEBUG_INFO("Frame 2 : %p (0x%08x)", m_frame[1] , (int)m_dataOffset[1]); for (int i = 0; i < MAX_FRAMES; ++i)
{
m_frame[i] = m_frames + i * m_frameSize;
m_dataOffset[i] = m_frame[i] - m_memory;
DEBUG_INFO("Frame %d : %p (0x%08x)", i, m_frame[i], (int)m_dataOffset[i]);
}
return true; return true;
} }
void Service::DeInitialize() void Service::DeInitialize()
{ {
if (m_timer)
{
CloseHandle(m_timer);
m_timer = NULL;
}
m_shmHeader = NULL;
m_cursorData = NULL;
m_frame[0] = NULL;
m_frame[1] = NULL;
m_cursorOffset = 0;
m_dataOffset[0] = 0;
m_dataOffset[1] = 0;
m_cursorDataSize = 0;
m_frameSize = 0;
WaitForSingleObject(m_cursorThread, INFINITE); WaitForSingleObject(m_cursorThread, INFINITE);
CloseHandle(m_cursorThread); CloseHandle(m_cursorThread);
CloseHandle(m_cursorEvent); CloseHandle(m_cursorEvent);
m_shmHeader = NULL;
m_cursorData = NULL;
m_cursorDataSize = 0;
m_cursorOffset = 0;
m_haveFrame = false;
for(int i = 0; i < MAX_FRAMES; ++i)
{
m_frame [i] = NULL;
m_dataOffset[i] = 0;
}
m_frameSize = 0;
m_ivshmem->DeInitialize(); m_ivshmem->DeInitialize();
if (m_capture) if (m_capture)
@ -218,6 +210,7 @@ bool Service::Process()
bool ok = false; bool ok = false;
bool cursorOnly = false; bool cursorOnly = false;
bool repeat = false;
for(int i = 0; i < 2; ++i) for(int i = 0; i < 2; ++i)
{ {
// capture a frame of data // capture a frame of data
@ -227,6 +220,20 @@ bool Service::Process()
ok = true; ok = true;
break; break;
case GRAB_STATUS_TIMEOUT:
if (m_haveFrame)
{
ok = true;
repeat = true;
if (--m_frameIndex < 0)
m_frameIndex = MAX_FRAMES - 1;
break;
}
// capture timeouts are not errors
--i;
continue;
case GRAB_STATUS_CURSOR: case GRAB_STATUS_CURSOR:
ok = true; ok = true;
cursorOnly = true; cursorOnly = true;
@ -309,15 +316,23 @@ bool Service::Process()
{ {
KVMFRFrame * fi = &m_shmHeader->frame; KVMFRFrame * fi = &m_shmHeader->frame;
// only update the header if the frame is new
if (!repeat)
{
fi->type = m_capture->GetFrameType(); fi->type = m_capture->GetFrameType();
fi->width = frame.width; fi->width = frame.width;
fi->height = frame.height; fi->height = frame.height;
fi->stride = frame.stride; fi->stride = frame.stride;
fi->pitch = frame.pitch; fi->pitch = frame.pitch;
fi->dataPos = m_dataOffset[m_frameIndex]; fi->dataPos = m_dataOffset[m_frameIndex];
if (++m_frameIndex == 2) }
if (++m_frameIndex == MAX_FRAMES)
m_frameIndex = 0; m_frameIndex = 0;
// remember that we have a valid frame
m_haveFrame = true;
// signal a frame update // signal a frame update
fi->flags |= KVMFR_FRAME_FLAG_UPDATE; fi->flags |= KVMFR_FRAME_FLAG_UPDATE;
} }

View file

@ -26,6 +26,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include "IVSHMEM.h" #include "IVSHMEM.h"
#include "ICapture.h" #include "ICapture.h"
#define MAX_FRAMES 2
class Service class Service
{ {
public: public:
@ -57,9 +59,10 @@ private:
KVMFRHeader * m_shmHeader; KVMFRHeader * m_shmHeader;
uint8_t * m_frame[2]; bool m_haveFrame;
uint8_t * m_frame[MAX_FRAMES];
size_t m_frameSize; size_t m_frameSize;
uint64_t m_dataOffset[2]; uint64_t m_dataOffset[MAX_FRAMES];
int m_frameIndex; int m_frameIndex;
static DWORD WINAPI _CursorThread(LPVOID lpParameter) { return ((Service *)lpParameter)->CursorThread(); } static DWORD WINAPI _CursorThread(LPVOID lpParameter) { return ((Service *)lpParameter)->CursorThread(); }