ore untangling
This commit is contained in:
@@ -62,6 +62,8 @@ set(APP_SOURCES
|
|||||||
"${APP_DIR}/gl/OpenGLComposite.cpp"
|
"${APP_DIR}/gl/OpenGLComposite.cpp"
|
||||||
"${APP_DIR}/gl/OpenGLComposite.h"
|
"${APP_DIR}/gl/OpenGLComposite.h"
|
||||||
"${APP_DIR}/gl/OpenGLCompositeRuntimeControls.cpp"
|
"${APP_DIR}/gl/OpenGLCompositeRuntimeControls.cpp"
|
||||||
|
"${APP_DIR}/gl/RenderEngine.cpp"
|
||||||
|
"${APP_DIR}/gl/RenderEngine.h"
|
||||||
"${APP_DIR}/gl/pipeline/OpenGLRenderPass.cpp"
|
"${APP_DIR}/gl/pipeline/OpenGLRenderPass.cpp"
|
||||||
"${APP_DIR}/gl/pipeline/OpenGLRenderPass.h"
|
"${APP_DIR}/gl/pipeline/OpenGLRenderPass.h"
|
||||||
"${APP_DIR}/gl/pipeline/OpenGLRenderPipeline.cpp"
|
"${APP_DIR}/gl/pipeline/OpenGLRenderPipeline.cpp"
|
||||||
@@ -122,6 +124,8 @@ set(APP_SOURCES
|
|||||||
"${APP_DIR}/targetver.h"
|
"${APP_DIR}/targetver.h"
|
||||||
"${APP_DIR}/videoio/VideoIOFormat.cpp"
|
"${APP_DIR}/videoio/VideoIOFormat.cpp"
|
||||||
"${APP_DIR}/videoio/VideoIOFormat.h"
|
"${APP_DIR}/videoio/VideoIOFormat.h"
|
||||||
|
"${APP_DIR}/videoio/VideoBackend.cpp"
|
||||||
|
"${APP_DIR}/videoio/VideoBackend.h"
|
||||||
"${APP_DIR}/videoio/VideoIOTypes.h"
|
"${APP_DIR}/videoio/VideoIOTypes.h"
|
||||||
"${APP_DIR}/videoio/VideoPlayoutScheduler.cpp"
|
"${APP_DIR}/videoio/VideoPlayoutScheduler.cpp"
|
||||||
"${APP_DIR}/videoio/VideoPlayoutScheduler.h"
|
"${APP_DIR}/videoio/VideoPlayoutScheduler.h"
|
||||||
|
|||||||
@@ -186,6 +186,7 @@
|
|||||||
<ClCompile Include="LoopThroughWithOpenGLCompositing.cpp" />
|
<ClCompile Include="LoopThroughWithOpenGLCompositing.cpp" />
|
||||||
<ClCompile Include="gl\OpenGLComposite.cpp" />
|
<ClCompile Include="gl\OpenGLComposite.cpp" />
|
||||||
<ClCompile Include="gl\OpenGLCompositeRuntimeControls.cpp" />
|
<ClCompile Include="gl\OpenGLCompositeRuntimeControls.cpp" />
|
||||||
|
<ClCompile Include="gl\RenderEngine.cpp" />
|
||||||
<ClCompile Include="gl\pipeline\OpenGLRenderPass.cpp" />
|
<ClCompile Include="gl\pipeline\OpenGLRenderPass.cpp" />
|
||||||
<ClCompile Include="gl\pipeline\OpenGLRenderPipeline.cpp" />
|
<ClCompile Include="gl\pipeline\OpenGLRenderPipeline.cpp" />
|
||||||
<ClCompile Include="gl\pipeline\ShaderFeedbackBuffers.cpp" />
|
<ClCompile Include="gl\pipeline\ShaderFeedbackBuffers.cpp" />
|
||||||
@@ -220,6 +221,7 @@
|
|||||||
<ClCompile Include="runtime\RuntimeStore.cpp" />
|
<ClCompile Include="runtime\RuntimeStore.cpp" />
|
||||||
<ClCompile Include="shader\ShaderCompiler.cpp" />
|
<ClCompile Include="shader\ShaderCompiler.cpp" />
|
||||||
<ClCompile Include="shader\ShaderPackageRegistry.cpp" />
|
<ClCompile Include="shader\ShaderPackageRegistry.cpp" />
|
||||||
|
<ClCompile Include="videoio\VideoBackend.cpp" />
|
||||||
<ClCompile Include="videoio\VideoIOFormat.cpp" />
|
<ClCompile Include="videoio\VideoIOFormat.cpp" />
|
||||||
<ClCompile Include="videoio\VideoPlayoutScheduler.cpp" />
|
<ClCompile Include="videoio\VideoPlayoutScheduler.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@@ -236,6 +238,7 @@
|
|||||||
<ClInclude Include="gl\shader\GlShaderSources.h" />
|
<ClInclude Include="gl\shader\GlShaderSources.h" />
|
||||||
<ClInclude Include="LoopThroughWithOpenGLCompositing.h" />
|
<ClInclude Include="LoopThroughWithOpenGLCompositing.h" />
|
||||||
<ClInclude Include="gl\OpenGLComposite.h" />
|
<ClInclude Include="gl\OpenGLComposite.h" />
|
||||||
|
<ClInclude Include="gl\RenderEngine.h" />
|
||||||
<ClInclude Include="gl\pipeline\OpenGLRenderPass.h" />
|
<ClInclude Include="gl\pipeline\OpenGLRenderPass.h" />
|
||||||
<ClInclude Include="gl\pipeline\OpenGLRenderPipeline.h" />
|
<ClInclude Include="gl\pipeline\OpenGLRenderPipeline.h" />
|
||||||
<ClInclude Include="gl\pipeline\RenderPassDescriptor.h" />
|
<ClInclude Include="gl\pipeline\RenderPassDescriptor.h" />
|
||||||
@@ -272,6 +275,7 @@
|
|||||||
<ClInclude Include="videoio\decklink\DeckLinkFrameTransfer.h" />
|
<ClInclude Include="videoio\decklink\DeckLinkFrameTransfer.h" />
|
||||||
<ClInclude Include="videoio\decklink\DeckLinkSession.h" />
|
<ClInclude Include="videoio\decklink\DeckLinkSession.h" />
|
||||||
<ClInclude Include="videoio\decklink\DeckLinkVideoIOFormat.h" />
|
<ClInclude Include="videoio\decklink\DeckLinkVideoIOFormat.h" />
|
||||||
|
<ClInclude Include="videoio\VideoBackend.h" />
|
||||||
<ClInclude Include="videoio\VideoIOFormat.h" />
|
<ClInclude Include="videoio\VideoIOFormat.h" />
|
||||||
<ClInclude Include="videoio\VideoIOTypes.h" />
|
<ClInclude Include="videoio\VideoIOTypes.h" />
|
||||||
<ClInclude Include="videoio\VideoPlayoutScheduler.h" />
|
<ClInclude Include="videoio\VideoPlayoutScheduler.h" />
|
||||||
|
|||||||
@@ -48,6 +48,9 @@
|
|||||||
<ClCompile Include="gl\OpenGLCompositeRuntimeControls.cpp">
|
<ClCompile Include="gl\OpenGLCompositeRuntimeControls.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="gl\RenderEngine.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="gl\pipeline\OpenGLRenderPass.cpp">
|
<ClCompile Include="gl\pipeline\OpenGLRenderPass.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -138,6 +141,9 @@
|
|||||||
<ClCompile Include="shader\ShaderPackageRegistry.cpp">
|
<ClCompile Include="shader\ShaderPackageRegistry.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="videoio\VideoBackend.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="videoio\VideoIOFormat.cpp">
|
<ClCompile Include="videoio\VideoIOFormat.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -179,6 +185,9 @@
|
|||||||
<ClInclude Include="gl\OpenGLComposite.h">
|
<ClInclude Include="gl\OpenGLComposite.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="gl\RenderEngine.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="gl\pipeline\OpenGLRenderPass.h">
|
<ClInclude Include="gl\pipeline\OpenGLRenderPass.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -287,6 +296,9 @@
|
|||||||
<ClInclude Include="videoio\decklink\DeckLinkFrameTransfer.h">
|
<ClInclude Include="videoio\decklink\DeckLinkFrameTransfer.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="videoio\VideoBackend.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="runtime\RuntimeClock.h">
|
<ClInclude Include="runtime\RuntimeClock.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
#include "DeckLinkDisplayMode.h"
|
#include "DeckLinkDisplayMode.h"
|
||||||
#include "DeckLinkSession.h"
|
|
||||||
#include "OpenGLComposite.h"
|
#include "OpenGLComposite.h"
|
||||||
#include "GLExtensions.h"
|
#include "GLExtensions.h"
|
||||||
#include "GlRenderConstants.h"
|
#include "GlRenderConstants.h"
|
||||||
#include "OpenGLRenderPass.h"
|
|
||||||
#include "OpenGLRenderPipeline.h"
|
|
||||||
#include "OpenGLShaderPrograms.h"
|
|
||||||
#include "OpenGLVideoIOBridge.h"
|
|
||||||
#include "PngScreenshotWriter.h"
|
#include "PngScreenshotWriter.h"
|
||||||
|
#include "RenderEngine.h"
|
||||||
#include "RuntimeParameterUtils.h"
|
#include "RuntimeParameterUtils.h"
|
||||||
#include "RuntimeServices.h"
|
#include "RuntimeServices.h"
|
||||||
#include "ShaderBuildQueue.h"
|
#include "ShaderBuildQueue.h"
|
||||||
|
#include "VideoBackend.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
@@ -97,8 +94,6 @@ JsonValue BuildOscCommitValue(const ShaderParameterDefinition& definition, const
|
|||||||
|
|
||||||
OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
|
OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
|
||||||
hGLWnd(hWnd), hGLDC(hDC), hGLRC(hRC),
|
hGLWnd(hWnd), hGLDC(hDC), hGLRC(hRC),
|
||||||
mVideoIO(std::make_unique<DeckLinkSession>()),
|
|
||||||
mRenderer(std::make_unique<OpenGLRenderer>()),
|
|
||||||
mUseCommittedLayerStates(false),
|
mUseCommittedLayerStates(false),
|
||||||
mScreenshotRequested(false)
|
mScreenshotRequested(false)
|
||||||
{
|
{
|
||||||
@@ -106,22 +101,16 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
|
|||||||
mRuntimeHost = std::make_unique<RuntimeHost>();
|
mRuntimeHost = std::make_unique<RuntimeHost>();
|
||||||
mRuntimeStore = std::make_unique<RuntimeStore>(*mRuntimeHost);
|
mRuntimeStore = std::make_unique<RuntimeStore>(*mRuntimeHost);
|
||||||
mRuntimeSnapshotProvider = std::make_unique<RuntimeSnapshotProvider>(*mRuntimeHost);
|
mRuntimeSnapshotProvider = std::make_unique<RuntimeSnapshotProvider>(*mRuntimeHost);
|
||||||
mRenderPipeline = std::make_unique<OpenGLRenderPipeline>(
|
mRenderEngine = std::make_unique<RenderEngine>(
|
||||||
*mRenderer,
|
|
||||||
*mRuntimeHost,
|
*mRuntimeHost,
|
||||||
|
*mRuntimeSnapshotProvider,
|
||||||
|
pMutex,
|
||||||
|
hGLDC,
|
||||||
|
hGLRC,
|
||||||
[this]() { renderEffect(); },
|
[this]() { renderEffect(); },
|
||||||
[this]() { ProcessScreenshotRequest(); },
|
[this]() { ProcessScreenshotRequest(); },
|
||||||
[this]() { paintGL(false); });
|
[this]() { paintGL(false); });
|
||||||
mVideoIOBridge = std::make_unique<OpenGLVideoIOBridge>(
|
mVideoBackend = std::make_unique<VideoBackend>(*mRenderEngine, mRuntimeHost->GetHealthTelemetry());
|
||||||
*mVideoIO,
|
|
||||||
*mRenderer,
|
|
||||||
*mRenderPipeline,
|
|
||||||
*mRuntimeHost,
|
|
||||||
pMutex,
|
|
||||||
hGLDC,
|
|
||||||
hGLRC);
|
|
||||||
mRenderPass = std::make_unique<OpenGLRenderPass>(*mRenderer);
|
|
||||||
mShaderPrograms = std::make_unique<OpenGLShaderPrograms>(*mRenderer, *mRuntimeHost, *mRuntimeSnapshotProvider);
|
|
||||||
mShaderBuildQueue = std::make_unique<ShaderBuildQueue>(*mRuntimeSnapshotProvider);
|
mShaderBuildQueue = std::make_unique<ShaderBuildQueue>(*mRuntimeSnapshotProvider);
|
||||||
mRuntimeServices = std::make_unique<RuntimeServices>();
|
mRuntimeServices = std::make_unique<RuntimeServices>();
|
||||||
}
|
}
|
||||||
@@ -132,8 +121,8 @@ OpenGLComposite::~OpenGLComposite()
|
|||||||
mRuntimeServices->Stop();
|
mRuntimeServices->Stop();
|
||||||
if (mShaderBuildQueue)
|
if (mShaderBuildQueue)
|
||||||
mShaderBuildQueue->Stop();
|
mShaderBuildQueue->Stop();
|
||||||
mVideoIO->ReleaseResources();
|
if (mVideoBackend)
|
||||||
mRenderer->DestroyResources();
|
mVideoBackend->ReleaseResources();
|
||||||
|
|
||||||
DeleteCriticalSection(&pMutex);
|
DeleteCriticalSection(&pMutex);
|
||||||
}
|
}
|
||||||
@@ -173,7 +162,7 @@ bool OpenGLComposite::InitVideoIO()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mVideoIO->DiscoverDevicesAndModes(videoModes, initFailureReason))
|
if (!mVideoBackend->DiscoverDevicesAndModes(videoModes, initFailureReason))
|
||||||
{
|
{
|
||||||
const char* title = initFailureReason == "Please install the Blackmagic DeckLink drivers to use the features of this application."
|
const char* title = initFailureReason == "Please install the Blackmagic DeckLink drivers to use the features of this application."
|
||||||
? "This application requires the DeckLink drivers installed."
|
? "This application requires the DeckLink drivers installed."
|
||||||
@@ -182,7 +171,7 @@ bool OpenGLComposite::InitVideoIO()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const bool outputAlphaRequired = mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured();
|
const bool outputAlphaRequired = mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured();
|
||||||
if (!mVideoIO->SelectPreferredFormats(videoModes, outputAlphaRequired, initFailureReason))
|
if (!mVideoBackend->SelectPreferredFormats(videoModes, outputAlphaRequired, initFailureReason))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (! CheckOpenGLExtensions())
|
if (! CheckOpenGLExtensions())
|
||||||
@@ -197,38 +186,38 @@ bool OpenGLComposite::InitVideoIO()
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
PublishVideoIOStatus(mVideoIO->OutputModelName().empty()
|
PublishVideoIOStatus(mVideoBackend->OutputModelName().empty()
|
||||||
? "DeckLink output device selected."
|
? "DeckLink output device selected."
|
||||||
: ("Selected output device: " + mVideoIO->OutputModelName()));
|
: ("Selected output device: " + mVideoBackend->OutputModelName()));
|
||||||
|
|
||||||
// Resize window to match output video frame, but scale large formats down by half for viewing.
|
// Resize window to match output video frame, but scale large formats down by half for viewing.
|
||||||
if (mVideoIO->OutputFrameWidth() < 1920)
|
if (mVideoBackend->OutputFrameWidth() < 1920)
|
||||||
resizeWindow(mVideoIO->OutputFrameWidth(), mVideoIO->OutputFrameHeight());
|
resizeWindow(mVideoBackend->OutputFrameWidth(), mVideoBackend->OutputFrameHeight());
|
||||||
else
|
else
|
||||||
resizeWindow(mVideoIO->OutputFrameWidth() / 2, mVideoIO->OutputFrameHeight() / 2);
|
resizeWindow(mVideoBackend->OutputFrameWidth() / 2, mVideoBackend->OutputFrameHeight() / 2);
|
||||||
|
|
||||||
if (!mVideoIO->ConfigureInput([this](const VideoIOFrame& frame) { mVideoIOBridge->VideoFrameArrived(frame); }, videoModes.input, initFailureReason))
|
if (!mVideoBackend->ConfigureInput(videoModes.input, initFailureReason))
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!mVideoIO->HasInputDevice() && mRuntimeHost)
|
if (!mVideoBackend->HasInputDevice() && mRuntimeHost)
|
||||||
{
|
{
|
||||||
mRuntimeHost->SetSignalStatus(false, mVideoIO->InputFrameWidth(), mVideoIO->InputFrameHeight(), mVideoIO->InputDisplayModeName());
|
mRuntimeHost->SetSignalStatus(false, mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight(), mVideoBackend->InputDisplayModeName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mVideoIO->ConfigureOutput([this](const VideoIOCompletion& completion) { mVideoIOBridge->PlayoutFrameCompleted(completion); }, videoModes.output, mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured(), initFailureReason))
|
if (!mVideoBackend->ConfigureOutput(videoModes.output, mRuntimeStore && mRuntimeStore->IsExternalKeyingConfigured(), initFailureReason))
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
PublishVideoIOStatus(mVideoIO->StatusMessage());
|
PublishVideoIOStatus(mVideoBackend->StatusMessage());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (!initFailureReason.empty())
|
if (!initFailureReason.empty())
|
||||||
MessageBoxA(NULL, initFailureReason.c_str(), "DeckLink initialization failed", MB_OK | MB_ICONERROR);
|
MessageBoxA(NULL, initFailureReason.c_str(), "DeckLink initialization failed", MB_OK | MB_ICONERROR);
|
||||||
mVideoIO->ReleaseResources();
|
mVideoBackend->ReleaseResources();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,23 +241,21 @@ void OpenGLComposite::paintGL(bool force)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TryEnterCriticalSection(&pMutex))
|
if (!mRenderEngine->TryPresentToWindow(mVideoBackend->OutputFrameWidth(), mVideoBackend->OutputFrameHeight()))
|
||||||
{
|
{
|
||||||
ValidateRect(hGLWnd, NULL);
|
ValidateRect(hGLWnd, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRenderer->PresentToWindow(hGLDC, mVideoIO->OutputFrameWidth(), mVideoIO->OutputFrameHeight());
|
|
||||||
mLastPreviewPresentTime = std::chrono::steady_clock::now();
|
mLastPreviewPresentTime = std::chrono::steady_clock::now();
|
||||||
ValidateRect(hGLWnd, NULL);
|
ValidateRect(hGLWnd, NULL);
|
||||||
LeaveCriticalSection(&pMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLComposite::resizeGL(WORD width, WORD height)
|
void OpenGLComposite::resizeGL(WORD width, WORD height)
|
||||||
{
|
{
|
||||||
// We don't set the project or model matrices here since the window data is copied directly from
|
// We don't set the project or model matrices here since the window data is copied directly from
|
||||||
// an off-screen FBO in paintGL(). Just save the width and height for use in paintGL().
|
// an off-screen FBO in paintGL(). Just save the width and height for use in paintGL().
|
||||||
mRenderer->ResizeView(width, height);
|
mRenderEngine->ResizeView(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLComposite::resizeWindow(int width, int height)
|
void OpenGLComposite::resizeWindow(int width, int height)
|
||||||
@@ -286,17 +273,17 @@ void OpenGLComposite::PublishVideoIOStatus(const std::string& statusMessage)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!statusMessage.empty())
|
if (!statusMessage.empty())
|
||||||
mVideoIO->SetStatusMessage(statusMessage);
|
mVideoBackend->SetStatusMessage(statusMessage);
|
||||||
|
|
||||||
mRuntimeHost->SetVideoIOStatus(
|
mRuntimeHost->SetVideoIOStatus(
|
||||||
"decklink",
|
"decklink",
|
||||||
mVideoIO->OutputModelName(),
|
mVideoBackend->OutputModelName(),
|
||||||
mVideoIO->SupportsInternalKeying(),
|
mVideoBackend->SupportsInternalKeying(),
|
||||||
mVideoIO->SupportsExternalKeying(),
|
mVideoBackend->SupportsExternalKeying(),
|
||||||
mVideoIO->KeyerInterfaceAvailable(),
|
mVideoBackend->KeyerInterfaceAvailable(),
|
||||||
mRuntimeStore ? mRuntimeStore->IsExternalKeyingConfigured() : false,
|
mRuntimeStore ? mRuntimeStore->IsExternalKeyingConfigured() : false,
|
||||||
mVideoIO->ExternalKeyingActive(),
|
mVideoBackend->ExternalKeyingActive(),
|
||||||
mVideoIO->StatusMessage());
|
mVideoBackend->StatusMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLComposite::InitOpenGLState()
|
bool OpenGLComposite::InitOpenGLState()
|
||||||
@@ -319,41 +306,41 @@ bool OpenGLComposite::InitOpenGLState()
|
|||||||
|
|
||||||
// Prepare the runtime shader program generated from the active shader package.
|
// Prepare the runtime shader program generated from the active shader package.
|
||||||
char compilerErrorMessage[1024];
|
char compilerErrorMessage[1024];
|
||||||
if (!mShaderPrograms->CompileDecodeShader(sizeof(compilerErrorMessage), compilerErrorMessage))
|
if (!mRenderEngine->CompileDecodeShader(sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||||
{
|
{
|
||||||
MessageBoxA(NULL, compilerErrorMessage, "OpenGL decode shader failed to load or compile", MB_OK);
|
MessageBoxA(NULL, compilerErrorMessage, "OpenGL decode shader failed to load or compile", MB_OK);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!mShaderPrograms->CompileOutputPackShader(sizeof(compilerErrorMessage), compilerErrorMessage))
|
if (!mRenderEngine->CompileOutputPackShader(sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||||
{
|
{
|
||||||
MessageBoxA(NULL, compilerErrorMessage, "OpenGL output pack shader failed to load or compile", MB_OK);
|
MessageBoxA(NULL, compilerErrorMessage, "OpenGL output pack shader failed to load or compile", MB_OK);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string rendererError;
|
std::string rendererError;
|
||||||
if (!mRenderer->InitializeResources(
|
if (!mRenderEngine->InitializeResources(
|
||||||
mVideoIO->InputFrameWidth(),
|
mVideoBackend->InputFrameWidth(),
|
||||||
mVideoIO->InputFrameHeight(),
|
mVideoBackend->InputFrameHeight(),
|
||||||
mVideoIO->CaptureTextureWidth(),
|
mVideoBackend->CaptureTextureWidth(),
|
||||||
mVideoIO->OutputFrameWidth(),
|
mVideoBackend->OutputFrameWidth(),
|
||||||
mVideoIO->OutputFrameHeight(),
|
mVideoBackend->OutputFrameHeight(),
|
||||||
mVideoIO->OutputPackTextureWidth(),
|
mVideoBackend->OutputPackTextureWidth(),
|
||||||
rendererError))
|
rendererError))
|
||||||
{
|
{
|
||||||
MessageBoxA(NULL, rendererError.c_str(), "OpenGL initialization error.", MB_OK);
|
MessageBoxA(NULL, rendererError.c_str(), "OpenGL initialization error.", MB_OK);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mShaderPrograms->CompileLayerPrograms(mVideoIO->InputFrameWidth(), mVideoIO->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
|
if (!mRenderEngine->CompileLayerPrograms(mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||||
{
|
{
|
||||||
MessageBoxA(NULL, compilerErrorMessage, "OpenGL shader failed to load or compile", MB_OK);
|
MessageBoxA(NULL, compilerErrorMessage, "OpenGL shader failed to load or compile", MB_OK);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mCachedLayerRenderStates = mShaderPrograms->CommittedLayerStates();
|
mCachedLayerRenderStates = mRenderEngine->CommittedLayerStates();
|
||||||
mUseCommittedLayerStates = false;
|
mUseCommittedLayerStates = false;
|
||||||
|
|
||||||
mShaderPrograms->ResetTemporalHistoryState();
|
mRenderEngine->ResetTemporalHistoryState();
|
||||||
mShaderPrograms->ResetShaderFeedbackState();
|
mRenderEngine->ResetShaderFeedbackState();
|
||||||
|
|
||||||
broadcastRuntimeState();
|
broadcastRuntimeState();
|
||||||
mRuntimeServices->BeginPolling(*mRuntimeHost);
|
mRuntimeServices->BeginPolling(*mRuntimeHost);
|
||||||
@@ -362,7 +349,7 @@ bool OpenGLComposite::InitOpenGLState()
|
|||||||
|
|
||||||
bool OpenGLComposite::Start()
|
bool OpenGLComposite::Start()
|
||||||
{
|
{
|
||||||
return mVideoIO->Start();
|
return mVideoBackend->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLComposite::Stop()
|
bool OpenGLComposite::Stop()
|
||||||
@@ -370,8 +357,8 @@ bool OpenGLComposite::Stop()
|
|||||||
if (mRuntimeServices)
|
if (mRuntimeServices)
|
||||||
mRuntimeServices->Stop();
|
mRuntimeServices->Stop();
|
||||||
|
|
||||||
const bool wasExternalKeyingActive = mVideoIO->ExternalKeyingActive();
|
const bool wasExternalKeyingActive = mVideoBackend->ExternalKeyingActive();
|
||||||
mVideoIO->Stop();
|
mVideoBackend->Stop();
|
||||||
if (wasExternalKeyingActive)
|
if (wasExternalKeyingActive)
|
||||||
PublishVideoIOStatus("External keying has been disabled.");
|
PublishVideoIOStatus("External keying has been disabled.");
|
||||||
|
|
||||||
@@ -587,19 +574,19 @@ void OpenGLComposite::renderEffect()
|
|||||||
mOscOverlayStates.erase(overlayKey);
|
mOscOverlayStates.erase(overlayKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
const bool hasInputSource = mVideoIO->HasInputSource();
|
const bool hasInputSource = mVideoBackend->HasInputSource();
|
||||||
std::vector<RuntimeRenderState> layerStates;
|
std::vector<RuntimeRenderState> layerStates;
|
||||||
if (mUseCommittedLayerStates)
|
if (mUseCommittedLayerStates)
|
||||||
{
|
{
|
||||||
layerStates = mShaderPrograms->CommittedLayerStates();
|
layerStates = mRenderEngine->CommittedLayerStates();
|
||||||
applyOscOverlays(layerStates, false);
|
applyOscOverlays(layerStates, false);
|
||||||
if (mRuntimeSnapshotProvider)
|
if (mRuntimeSnapshotProvider)
|
||||||
mRuntimeSnapshotProvider->RefreshDynamicRenderStateFields(layerStates);
|
mRuntimeSnapshotProvider->RefreshDynamicRenderStateFields(layerStates);
|
||||||
}
|
}
|
||||||
else if (mRuntimeSnapshotProvider)
|
else if (mRuntimeSnapshotProvider)
|
||||||
{
|
{
|
||||||
const unsigned renderWidth = mVideoIO->InputFrameWidth();
|
const unsigned renderWidth = mVideoBackend->InputFrameWidth();
|
||||||
const unsigned renderHeight = mVideoIO->InputFrameHeight();
|
const unsigned renderHeight = mVideoBackend->InputFrameHeight();
|
||||||
const RuntimeSnapshotVersions versions = mRuntimeSnapshotProvider->GetVersions();
|
const RuntimeSnapshotVersions versions = mRuntimeSnapshotProvider->GetVersions();
|
||||||
const bool renderStateCacheValid =
|
const bool renderStateCacheValid =
|
||||||
!mCachedLayerRenderStates.empty() &&
|
!mCachedLayerRenderStates.empty() &&
|
||||||
@@ -650,20 +637,14 @@ void OpenGLComposite::renderEffect()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const unsigned historyCap = mRuntimeStore ? mRuntimeStore->GetConfiguredMaxTemporalHistoryFrames() : 0;
|
const unsigned historyCap = mRuntimeStore ? mRuntimeStore->GetConfiguredMaxTemporalHistoryFrames() : 0;
|
||||||
mRenderPass->Render(
|
mRenderEngine->RenderLayerStack(
|
||||||
hasInputSource,
|
hasInputSource,
|
||||||
layerStates,
|
layerStates,
|
||||||
mVideoIO->InputFrameWidth(),
|
mVideoBackend->InputFrameWidth(),
|
||||||
mVideoIO->InputFrameHeight(),
|
mVideoBackend->InputFrameHeight(),
|
||||||
mVideoIO->CaptureTextureWidth(),
|
mVideoBackend->CaptureTextureWidth(),
|
||||||
mVideoIO->InputPixelFormat(),
|
mVideoBackend->InputPixelFormat(),
|
||||||
historyCap,
|
historyCap);
|
||||||
[this](const RuntimeRenderState& state, LayerProgram::TextBinding& textBinding, std::string& error) {
|
|
||||||
return mShaderPrograms->UpdateTextBindingTexture(state, textBinding, error);
|
|
||||||
},
|
|
||||||
[this](const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength, bool feedbackAvailable) {
|
|
||||||
return mShaderPrograms->UpdateGlobalParamsBuffer(state, availableSourceHistoryLength, availableTemporalHistoryLength, feedbackAvailable);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLComposite::ProcessScreenshotRequest()
|
void OpenGLComposite::ProcessScreenshotRequest()
|
||||||
@@ -671,21 +652,16 @@ void OpenGLComposite::ProcessScreenshotRequest()
|
|||||||
if (!mScreenshotRequested.exchange(false))
|
if (!mScreenshotRequested.exchange(false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const unsigned width = mVideoIO ? mVideoIO->OutputFrameWidth() : 0;
|
const unsigned width = mVideoBackend ? mVideoBackend->OutputFrameWidth() : 0;
|
||||||
const unsigned height = mVideoIO ? mVideoIO->OutputFrameHeight() : 0;
|
const unsigned height = mVideoBackend ? mVideoBackend->OutputFrameHeight() : 0;
|
||||||
if (width == 0 || height == 0)
|
if (width == 0 || height == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<unsigned char> bottomUpPixels(static_cast<std::size_t>(width) * height * 4);
|
std::vector<unsigned char> bottomUpPixels;
|
||||||
|
if (!mRenderEngine->ReadOutputFrameRgba(width, height, bottomUpPixels))
|
||||||
|
return;
|
||||||
std::vector<unsigned char> topDownPixels(bottomUpPixels.size());
|
std::vector<unsigned char> topDownPixels(bottomUpPixels.size());
|
||||||
|
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mRenderer->OutputFramebuffer());
|
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
|
||||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
|
||||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bottomUpPixels.data());
|
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
|
||||||
|
|
||||||
const std::size_t rowBytes = static_cast<std::size_t>(width) * 4;
|
const std::size_t rowBytes = static_cast<std::size_t>(width) * 4;
|
||||||
for (unsigned y = 0; y < height; ++y)
|
for (unsigned y = 0; y < height; ++y)
|
||||||
{
|
{
|
||||||
@@ -752,7 +728,7 @@ bool OpenGLComposite::ProcessRuntimePollResults()
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
char compilerErrorMessage[1024] = {};
|
char compilerErrorMessage[1024] = {};
|
||||||
if (!mShaderPrograms->CommitPreparedLayerPrograms(readyBuild, mVideoIO->InputFrameWidth(), mVideoIO->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
|
if (!mRenderEngine->CommitPreparedLayerPrograms(readyBuild, mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight(), sizeof(compilerErrorMessage), compilerErrorMessage))
|
||||||
{
|
{
|
||||||
mRuntimeStore->SetCompileStatus(false, compilerErrorMessage);
|
mRuntimeStore->SetCompileStatus(false, compilerErrorMessage);
|
||||||
mUseCommittedLayerStates = true;
|
mUseCommittedLayerStates = true;
|
||||||
@@ -762,10 +738,10 @@ bool OpenGLComposite::ProcessRuntimePollResults()
|
|||||||
}
|
}
|
||||||
|
|
||||||
mUseCommittedLayerStates = false;
|
mUseCommittedLayerStates = false;
|
||||||
mCachedLayerRenderStates = mShaderPrograms->CommittedLayerStates();
|
mCachedLayerRenderStates = mRenderEngine->CommittedLayerStates();
|
||||||
mShaderPrograms->ResetTemporalHistoryState();
|
mRenderEngine->ResetTemporalHistoryState();
|
||||||
if (!mPreserveFeedbackOnNextShaderBuild)
|
if (!mPreserveFeedbackOnNextShaderBuild)
|
||||||
mShaderPrograms->ResetShaderFeedbackState();
|
mRenderEngine->ResetShaderFeedbackState();
|
||||||
mPreserveFeedbackOnNextShaderBuild = false;
|
mPreserveFeedbackOnNextShaderBuild = false;
|
||||||
broadcastRuntimeState();
|
broadcastRuntimeState();
|
||||||
return true;
|
return true;
|
||||||
@@ -780,13 +756,13 @@ bool OpenGLComposite::ProcessRuntimePollResults()
|
|||||||
|
|
||||||
void OpenGLComposite::RequestShaderBuild()
|
void OpenGLComposite::RequestShaderBuild()
|
||||||
{
|
{
|
||||||
if (!mShaderBuildQueue || !mVideoIO)
|
if (!mShaderBuildQueue || !mVideoBackend)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mUseCommittedLayerStates = true;
|
mUseCommittedLayerStates = true;
|
||||||
if (mRuntimeHost)
|
if (mRuntimeHost)
|
||||||
mRuntimeStore->ClearReloadRequest();
|
mRuntimeStore->ClearReloadRequest();
|
||||||
mShaderBuildQueue->RequestBuild(mVideoIO->InputFrameWidth(), mVideoIO->InputFrameHeight());
|
mShaderBuildQueue->RequestBuild(mVideoBackend->InputFrameWidth(), mVideoBackend->InputFrameHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLComposite::broadcastRuntimeState()
|
void OpenGLComposite::broadcastRuntimeState()
|
||||||
@@ -797,8 +773,8 @@ void OpenGLComposite::broadcastRuntimeState()
|
|||||||
|
|
||||||
void OpenGLComposite::resetTemporalHistoryState()
|
void OpenGLComposite::resetTemporalHistoryState()
|
||||||
{
|
{
|
||||||
mShaderPrograms->ResetTemporalHistoryState();
|
mRenderEngine->ResetTemporalHistoryState();
|
||||||
mShaderPrograms->ResetShaderFeedbackState();
|
mRenderEngine->ResetShaderFeedbackState();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLComposite::CheckOpenGLExtensions()
|
bool OpenGLComposite::CheckOpenGLExtensions()
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#include <comutil.h>
|
#include <comutil.h>
|
||||||
|
|
||||||
#include "GLExtensions.h"
|
#include "GLExtensions.h"
|
||||||
#include "OpenGLRenderer.h"
|
|
||||||
#include "RuntimeHost.h"
|
#include "RuntimeHost.h"
|
||||||
#include "RuntimeSnapshotProvider.h"
|
#include "RuntimeSnapshotProvider.h"
|
||||||
#include "RuntimeStore.h"
|
#include "RuntimeStore.h"
|
||||||
@@ -27,13 +26,10 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
class VideoIODevice;
|
class RenderEngine;
|
||||||
class OpenGLVideoIOBridge;
|
|
||||||
class OpenGLRenderPass;
|
|
||||||
class OpenGLRenderPipeline;
|
|
||||||
class OpenGLShaderPrograms;
|
|
||||||
class RuntimeServices;
|
class RuntimeServices;
|
||||||
class ShaderBuildQueue;
|
class ShaderBuildQueue;
|
||||||
|
class VideoBackend;
|
||||||
|
|
||||||
|
|
||||||
class OpenGLComposite
|
class OpenGLComposite
|
||||||
@@ -74,7 +70,6 @@ private:
|
|||||||
void resizeWindow(int width, int height);
|
void resizeWindow(int width, int height);
|
||||||
bool CheckOpenGLExtensions();
|
bool CheckOpenGLExtensions();
|
||||||
void PublishVideoIOStatus(const std::string& statusMessage);
|
void PublishVideoIOStatus(const std::string& statusMessage);
|
||||||
using LayerProgram = OpenGLRenderer::LayerProgram;
|
|
||||||
struct OscOverlayState
|
struct OscOverlayState
|
||||||
{
|
{
|
||||||
std::string layerKey;
|
std::string layerKey;
|
||||||
@@ -94,17 +89,13 @@ private:
|
|||||||
HGLRC hGLRC;
|
HGLRC hGLRC;
|
||||||
CRITICAL_SECTION pMutex;
|
CRITICAL_SECTION pMutex;
|
||||||
|
|
||||||
std::unique_ptr<VideoIODevice> mVideoIO;
|
|
||||||
std::unique_ptr<OpenGLRenderer> mRenderer;
|
|
||||||
std::unique_ptr<RuntimeHost> mRuntimeHost;
|
std::unique_ptr<RuntimeHost> mRuntimeHost;
|
||||||
std::unique_ptr<RuntimeStore> mRuntimeStore;
|
std::unique_ptr<RuntimeStore> mRuntimeStore;
|
||||||
std::unique_ptr<RuntimeSnapshotProvider> mRuntimeSnapshotProvider;
|
std::unique_ptr<RuntimeSnapshotProvider> mRuntimeSnapshotProvider;
|
||||||
std::unique_ptr<OpenGLVideoIOBridge> mVideoIOBridge;
|
std::unique_ptr<RenderEngine> mRenderEngine;
|
||||||
std::unique_ptr<OpenGLRenderPass> mRenderPass;
|
|
||||||
std::unique_ptr<OpenGLRenderPipeline> mRenderPipeline;
|
|
||||||
std::unique_ptr<OpenGLShaderPrograms> mShaderPrograms;
|
|
||||||
std::unique_ptr<ShaderBuildQueue> mShaderBuildQueue;
|
std::unique_ptr<ShaderBuildQueue> mShaderBuildQueue;
|
||||||
std::unique_ptr<RuntimeServices> mRuntimeServices;
|
std::unique_ptr<RuntimeServices> mRuntimeServices;
|
||||||
|
std::unique_ptr<VideoBackend> mVideoBackend;
|
||||||
std::vector<RuntimeRenderState> mCachedLayerRenderStates;
|
std::vector<RuntimeRenderState> mCachedLayerRenderStates;
|
||||||
uint64_t mCachedRenderStateVersion = 0;
|
uint64_t mCachedRenderStateVersion = 0;
|
||||||
uint64_t mCachedParameterStateVersion = 0;
|
uint64_t mCachedParameterStateVersion = 0;
|
||||||
|
|||||||
180
apps/LoopThroughWithOpenGLCompositing/gl/RenderEngine.cpp
Normal file
180
apps/LoopThroughWithOpenGLCompositing/gl/RenderEngine.cpp
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
#include "RenderEngine.h"
|
||||||
|
|
||||||
|
#include <gl/gl.h>
|
||||||
|
|
||||||
|
RenderEngine::RenderEngine(
|
||||||
|
RuntimeHost& runtimeHost,
|
||||||
|
RuntimeSnapshotProvider& runtimeSnapshotProvider,
|
||||||
|
CRITICAL_SECTION& mutex,
|
||||||
|
HDC hdc,
|
||||||
|
HGLRC hglrc,
|
||||||
|
RenderEffectCallback renderEffect,
|
||||||
|
ScreenshotCallback screenshotReady,
|
||||||
|
PreviewPaintCallback previewPaint) :
|
||||||
|
mRenderer(),
|
||||||
|
mRenderPass(mRenderer),
|
||||||
|
mRenderPipeline(mRenderer, runtimeHost, std::move(renderEffect), std::move(screenshotReady), std::move(previewPaint)),
|
||||||
|
mShaderPrograms(mRenderer, runtimeHost, runtimeSnapshotProvider),
|
||||||
|
mMutex(mutex),
|
||||||
|
mHdc(hdc),
|
||||||
|
mHglrc(hglrc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderEngine::~RenderEngine()
|
||||||
|
{
|
||||||
|
mRenderer.DestroyResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderEngine::CompileDecodeShader(int errorMessageSize, char* errorMessage)
|
||||||
|
{
|
||||||
|
return mShaderPrograms.CompileDecodeShader(errorMessageSize, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderEngine::CompileOutputPackShader(int errorMessageSize, char* errorMessage)
|
||||||
|
{
|
||||||
|
return mShaderPrograms.CompileOutputPackShader(errorMessageSize, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderEngine::InitializeResources(
|
||||||
|
unsigned inputFrameWidth,
|
||||||
|
unsigned inputFrameHeight,
|
||||||
|
unsigned captureTextureWidth,
|
||||||
|
unsigned outputFrameWidth,
|
||||||
|
unsigned outputFrameHeight,
|
||||||
|
unsigned outputPackTextureWidth,
|
||||||
|
std::string& error)
|
||||||
|
{
|
||||||
|
return mRenderer.InitializeResources(
|
||||||
|
inputFrameWidth,
|
||||||
|
inputFrameHeight,
|
||||||
|
captureTextureWidth,
|
||||||
|
outputFrameWidth,
|
||||||
|
outputFrameHeight,
|
||||||
|
outputPackTextureWidth,
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderEngine::CompileLayerPrograms(unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage)
|
||||||
|
{
|
||||||
|
return mShaderPrograms.CompileLayerPrograms(inputFrameWidth, inputFrameHeight, errorMessageSize, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderEngine::CommitPreparedLayerPrograms(const PreparedShaderBuild& preparedBuild, unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage)
|
||||||
|
{
|
||||||
|
return mShaderPrograms.CommitPreparedLayerPrograms(preparedBuild, inputFrameWidth, inputFrameHeight, errorMessageSize, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<RuntimeRenderState>& RenderEngine::CommittedLayerStates() const
|
||||||
|
{
|
||||||
|
return mShaderPrograms.CommittedLayerStates();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderEngine::ResetTemporalHistoryState()
|
||||||
|
{
|
||||||
|
mShaderPrograms.ResetTemporalHistoryState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderEngine::ResetShaderFeedbackState()
|
||||||
|
{
|
||||||
|
mShaderPrograms.ResetShaderFeedbackState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderEngine::ResizeView(int width, int height)
|
||||||
|
{
|
||||||
|
mRenderer.ResizeView(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderEngine::TryPresentToWindow(unsigned outputFrameWidth, unsigned outputFrameHeight)
|
||||||
|
{
|
||||||
|
if (!TryEnterCriticalSection(&mMutex))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mRenderer.PresentToWindow(mHdc, outputFrameWidth, outputFrameHeight);
|
||||||
|
LeaveCriticalSection(&mMutex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderEngine::TryUploadInputFrame(const VideoIOFrame& inputFrame, const VideoIOState& videoState)
|
||||||
|
{
|
||||||
|
if (inputFrame.hasNoInputSource || inputFrame.bytes == nullptr)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const long textureSize = inputFrame.rowBytes * static_cast<long>(inputFrame.height);
|
||||||
|
if (!TryEnterCriticalSection(&mMutex))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wglMakeCurrent(mHdc, mHglrc);
|
||||||
|
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mRenderer.TextureUploadBuffer());
|
||||||
|
glBufferData(GL_PIXEL_UNPACK_BUFFER, textureSize, inputFrame.bytes, GL_DYNAMIC_DRAW);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, mRenderer.CaptureTexture());
|
||||||
|
if (inputFrame.pixelFormat == VideoIOPixelFormat::V210)
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, videoState.captureTextureWidth, videoState.inputFrameSize.height, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
else
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, videoState.captureTextureWidth, videoState.inputFrameSize.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
|
wglMakeCurrent(NULL, NULL);
|
||||||
|
LeaveCriticalSection(&mMutex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderEngine::RenderOutputFrame(const RenderPipelineFrameContext& context, VideoIOOutputFrame& outputFrame)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&mMutex);
|
||||||
|
wglMakeCurrent(mHdc, mHglrc);
|
||||||
|
const bool rendered = mRenderPipeline.RenderFrame(context, outputFrame);
|
||||||
|
wglMakeCurrent(NULL, NULL);
|
||||||
|
LeaveCriticalSection(&mMutex);
|
||||||
|
return rendered;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderEngine::RenderLayerStack(
|
||||||
|
bool hasInputSource,
|
||||||
|
const std::vector<RuntimeRenderState>& layerStates,
|
||||||
|
unsigned inputFrameWidth,
|
||||||
|
unsigned inputFrameHeight,
|
||||||
|
unsigned captureTextureWidth,
|
||||||
|
VideoIOPixelFormat inputPixelFormat,
|
||||||
|
unsigned historyCap)
|
||||||
|
{
|
||||||
|
mRenderPass.Render(
|
||||||
|
hasInputSource,
|
||||||
|
layerStates,
|
||||||
|
inputFrameWidth,
|
||||||
|
inputFrameHeight,
|
||||||
|
captureTextureWidth,
|
||||||
|
inputPixelFormat,
|
||||||
|
historyCap,
|
||||||
|
[this](const RuntimeRenderState& state, OpenGLRenderer::LayerProgram::TextBinding& textBinding, std::string& error) {
|
||||||
|
return mShaderPrograms.UpdateTextBindingTexture(state, textBinding, error);
|
||||||
|
},
|
||||||
|
[this](const RuntimeRenderState& state, unsigned availableSourceHistoryLength, unsigned availableTemporalHistoryLength, bool feedbackAvailable) {
|
||||||
|
return mShaderPrograms.UpdateGlobalParamsBuffer(state, availableSourceHistoryLength, availableTemporalHistoryLength, feedbackAvailable);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderEngine::ReadOutputFrameRgba(unsigned width, unsigned height, std::vector<unsigned char>& bottomUpPixels)
|
||||||
|
{
|
||||||
|
if (width == 0 || height == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
EnterCriticalSection(&mMutex);
|
||||||
|
wglMakeCurrent(mHdc, mHglrc);
|
||||||
|
|
||||||
|
bottomUpPixels.resize(static_cast<std::size_t>(width) * height * 4);
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, mRenderer.OutputFramebuffer());
|
||||||
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||||
|
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||||
|
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bottomUpPixels.data());
|
||||||
|
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||||
|
|
||||||
|
wglMakeCurrent(NULL, NULL);
|
||||||
|
LeaveCriticalSection(&mMutex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
72
apps/LoopThroughWithOpenGLCompositing/gl/RenderEngine.h
Normal file
72
apps/LoopThroughWithOpenGLCompositing/gl/RenderEngine.h
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "OpenGLRenderPass.h"
|
||||||
|
#include "OpenGLRenderPipeline.h"
|
||||||
|
#include "OpenGLRenderer.h"
|
||||||
|
#include "OpenGLShaderPrograms.h"
|
||||||
|
#include "RuntimeHost.h"
|
||||||
|
#include "RuntimeSnapshotProvider.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class RenderEngine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using RenderEffectCallback = std::function<void()>;
|
||||||
|
using ScreenshotCallback = std::function<void()>;
|
||||||
|
using PreviewPaintCallback = std::function<void()>;
|
||||||
|
|
||||||
|
RenderEngine(
|
||||||
|
RuntimeHost& runtimeHost,
|
||||||
|
RuntimeSnapshotProvider& runtimeSnapshotProvider,
|
||||||
|
CRITICAL_SECTION& mutex,
|
||||||
|
HDC hdc,
|
||||||
|
HGLRC hglrc,
|
||||||
|
RenderEffectCallback renderEffect,
|
||||||
|
ScreenshotCallback screenshotReady,
|
||||||
|
PreviewPaintCallback previewPaint);
|
||||||
|
~RenderEngine();
|
||||||
|
|
||||||
|
bool CompileDecodeShader(int errorMessageSize, char* errorMessage);
|
||||||
|
bool CompileOutputPackShader(int errorMessageSize, char* errorMessage);
|
||||||
|
bool InitializeResources(
|
||||||
|
unsigned inputFrameWidth,
|
||||||
|
unsigned inputFrameHeight,
|
||||||
|
unsigned captureTextureWidth,
|
||||||
|
unsigned outputFrameWidth,
|
||||||
|
unsigned outputFrameHeight,
|
||||||
|
unsigned outputPackTextureWidth,
|
||||||
|
std::string& error);
|
||||||
|
bool CompileLayerPrograms(unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage);
|
||||||
|
bool CommitPreparedLayerPrograms(const PreparedShaderBuild& preparedBuild, unsigned inputFrameWidth, unsigned inputFrameHeight, int errorMessageSize, char* errorMessage);
|
||||||
|
|
||||||
|
const std::vector<RuntimeRenderState>& CommittedLayerStates() const;
|
||||||
|
void ResetTemporalHistoryState();
|
||||||
|
void ResetShaderFeedbackState();
|
||||||
|
void ResizeView(int width, int height);
|
||||||
|
bool TryPresentToWindow(unsigned outputFrameWidth, unsigned outputFrameHeight);
|
||||||
|
bool TryUploadInputFrame(const VideoIOFrame& inputFrame, const VideoIOState& videoState);
|
||||||
|
bool RenderOutputFrame(const RenderPipelineFrameContext& context, VideoIOOutputFrame& outputFrame);
|
||||||
|
void RenderLayerStack(
|
||||||
|
bool hasInputSource,
|
||||||
|
const std::vector<RuntimeRenderState>& layerStates,
|
||||||
|
unsigned inputFrameWidth,
|
||||||
|
unsigned inputFrameHeight,
|
||||||
|
unsigned captureTextureWidth,
|
||||||
|
VideoIOPixelFormat inputPixelFormat,
|
||||||
|
unsigned historyCap);
|
||||||
|
bool ReadOutputFrameRgba(unsigned width, unsigned height, std::vector<unsigned char>& bottomUpPixels);
|
||||||
|
|
||||||
|
private:
|
||||||
|
OpenGLRenderer mRenderer;
|
||||||
|
OpenGLRenderPass mRenderPass;
|
||||||
|
OpenGLRenderPipeline mRenderPipeline;
|
||||||
|
OpenGLShaderPrograms mShaderPrograms;
|
||||||
|
CRITICAL_SECTION& mMutex;
|
||||||
|
HDC mHdc;
|
||||||
|
HGLRC mHglrc;
|
||||||
|
};
|
||||||
@@ -1,26 +1,17 @@
|
|||||||
#include "OpenGLVideoIOBridge.h"
|
#include "OpenGLVideoIOBridge.h"
|
||||||
|
|
||||||
#include "OpenGLRenderer.h"
|
#include "HealthTelemetry.h"
|
||||||
#include "RuntimeHost.h"
|
#include "RenderEngine.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <gl/gl.h>
|
|
||||||
|
|
||||||
OpenGLVideoIOBridge::OpenGLVideoIOBridge(
|
OpenGLVideoIOBridge::OpenGLVideoIOBridge(
|
||||||
VideoIODevice& videoIO,
|
VideoIODevice& videoIO,
|
||||||
OpenGLRenderer& renderer,
|
RenderEngine& renderEngine,
|
||||||
OpenGLRenderPipeline& renderPipeline,
|
HealthTelemetry& healthTelemetry) :
|
||||||
RuntimeHost& runtimeHost,
|
|
||||||
CRITICAL_SECTION& mutex,
|
|
||||||
HDC hdc,
|
|
||||||
HGLRC hglrc) :
|
|
||||||
mVideoIO(videoIO),
|
mVideoIO(videoIO),
|
||||||
mRenderer(renderer),
|
mRenderEngine(renderEngine),
|
||||||
mRenderPipeline(renderPipeline),
|
mHealthTelemetry(healthTelemetry)
|
||||||
mRuntimeHost(runtimeHost),
|
|
||||||
mMutex(mutex),
|
|
||||||
mHdc(hdc),
|
|
||||||
mHglrc(hglrc)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +37,7 @@ void OpenGLVideoIOBridge::RecordFramePacing(VideoIOCompletionResult completionRe
|
|||||||
else if (completionResult == VideoIOCompletionResult::Flushed)
|
else if (completionResult == VideoIOCompletionResult::Flushed)
|
||||||
++mFlushedFrameCount;
|
++mFlushedFrameCount;
|
||||||
|
|
||||||
mRuntimeHost.GetHealthTelemetry().TryRecordFramePacingStats(
|
mHealthTelemetry.TryRecordFramePacingStats(
|
||||||
mCompletionIntervalMilliseconds,
|
mCompletionIntervalMilliseconds,
|
||||||
mSmoothedCompletionIntervalMilliseconds,
|
mSmoothedCompletionIntervalMilliseconds,
|
||||||
mMaxCompletionIntervalMilliseconds,
|
mMaxCompletionIntervalMilliseconds,
|
||||||
@@ -58,38 +49,12 @@ void OpenGLVideoIOBridge::RecordFramePacing(VideoIOCompletionResult completionRe
|
|||||||
void OpenGLVideoIOBridge::VideoFrameArrived(const VideoIOFrame& inputFrame)
|
void OpenGLVideoIOBridge::VideoFrameArrived(const VideoIOFrame& inputFrame)
|
||||||
{
|
{
|
||||||
const VideoIOState& state = mVideoIO.State();
|
const VideoIOState& state = mVideoIO.State();
|
||||||
mRuntimeHost.GetHealthTelemetry().TryReportSignalStatus(!inputFrame.hasNoInputSource, state.inputFrameSize.width, state.inputFrameSize.height, state.inputDisplayModeName);
|
mHealthTelemetry.TryReportSignalStatus(!inputFrame.hasNoInputSource, state.inputFrameSize.width, state.inputFrameSize.height, state.inputDisplayModeName);
|
||||||
|
|
||||||
if (inputFrame.hasNoInputSource || inputFrame.bytes == nullptr)
|
if (inputFrame.hasNoInputSource || inputFrame.bytes == nullptr)
|
||||||
return; // don't transfer texture when there's no input
|
return; // don't transfer texture when there's no input
|
||||||
|
|
||||||
const long textureSize = inputFrame.rowBytes * static_cast<long>(inputFrame.height);
|
mRenderEngine.TryUploadInputFrame(inputFrame, state);
|
||||||
|
|
||||||
// Never let input upload stall the playout/render callback. If the GL bridge
|
|
||||||
// is busy producing an output frame, skip this upload and use the next input.
|
|
||||||
if (!TryEnterCriticalSection(&mMutex))
|
|
||||||
return;
|
|
||||||
|
|
||||||
wglMakeCurrent(mHdc, mHglrc); // make OpenGL context current in this thread
|
|
||||||
|
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mRenderer.TextureUploadBuffer());
|
|
||||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, textureSize, inputFrame.bytes, GL_DYNAMIC_DRAW);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, mRenderer.CaptureTexture());
|
|
||||||
|
|
||||||
// NULL for last arg indicates use current GL_PIXEL_UNPACK_BUFFER target as texture data.
|
|
||||||
if (inputFrame.pixelFormat == VideoIOPixelFormat::V210)
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, state.captureTextureWidth, state.inputFrameSize.height, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
else
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, state.captureTextureWidth, state.inputFrameSize.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
|
||||||
|
|
||||||
wglMakeCurrent(NULL, NULL);
|
|
||||||
|
|
||||||
LeaveCriticalSection(&mMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLVideoIOBridge::PlayoutFrameCompleted(const VideoIOCompletion& completion)
|
void OpenGLVideoIOBridge::PlayoutFrameCompleted(const VideoIOCompletion& completion)
|
||||||
@@ -104,15 +69,7 @@ void OpenGLVideoIOBridge::PlayoutFrameCompleted(const VideoIOCompletion& complet
|
|||||||
frameContext.videoState = state;
|
frameContext.videoState = state;
|
||||||
frameContext.completion = completion;
|
frameContext.completion = completion;
|
||||||
|
|
||||||
EnterCriticalSection(&mMutex);
|
mRenderEngine.RenderOutputFrame(frameContext, outputFrame);
|
||||||
|
|
||||||
// make GL context current in this thread
|
|
||||||
wglMakeCurrent(mHdc, mHglrc);
|
|
||||||
|
|
||||||
mRenderPipeline.RenderFrame(frameContext, outputFrame);
|
|
||||||
wglMakeCurrent(NULL, NULL);
|
|
||||||
|
|
||||||
LeaveCriticalSection(&mMutex);
|
|
||||||
|
|
||||||
mVideoIO.EndOutputFrame(outputFrame);
|
mVideoIO.EndOutputFrame(outputFrame);
|
||||||
|
|
||||||
|
|||||||
@@ -2,24 +2,19 @@
|
|||||||
|
|
||||||
#include "OpenGLRenderPipeline.h"
|
#include "OpenGLRenderPipeline.h"
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
class RuntimeHost;
|
class HealthTelemetry;
|
||||||
|
class RenderEngine;
|
||||||
|
|
||||||
class OpenGLVideoIOBridge
|
class OpenGLVideoIOBridge
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OpenGLVideoIOBridge(
|
OpenGLVideoIOBridge(
|
||||||
VideoIODevice& videoIO,
|
VideoIODevice& videoIO,
|
||||||
OpenGLRenderer& renderer,
|
RenderEngine& renderEngine,
|
||||||
OpenGLRenderPipeline& renderPipeline,
|
HealthTelemetry& healthTelemetry);
|
||||||
RuntimeHost& runtimeHost,
|
|
||||||
CRITICAL_SECTION& mutex,
|
|
||||||
HDC hdc,
|
|
||||||
HGLRC hglrc);
|
|
||||||
|
|
||||||
void VideoFrameArrived(const VideoIOFrame& inputFrame);
|
void VideoFrameArrived(const VideoIOFrame& inputFrame);
|
||||||
void PlayoutFrameCompleted(const VideoIOCompletion& completion);
|
void PlayoutFrameCompleted(const VideoIOCompletion& completion);
|
||||||
@@ -28,12 +23,8 @@ private:
|
|||||||
void RecordFramePacing(VideoIOCompletionResult completionResult);
|
void RecordFramePacing(VideoIOCompletionResult completionResult);
|
||||||
|
|
||||||
VideoIODevice& mVideoIO;
|
VideoIODevice& mVideoIO;
|
||||||
OpenGLRenderer& mRenderer;
|
RenderEngine& mRenderEngine;
|
||||||
OpenGLRenderPipeline& mRenderPipeline;
|
HealthTelemetry& mHealthTelemetry;
|
||||||
RuntimeHost& mRuntimeHost;
|
|
||||||
CRITICAL_SECTION& mMutex;
|
|
||||||
HDC mHdc;
|
|
||||||
HGLRC mHglrc;
|
|
||||||
std::chrono::steady_clock::time_point mLastPlayoutCompletionTime;
|
std::chrono::steady_clock::time_point mLastPlayoutCompletionTime;
|
||||||
double mCompletionIntervalMilliseconds = 0.0;
|
double mCompletionIntervalMilliseconds = 0.0;
|
||||||
double mSmoothedCompletionIntervalMilliseconds = 0.0;
|
double mSmoothedCompletionIntervalMilliseconds = 0.0;
|
||||||
|
|||||||
175
apps/LoopThroughWithOpenGLCompositing/videoio/VideoBackend.cpp
Normal file
175
apps/LoopThroughWithOpenGLCompositing/videoio/VideoBackend.cpp
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
#include "VideoBackend.h"
|
||||||
|
|
||||||
|
#include "DeckLinkSession.h"
|
||||||
|
#include "OpenGLVideoIOBridge.h"
|
||||||
|
#include "RenderEngine.h"
|
||||||
|
#include "HealthTelemetry.h"
|
||||||
|
|
||||||
|
VideoBackend::VideoBackend(RenderEngine& renderEngine, HealthTelemetry& healthTelemetry) :
|
||||||
|
mVideoIODevice(std::make_unique<DeckLinkSession>()),
|
||||||
|
mBridge(std::make_unique<OpenGLVideoIOBridge>(*mVideoIODevice, renderEngine, healthTelemetry))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoBackend::~VideoBackend()
|
||||||
|
{
|
||||||
|
ReleaseResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoBackend::ReleaseResources()
|
||||||
|
{
|
||||||
|
if (mVideoIODevice)
|
||||||
|
mVideoIODevice->ReleaseResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::DiscoverDevicesAndModes(const VideoFormatSelection& videoModes, std::string& error)
|
||||||
|
{
|
||||||
|
return mVideoIODevice->DiscoverDevicesAndModes(videoModes, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::SelectPreferredFormats(const VideoFormatSelection& videoModes, bool outputAlphaRequired, std::string& error)
|
||||||
|
{
|
||||||
|
return mVideoIODevice->SelectPreferredFormats(videoModes, outputAlphaRequired, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::ConfigureInput(const VideoFormat& inputVideoMode, std::string& error)
|
||||||
|
{
|
||||||
|
return mVideoIODevice->ConfigureInput(
|
||||||
|
[this](const VideoIOFrame& frame) { mBridge->VideoFrameArrived(frame); },
|
||||||
|
inputVideoMode,
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::ConfigureOutput(const VideoFormat& outputVideoMode, bool externalKeyingEnabled, std::string& error)
|
||||||
|
{
|
||||||
|
return mVideoIODevice->ConfigureOutput(
|
||||||
|
[this](const VideoIOCompletion& completion) { mBridge->PlayoutFrameCompleted(completion); },
|
||||||
|
outputVideoMode,
|
||||||
|
externalKeyingEnabled,
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::Start()
|
||||||
|
{
|
||||||
|
return mVideoIODevice->Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::Stop()
|
||||||
|
{
|
||||||
|
return mVideoIODevice->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
const VideoIOState& VideoBackend::State() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->State();
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoIOState& VideoBackend::MutableState()
|
||||||
|
{
|
||||||
|
return mVideoIODevice->MutableState();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::BeginOutputFrame(VideoIOOutputFrame& frame)
|
||||||
|
{
|
||||||
|
return mVideoIODevice->BeginOutputFrame(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoBackend::EndOutputFrame(VideoIOOutputFrame& frame)
|
||||||
|
{
|
||||||
|
mVideoIODevice->EndOutputFrame(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::ScheduleOutputFrame(const VideoIOOutputFrame& frame)
|
||||||
|
{
|
||||||
|
return mVideoIODevice->ScheduleOutputFrame(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoBackend::AccountForCompletionResult(VideoIOCompletionResult result)
|
||||||
|
{
|
||||||
|
mVideoIODevice->AccountForCompletionResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::HasInputDevice() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->HasInputDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::HasInputSource() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->HasInputSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned VideoBackend::InputFrameWidth() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->InputFrameWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned VideoBackend::InputFrameHeight() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->InputFrameHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned VideoBackend::OutputFrameWidth() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->OutputFrameWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned VideoBackend::OutputFrameHeight() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->OutputFrameHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned VideoBackend::CaptureTextureWidth() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->CaptureTextureWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned VideoBackend::OutputPackTextureWidth() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->OutputPackTextureWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoIOPixelFormat VideoBackend::InputPixelFormat() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->InputPixelFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& VideoBackend::InputDisplayModeName() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->InputDisplayModeName();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& VideoBackend::OutputModelName() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->OutputModelName();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::SupportsInternalKeying() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->SupportsInternalKeying();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::SupportsExternalKeying() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->SupportsExternalKeying();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::KeyerInterfaceAvailable() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->KeyerInterfaceAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VideoBackend::ExternalKeyingActive() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->ExternalKeyingActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& VideoBackend::StatusMessage() const
|
||||||
|
{
|
||||||
|
return mVideoIODevice->StatusMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoBackend::SetStatusMessage(const std::string& message)
|
||||||
|
{
|
||||||
|
mVideoIODevice->SetStatusMessage(message);
|
||||||
|
}
|
||||||
55
apps/LoopThroughWithOpenGLCompositing/videoio/VideoBackend.h
Normal file
55
apps/LoopThroughWithOpenGLCompositing/videoio/VideoBackend.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "VideoIOTypes.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class HealthTelemetry;
|
||||||
|
class OpenGLVideoIOBridge;
|
||||||
|
class RenderEngine;
|
||||||
|
class VideoIODevice;
|
||||||
|
|
||||||
|
class VideoBackend
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VideoBackend(RenderEngine& renderEngine, HealthTelemetry& healthTelemetry);
|
||||||
|
~VideoBackend();
|
||||||
|
|
||||||
|
void ReleaseResources();
|
||||||
|
bool DiscoverDevicesAndModes(const VideoFormatSelection& videoModes, std::string& error);
|
||||||
|
bool SelectPreferredFormats(const VideoFormatSelection& videoModes, bool outputAlphaRequired, std::string& error);
|
||||||
|
bool ConfigureInput(const VideoFormat& inputVideoMode, std::string& error);
|
||||||
|
bool ConfigureOutput(const VideoFormat& outputVideoMode, bool externalKeyingEnabled, std::string& error);
|
||||||
|
bool Start();
|
||||||
|
bool Stop();
|
||||||
|
|
||||||
|
const VideoIOState& State() const;
|
||||||
|
VideoIOState& MutableState();
|
||||||
|
bool BeginOutputFrame(VideoIOOutputFrame& frame);
|
||||||
|
void EndOutputFrame(VideoIOOutputFrame& frame);
|
||||||
|
bool ScheduleOutputFrame(const VideoIOOutputFrame& frame);
|
||||||
|
void AccountForCompletionResult(VideoIOCompletionResult result);
|
||||||
|
|
||||||
|
bool HasInputDevice() const;
|
||||||
|
bool HasInputSource() const;
|
||||||
|
unsigned InputFrameWidth() const;
|
||||||
|
unsigned InputFrameHeight() const;
|
||||||
|
unsigned OutputFrameWidth() const;
|
||||||
|
unsigned OutputFrameHeight() const;
|
||||||
|
unsigned CaptureTextureWidth() const;
|
||||||
|
unsigned OutputPackTextureWidth() const;
|
||||||
|
VideoIOPixelFormat InputPixelFormat() const;
|
||||||
|
const std::string& InputDisplayModeName() const;
|
||||||
|
const std::string& OutputModelName() const;
|
||||||
|
bool SupportsInternalKeying() const;
|
||||||
|
bool SupportsExternalKeying() const;
|
||||||
|
bool KeyerInterfaceAvailable() const;
|
||||||
|
bool ExternalKeyingActive() const;
|
||||||
|
const std::string& StatusMessage() const;
|
||||||
|
void SetStatusMessage(const std::string& message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<VideoIODevice> mVideoIODevice;
|
||||||
|
std::unique_ptr<OpenGLVideoIOBridge> mBridge;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user