From b2961c7939b2eb35c36914d282e71711ba4f5581 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Mon, 12 Oct 2020 18:52:37 +1100 Subject: [PATCH] [all] added new format version field to frame header --- client/src/main.c | 89 ++++++++++--------- common/include/common/KVMFR.h | 3 +- host/include/interface/capture.h | 1 + host/platform/Windows/capture/DXGI/src/dxgi.c | 24 +++-- .../Windows/capture/NVFBC/src/nvfbc.c | 28 ++++-- host/src/app.c | 13 +-- obs/lg.c | 57 ++++++------ 7 files changed, 126 insertions(+), 89 deletions(-) diff --git a/client/src/main.c b/client/src/main.c index 09c354d7..914cf6ad 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -375,6 +375,10 @@ static int frameThread(void * unused) LGMP_STATUS status; PLGMPClientQueue queue; + uint32_t formatVer = 0; + bool formatValid = false; + LG_RendererFormat lgrFormat; + SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); lgWaitEvent(e_startup, TIMEOUT_INFINITE); if (state.state != APP_STATE_RUNNING) @@ -421,56 +425,61 @@ static int frameThread(void * unused) KVMFRFrame * frame = (KVMFRFrame *)msg.mem; - // setup the renderer format with the frame format details - LG_RendererFormat lgrFormat; - lgrFormat.type = frame->type; - lgrFormat.width = frame->width; - lgrFormat.height = frame->height; - lgrFormat.stride = frame->stride; - lgrFormat.pitch = frame->pitch; - - size_t dataSize; - bool error = false; - switch(frame->type) + if (!formatValid || frame->formatVer != formatVer) { - case FRAME_TYPE_RGBA: - case FRAME_TYPE_BGRA: - case FRAME_TYPE_RGBA10: - dataSize = lgrFormat.height * lgrFormat.pitch; - lgrFormat.bpp = 32; - break; + // setup the renderer format with the frame format details + lgrFormat.type = frame->type; + lgrFormat.width = frame->width; + lgrFormat.height = frame->height; + lgrFormat.stride = frame->stride; + lgrFormat.pitch = frame->pitch; - case FRAME_TYPE_RGBA16F: - dataSize = lgrFormat.height * lgrFormat.pitch; - lgrFormat.bpp = 64; - break; + size_t dataSize; + bool error = false; + switch(frame->type) + { + case FRAME_TYPE_RGBA: + case FRAME_TYPE_BGRA: + case FRAME_TYPE_RGBA10: + dataSize = lgrFormat.height * lgrFormat.pitch; + lgrFormat.bpp = 32; + break; - case FRAME_TYPE_YUV420: - dataSize = lgrFormat.height * lgrFormat.width; - dataSize += (dataSize / 4) * 2; - lgrFormat.bpp = 12; - break; + case FRAME_TYPE_RGBA16F: + dataSize = lgrFormat.height * lgrFormat.pitch; + lgrFormat.bpp = 64; + break; - default: - DEBUG_ERROR("Unsupported frameType"); - error = true; + case FRAME_TYPE_YUV420: + dataSize = lgrFormat.height * lgrFormat.width; + dataSize += (dataSize / 4) * 2; + lgrFormat.bpp = 12; + break; + + default: + DEBUG_ERROR("Unsupported frameType"); + error = true; + break; + } + + if (error) + { + lgmpClientMessageDone(queue); + state.state = APP_STATE_SHUTDOWN; break; + } + + formatValid = true; + formatVer = frame->formatVer; } - if (error) + if (lgrFormat.width != state.srcSize.x || lgrFormat.height != state.srcSize.y) { - lgmpClientMessageDone(queue); - state.state = APP_STATE_SHUTDOWN; - break; - } - - if (frame->width != state.srcSize.x || frame->height != state.srcSize.y) - { - state.srcSize.x = frame->width; - state.srcSize.y = frame->height; + state.srcSize.x = lgrFormat.width; + state.srcSize.y = lgrFormat.height; state.haveSrcSize = true; if (params.autoResize) - SDL_SetWindowSize(state.window, frame->width, frame->height); + SDL_SetWindowSize(state.window, lgrFormat.width, lgrFormat.height); updatePositionInfo(); } diff --git a/common/include/common/KVMFR.h b/common/include/common/KVMFR.h index 374a6693..10dab83c 100644 --- a/common/include/common/KVMFR.h +++ b/common/include/common/KVMFR.h @@ -52,7 +52,7 @@ typedef enum CursorType CursorType; #define KVMFR_MAGIC "KVMFR---" -#define KVMFR_VERSION 4 +#define KVMFR_VERSION 5 typedef struct KVMFR { @@ -75,6 +75,7 @@ KVMFRCursor; typedef struct KVMFRFrame { + uint32_t formatVer; // the frame format version number FrameType type; // the frame data type uint32_t width; // the width uint32_t height; // the height diff --git a/host/include/interface/capture.h b/host/include/interface/capture.h index 03595203..99849cdf 100644 --- a/host/include/interface/capture.h +++ b/host/include/interface/capture.h @@ -52,6 +52,7 @@ CaptureFormat; typedef struct CaptureFrame { + unsigned int formatVer; unsigned int width; unsigned int height; unsigned int pitch; diff --git a/host/platform/Windows/capture/DXGI/src/dxgi.c b/host/platform/Windows/capture/DXGI/src/dxgi.c index 6781bbb2..32f02494 100644 --- a/host/platform/Windows/capture/DXGI/src/dxgi.c +++ b/host/platform/Windows/capture/DXGI/src/dxgi.c @@ -57,6 +57,7 @@ enum TextureState typedef struct Texture { + unsigned int formatVer; volatile enum TextureState state; ID3D11Texture2D * tex; D3D11_MAPPED_SUBRESOURCE map; @@ -91,6 +92,7 @@ struct iface CapturePostPointerBuffer postPointerBufferFn; LGEvent * frameEvent; + unsigned int formatVer; unsigned int width; unsigned int height; unsigned int pitch; @@ -227,9 +229,10 @@ static bool dxgi_init() HRESULT status; DXGI_OUTPUT_DESC outputDesc; - this->stop = false; - this->texRIndex = 0; - this->texWIndex = 0; + this->stop = false; + this->texRIndex = 0; + this->texWIndex = 0; + this->formatVer = 0; atomic_store(&this->texReady, 0); lgResetEvent(this->frameEvent); @@ -386,6 +389,7 @@ static bool dxgi_init() IDXGIAdapter1_GetDesc1(this->adapter, &adapterDesc); this->width = outputDesc.DesktopCoordinates.right - outputDesc.DesktopCoordinates.left; this->height = outputDesc.DesktopCoordinates.bottom - outputDesc.DesktopCoordinates.top; + ++this->formatVer; DEBUG_INFO("Device Descripion: %ls" , adapterDesc.Description); DEBUG_INFO("Device Vendor ID : 0x%x" , adapterDesc.VendorId); @@ -805,7 +809,8 @@ static CaptureResult dxgi_capture() ID3D11Texture2D_Release(src); // set the state, and signal - tex->state = TEXTURE_STATE_PENDING_MAP; + tex->state = TEXTURE_STATE_PENDING_MAP; + tex->formatVer = this->formatVer; if (atomic_fetch_add_explicit(&this->texReady, 1, memory_order_relaxed) == 0) lgSignalEvent(this->frameEvent); @@ -950,11 +955,12 @@ static CaptureResult dxgi_waitFrame(CaptureFrame * frame) tex->state = TEXTURE_STATE_MAPPED; - frame->width = this->width; - frame->height = this->height; - frame->pitch = this->pitch; - frame->stride = this->stride; - frame->format = this->format; + frame->formatVer = tex->formatVer; + frame->width = this->width; + frame->height = this->height; + frame->pitch = this->pitch; + frame->stride = this->stride; + frame->format = this->format; atomic_fetch_sub_explicit(&this->texReady, 1, memory_order_release); return CAPTURE_RESULT_OK; diff --git a/host/platform/Windows/capture/NVFBC/src/nvfbc.c b/host/platform/Windows/capture/NVFBC/src/nvfbc.c index 8ccb56a3..b40e968f 100644 --- a/host/platform/Windows/capture/NVFBC/src/nvfbc.c +++ b/host/platform/Windows/capture/NVFBC/src/nvfbc.c @@ -42,8 +42,11 @@ struct iface CapturePostPointerBuffer postPointerBufferFn; LGThread * pointerThread; - unsigned int maxWidth, maxHeight; - unsigned int width , height; + unsigned int maxWidth , maxHeight; + unsigned int width , height; + + unsigned int formatVer; + unsigned int grabWidth, grabHeight, grabStride; uint8_t * frameBuffer; uint8_t * diffMap; @@ -195,6 +198,7 @@ static bool nvfbc_init() return false; } + ++this->formatVer; return true; } @@ -284,10 +288,22 @@ static CaptureResult nvfbc_waitFrame(CaptureFrame * frame) if (this->stop) return CAPTURE_RESULT_REINIT; - frame->width = this->grabInfo.dwWidth; - frame->height = this->grabInfo.dwHeight; - frame->pitch = this->grabInfo.dwBufferWidth * 4; - frame->stride = this->grabInfo.dwBufferWidth; + if ( + this->grabInfo.dwWidth != this->grabWidth || + this->grabInfo.dwHeight != this->grabHeight || + this->grabInfo.dwBufferWidth != this->grabStride) + { + this->grabWidth = this->grabInfo.dwWidth; + this->grabHeight = this->grabInfo.dwHeight; + this->grabStride = this->grabInfo.dwBufferWidth; + ++this->formatVer; + } + + frame->formatVer = this->formatVer; + frame->width = this->grabWidth; + frame->height = this->grabHeight; + frame->pitch = this->grabStride * 4; + frame->stride = this->grabStride; #if 0 //NvFBC never sets bIsHDR so instead we check for any data in the alpha channel diff --git a/host/src/app.c b/host/src/app.c index 19890aed..7d7eaa10 100644 --- a/host/src/app.c +++ b/host/src/app.c @@ -188,12 +188,13 @@ static int frameThread(void * opaque) continue; } - fi->width = frame.width; - fi->height = frame.height; - fi->stride = frame.stride; - fi->pitch = frame.pitch; - fi->offset = pageSize - FrameBufferStructSize; - frameValid = true; + fi->formatVer = frame.formatVer; + fi->width = frame.width; + fi->height = frame.height; + fi->stride = frame.stride; + fi->pitch = frame.pitch; + fi->offset = pageSize - FrameBufferStructSize; + frameValid = true; // put the framebuffer on the border of the next page // this is to allow for aligned DMA transfers by the receiver diff --git a/obs/lg.c b/obs/lg.c index 6b530721..f2a1a61f 100644 --- a/obs/lg.c +++ b/obs/lg.c @@ -29,6 +29,7 @@ typedef struct obs_source_t * context; LGState state; char * shmFile; + uint32_t formatVer; uint32_t width, height; FrameType type; int bpp; @@ -452,20 +453,14 @@ static void lgVideoTick(void * data, float seconds) return; } - bool updateTexture = false; KVMFRFrame * frame = (KVMFRFrame *)msg.mem; - if (this->width != frame->width || - this->height != frame->height || - this->type != frame->type) + if (!this->texture || this->formatVer != frame->formatVer) { - updateTexture = true; - this->width = frame->width; - this->height = frame->height; - this->type = frame->type; - } + this->formatVer = frame->formatVer; + this->width = frame->width; + this->height = frame->height; + this->type = frame->type; - if (!this->texture || updateTexture) - { obs_enter_graphics(); if (this->texture) { @@ -509,24 +504,32 @@ static void lgVideoTick(void * data, float seconds) obs_leave_graphics(); } - FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)frame) + frame->offset); - framebuffer_read( - fb, - this->texData, // dst - this->linesize, // dstpitch - frame->height, // height - frame->width, // width - this->bpp, // bpp - frame->pitch // linepitch - ); + if (this->texture) + { + FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)frame) + frame->offset); + framebuffer_read( + fb, + this->texData, // dst + this->linesize, // dstpitch + frame->height, // height + frame->width, // width + this->bpp, // bpp + frame->pitch // linepitch + ); - lgmpClientMessageDone(this->frameQueue); - os_sem_post(this->frameSem); + lgmpClientMessageDone(this->frameQueue); + os_sem_post(this->frameSem); - obs_enter_graphics(); - gs_texture_unmap(this->texture); - gs_texture_map(this->texture, &this->texData, &this->linesize); - obs_leave_graphics(); + obs_enter_graphics(); + gs_texture_unmap(this->texture); + gs_texture_map(this->texture, &this->texData, &this->linesize); + obs_leave_graphics(); + } + else + { + lgmpClientMessageDone(this->frameQueue); + os_sem_post(this->frameSem); + } } static void lgVideoRender(void * data, gs_effect_t * effect)