OSC updates and video resolution fixes
Some checks failed
CI / Native Windows Build And Tests (push) Failing after 7s
CI / React UI Build (push) Has been cancelled
CI / Windows Release Package (push) Has been cancelled

This commit is contained in:
2026-05-03 14:33:33 +10:00
parent bfc12a1aea
commit 7dc4b552a5
20 changed files with 842 additions and 124 deletions

View File

@@ -192,6 +192,28 @@ bool ResolveConfiguredDisplayMode(const std::string& videoFormat, const std::str
return false;
}
bool FindDeckLinkDisplayMode(IDeckLinkDisplayModeIterator* iterator, BMDDisplayMode targetMode, IDeckLinkDisplayMode** foundMode)
{
if (!iterator || !foundMode)
return false;
*foundMode = NULL;
IDeckLinkDisplayMode* candidate = NULL;
while (iterator->Next(&candidate) == S_OK)
{
if (candidate->GetDisplayMode() == targetMode)
{
*foundMode = candidate;
return true;
}
candidate->Release();
candidate = NULL;
}
return false;
}
class ScopedGlShader
{
public:
@@ -295,8 +317,10 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
mCaptureDelegate(NULL), mPlayoutDelegate(NULL),
mDLInput(NULL), mDLOutput(NULL), mDLKeyer(NULL),
mPlayoutAllocator(NULL),
mFrameWidth(0), mFrameHeight(0),
mDisplayModeName("1080p59.94"),
mInputFrameWidth(0), mInputFrameHeight(0),
mOutputFrameWidth(0), mOutputFrameHeight(0),
mInputDisplayModeName("1080p59.94"),
mOutputDisplayModeName("1080p59.94"),
mHasNoInputSource(true),
mDeckLinkSupportsInternalKeying(false),
mDeckLinkSupportsExternalKeying(false),
@@ -307,10 +331,12 @@ OpenGLComposite::OpenGLComposite(HWND hWnd, HDC hDC, HGLRC hRC) :
mDecodedTexture(0),
mLayerTempTexture(0),
mFBOTexture(0),
mOutputTexture(0),
mUnpinnedTextureBuffer(0),
mDecodeFrameBuf(0),
mLayerTempFrameBuf(0),
mIdFrameBuf(0),
mOutputFrameBuf(0),
mIdColorBuf(0),
mIdDepthBuf(0),
mFullscreenVAO(0),
@@ -407,6 +433,10 @@ OpenGLComposite::~OpenGLComposite()
glDeleteTextures(1, &mLayerTempTexture);
if (mFBOTexture != 0)
glDeleteTextures(1, &mFBOTexture);
if (mOutputTexture != 0)
glDeleteTextures(1, &mOutputTexture);
if (mOutputFrameBuf != 0)
glDeleteFramebuffers(1, &mOutputFrameBuf);
if (mUnpinnedTextureBuffer != 0)
glDeleteBuffers(1, &mUnpinnedTextureBuffer);
@@ -427,10 +457,14 @@ bool OpenGLComposite::InitDeckLink()
IDeckLinkIterator* pDLIterator = NULL;
IDeckLink* pDL = NULL;
IDeckLinkProfileAttributes* deckLinkAttributes = NULL;
IDeckLinkDisplayModeIterator* pDLDisplayModeIterator = NULL;
IDeckLinkDisplayMode* pDLDisplayMode = NULL;
BMDDisplayMode displayMode = bmdModeHD1080p5994; // mode to use for capture and playout
std::string displayModeName = "1080p59.94";
IDeckLinkDisplayModeIterator* pDLInputDisplayModeIterator = NULL;
IDeckLinkDisplayModeIterator* pDLOutputDisplayModeIterator = NULL;
IDeckLinkDisplayMode* pDLInputDisplayMode = NULL;
IDeckLinkDisplayMode* pDLOutputDisplayMode = NULL;
BMDDisplayMode inputDisplayMode = bmdModeHD1080p5994;
BMDDisplayMode outputDisplayMode = bmdModeHD1080p5994;
std::string inputDisplayModeName = "1080p59.94";
std::string outputDisplayModeName = "1080p59.94";
int outputFrameRowBytes;
HRESULT result;
@@ -446,15 +480,23 @@ bool OpenGLComposite::InitDeckLink()
if (mRuntimeHost)
{
if (!ResolveConfiguredDisplayMode(mRuntimeHost->GetVideoFormat(), mRuntimeHost->GetFrameRate(), displayMode, displayModeName))
if (!ResolveConfiguredDisplayMode(mRuntimeHost->GetInputVideoFormat(), mRuntimeHost->GetInputFrameRate(), inputDisplayMode, inputDisplayModeName))
{
const std::string error = "Unsupported DeckLink video format/frameRate in config/runtime-host.json: " +
mRuntimeHost->GetVideoFormat() + " / " + mRuntimeHost->GetFrameRate();
MessageBoxA(NULL, error.c_str(), "DeckLink mode configuration error", MB_OK);
const std::string error = "Unsupported DeckLink inputVideoFormat/inputFrameRate in config/runtime-host.json: " +
mRuntimeHost->GetInputVideoFormat() + " / " + mRuntimeHost->GetInputFrameRate();
MessageBoxA(NULL, error.c_str(), "DeckLink input mode configuration error", MB_OK);
return false;
}
if (!ResolveConfiguredDisplayMode(mRuntimeHost->GetOutputVideoFormat(), mRuntimeHost->GetOutputFrameRate(), outputDisplayMode, outputDisplayModeName))
{
const std::string error = "Unsupported DeckLink outputVideoFormat/outputFrameRate in config/runtime-host.json: " +
mRuntimeHost->GetOutputVideoFormat() + " / " + mRuntimeHost->GetOutputFrameRate();
MessageBoxA(NULL, error.c_str(), "DeckLink output mode configuration error", MB_OK);
return false;
}
}
mDisplayModeName = displayModeName;
mInputDisplayModeName = inputDisplayModeName;
mOutputDisplayModeName = outputDisplayModeName;
result = CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void**)&pDLIterator);
if (FAILED(result))
@@ -538,35 +580,48 @@ bool OpenGLComposite::InitDeckLink()
goto error;
}
if (mDLOutput->GetDisplayModeIterator(&pDLDisplayModeIterator) != S_OK)
if (mDLInput->GetDisplayModeIterator(&pDLInputDisplayModeIterator) != S_OK)
{
MessageBox(NULL, _T("Cannot get Display Mode Iterator."), _T("DeckLink error."), MB_OK);
MessageBox(NULL, _T("Cannot get input Display Mode Iterator."), _T("DeckLink error."), MB_OK);
goto error;
}
while (pDLDisplayModeIterator->Next(&pDLDisplayMode) == S_OK)
if (!FindDeckLinkDisplayMode(pDLInputDisplayModeIterator, inputDisplayMode, &pDLInputDisplayMode))
{
if (pDLDisplayMode->GetDisplayMode() == displayMode)
break;
pDLDisplayMode->Release();
pDLDisplayMode = NULL;
const std::string error = "Cannot get specified input BMDDisplayMode for configured mode: " + inputDisplayModeName;
MessageBoxA(NULL, error.c_str(), "DeckLink input error.", MB_OK);
goto error;
}
pDLDisplayModeIterator->Release();
pDLDisplayModeIterator = NULL;
pDLInputDisplayModeIterator->Release();
pDLInputDisplayModeIterator = NULL;
if (pDLDisplayMode == NULL)
if (mDLOutput->GetDisplayModeIterator(&pDLOutputDisplayModeIterator) != S_OK)
{
const std::string error = "Cannot get specified BMDDisplayMode for configured mode: " + displayModeName;
MessageBoxA(NULL, error.c_str(), "DeckLink error.", MB_OK);
MessageBox(NULL, _T("Cannot get output Display Mode Iterator."), _T("DeckLink error."), MB_OK);
goto error;
}
mFrameWidth = pDLDisplayMode->GetWidth();
mFrameHeight = pDLDisplayMode->GetHeight();
if (!FindDeckLinkDisplayMode(pDLOutputDisplayModeIterator, outputDisplayMode, &pDLOutputDisplayMode))
{
const std::string error = "Cannot get specified output BMDDisplayMode for configured mode: " + outputDisplayModeName;
MessageBoxA(NULL, error.c_str(), "DeckLink output error.", MB_OK);
goto error;
}
pDLOutputDisplayModeIterator->Release();
pDLOutputDisplayModeIterator = NULL;
mInputFrameWidth = pDLInputDisplayMode->GetWidth();
mInputFrameHeight = pDLInputDisplayMode->GetHeight();
mOutputFrameWidth = pDLOutputDisplayMode->GetWidth();
mOutputFrameHeight = pDLOutputDisplayMode->GetHeight();
if (! CheckOpenGLExtensions())
goto error;
if (mInputFrameWidth != mOutputFrameWidth || mInputFrameHeight != mOutputFrameHeight)
{
mFastTransferExtensionAvailable = false;
OutputDebugStringA("Input/output dimensions differ; using regular OpenGL transfer fallback instead of fast transfer.\n");
}
if (! InitOpenGLState())
goto error;
@@ -586,18 +641,18 @@ bool OpenGLComposite::InitDeckLink()
mDeckLinkStatusMessage);
}
pDLDisplayMode->GetFrameRate(&mFrameDuration, &mFrameTimescale);
pDLOutputDisplayMode->GetFrameRate(&mFrameDuration, &mFrameTimescale);
// Resize window to match video frame, but scale large formats down by half for viewing
if (mFrameWidth < 1920)
resizeWindow(mFrameWidth, mFrameHeight);
// Resize window to match output video frame, but scale large formats down by half for viewing.
if (mOutputFrameWidth < 1920)
resizeWindow(mOutputFrameWidth, mOutputFrameHeight);
else
resizeWindow(mFrameWidth / 2, mFrameHeight / 2);
resizeWindow(mOutputFrameWidth / 2, mOutputFrameHeight / 2);
if (mFastTransferExtensionAvailable)
{
// Initialize fast video frame transfers
if (! VideoFrameTransfer::initialize(mFrameWidth, mFrameHeight, mCaptureTexture, mFBOTexture))
if (! VideoFrameTransfer::initialize(mInputFrameWidth, mInputFrameHeight, mCaptureTexture, mOutputTexture))
{
MessageBox(NULL, _T("Cannot initialize video transfers."), _T("VideoFrameTransfer error."), MB_OK);
goto error;
@@ -608,7 +663,7 @@ bool OpenGLComposite::InitDeckLink()
// Use custom allocators so we pin only once then recycle them
CComPtr<IDeckLinkVideoBufferAllocatorProvider> captureAllocator(new (std::nothrow) InputAllocatorPool(hGLDC, hGLRC));
if (mDLInput->EnableVideoInputWithAllocatorProvider(displayMode, bmdFormat8BitYUV, bmdVideoInputFlagDefault, captureAllocator) != S_OK)
if (mDLInput->EnableVideoInputWithAllocatorProvider(inputDisplayMode, bmdFormat8BitYUV, bmdVideoInputFlagDefault, captureAllocator) != S_OK)
goto error;
}
@@ -616,13 +671,13 @@ bool OpenGLComposite::InitDeckLink()
if (mDLInput->SetCallback(mCaptureDelegate) != S_OK)
goto error;
if (mDLOutput->RowBytesForPixelFormat(bmdFormat8BitBGRA, mFrameWidth, &outputFrameRowBytes) != S_OK)
if (mDLOutput->RowBytesForPixelFormat(bmdFormat8BitBGRA, mOutputFrameWidth, &outputFrameRowBytes) != S_OK)
goto error;
// Use a custom allocator so we pin only once then recycle them
mPlayoutAllocator = new PinnedMemoryAllocator(hGLDC, hGLRC, VideoFrameTransfer::GPUtoCPU, 1, outputFrameRowBytes * mFrameHeight);
mPlayoutAllocator = new PinnedMemoryAllocator(hGLDC, hGLRC, VideoFrameTransfer::GPUtoCPU, 1, outputFrameRowBytes * mOutputFrameHeight);
if (mDLOutput->EnableVideoOutput(displayMode, bmdVideoOutputFlagDefault) != S_OK)
if (mDLOutput->EnableVideoOutput(outputDisplayMode, bmdVideoOutputFlagDefault) != S_OK)
goto error;
if (mDLOutput->QueryInterface(IID_IDeckLinkKeyer, (void**)&mDLKeyer) == S_OK && mDLKeyer != NULL)
@@ -680,7 +735,7 @@ bool OpenGLComposite::InitDeckLink()
if (mPlayoutAllocator->AllocateVideoBuffer(&outputFrameBuffer) != S_OK)
goto error;
if (mDLOutput->CreateVideoFrameWithBuffer(mFrameWidth, mFrameHeight, outputFrameRowBytes, bmdFormat8BitBGRA, bmdFrameFlagFlipVertical, outputFrameBuffer, &outputFrame) != S_OK)
if (mDLOutput->CreateVideoFrameWithBuffer(mOutputFrameWidth, mOutputFrameHeight, outputFrameRowBytes, bmdFormat8BitBGRA, bmdFrameFlagFlipVertical, outputFrameBuffer, &outputFrame) != S_OK)
goto error;
mDLOutputVideoFrameQueue.push_back(outputFrame);
@@ -723,10 +778,28 @@ error:
pDL = NULL;
}
if (pDLDisplayMode != NULL)
if (pDLInputDisplayMode != NULL)
{
pDLDisplayMode->Release();
pDLDisplayMode = NULL;
pDLInputDisplayMode->Release();
pDLInputDisplayMode = NULL;
}
if (pDLOutputDisplayMode != NULL)
{
pDLOutputDisplayMode->Release();
pDLOutputDisplayMode = NULL;
}
if (pDLInputDisplayModeIterator != NULL)
{
pDLInputDisplayModeIterator->Release();
pDLInputDisplayModeIterator = NULL;
}
if (pDLOutputDisplayModeIterator != NULL)
{
pDLOutputDisplayModeIterator->Release();
pDLOutputDisplayModeIterator = NULL;
}
if (pDLIterator != NULL)
@@ -757,9 +830,9 @@ void OpenGLComposite::paintGL()
int destX = 0;
int destY = 0;
if (mFrameWidth > 0 && mFrameHeight > 0 && mViewWidth > 0 && mViewHeight > 0)
if (mOutputFrameWidth > 0 && mOutputFrameHeight > 0 && mViewWidth > 0 && mViewHeight > 0)
{
const double frameAspect = static_cast<double>(mFrameWidth) / static_cast<double>(mFrameHeight);
const double frameAspect = static_cast<double>(mOutputFrameWidth) / static_cast<double>(mOutputFrameHeight);
const double viewAspect = static_cast<double>(mViewWidth) / static_cast<double>(mViewHeight);
if (viewAspect > frameAspect)
@@ -776,12 +849,12 @@ void OpenGLComposite::paintGL()
}
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, mIdFrameBuf);
glBindFramebuffer(GL_READ_FRAMEBUFFER, mOutputFrameBuf);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glViewport(0, 0, mViewWidth, mViewHeight);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBlitFramebuffer(0, 0, mFrameWidth, mFrameHeight, destX, destY, destX + destWidth, destY + destHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBlitFramebuffer(0, 0, mOutputFrameWidth, mOutputFrameHeight, destX, destY, destX + destWidth, destY + destHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
SwapBuffers(hGLDC);
ValidateRect(hGLWnd, NULL);
@@ -893,7 +966,7 @@ bool OpenGLComposite::InitOpenGLState()
// Create texture with empty data, we will update it using glTexSubImage2D each frame.
// The captured video is YCbCr 4:2:2 packed into a UYVY macropixel. OpenGL has no YCbCr format
// so treat it as RGBA 4:4:4:4 by halving the width and using GL_RGBA internal format.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mFrameWidth/2, mFrameHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mInputFrameWidth / 2, mInputFrameHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glGenTextures(1, &mDecodedTexture);
@@ -902,7 +975,7 @@ bool OpenGLComposite::InitOpenGLState()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mFrameWidth, mFrameHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mInputFrameWidth, mInputFrameHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glGenTextures(1, &mLayerTempTexture);
@@ -911,7 +984,7 @@ bool OpenGLComposite::InitOpenGLState()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mFrameWidth, mFrameHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mInputFrameWidth, mInputFrameHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
@@ -920,6 +993,7 @@ bool OpenGLComposite::InitOpenGLState()
glGenFramebuffers(1, &mDecodeFrameBuf);
glGenFramebuffers(1, &mLayerTempFrameBuf);
glGenFramebuffers(1, &mIdFrameBuf);
glGenFramebuffers(1, &mOutputFrameBuf);
glGenRenderbuffers(1, &mIdColorBuf);
glGenRenderbuffers(1, &mIdDepthBuf);
glGenVertexArrays(1, &mFullscreenVAO);
@@ -952,11 +1026,11 @@ bool OpenGLComposite::InitOpenGLState()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mFrameWidth, mFrameHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mInputFrameWidth, mInputFrameHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
// Attach a depth buffer
glBindRenderbuffer(GL_RENDERBUFFER, mIdDepthBuf);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mFrameWidth, mFrameHeight);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mInputFrameWidth, mInputFrameHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER, mIdDepthBuf);
@@ -970,6 +1044,23 @@ bool OpenGLComposite::InitOpenGLState()
return false;
}
glGenTextures(1, &mOutputTexture);
glBindTexture(GL_TEXTURE_2D, mOutputTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mOutputFrameWidth, mOutputFrameHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glBindFramebuffer(GL_FRAMEBUFFER, mOutputFrameBuf);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mOutputTexture, 0);
glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (glStatus != GL_FRAMEBUFFER_COMPLETE)
{
MessageBox(NULL, _T("Cannot initialize output framebuffer."), _T("OpenGL initialization error."), MB_OK);
return false;
}
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -991,7 +1082,7 @@ void OpenGLComposite::VideoFrameArrived(IDeckLinkVideoInputFrame* inputFrame, bo
{
mHasNoInputSource = hasNoInputSource;
if (mRuntimeHost)
mRuntimeHost->SetSignalStatus(!hasNoInputSource, mFrameWidth, mFrameHeight, mDisplayModeName);
mRuntimeHost->SetSignalStatus(!hasNoInputSource, mInputFrameWidth, mInputFrameHeight, mInputDisplayModeName);
if (mHasNoInputSource)
return; // don't transfer texture when there's no input
@@ -1030,7 +1121,7 @@ void OpenGLComposite::VideoFrameArrived(IDeckLinkVideoInputFrame* inputFrame, bo
glBindTexture(GL_TEXTURE_2D, mCaptureTexture);
// NULL for last arg indicates use current GL_PIXEL_UNPACK_BUFFER target as texture data
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mFrameWidth/2, mFrameHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mInputFrameWidth / 2, mInputFrameHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
@@ -1064,6 +1155,10 @@ void OpenGLComposite::PlayoutFrameCompleted(IDeckLinkVideoFrame* completedFrame,
VideoFrameTransfer::beginTextureInUse(VideoFrameTransfer::GPUtoCPU);
glBindFramebuffer(GL_FRAMEBUFFER, mIdFrameBuf);
renderEffect();
glBindFramebuffer(GL_READ_FRAMEBUFFER, mIdFrameBuf);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mOutputFrameBuf);
glBlitFramebuffer(0, 0, mInputFrameWidth, mInputFrameHeight, 0, 0, mOutputFrameWidth, mOutputFrameHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_FRAMEBUFFER, mOutputFrameBuf);
glFlush();
if (mFastTransferExtensionAvailable)
VideoFrameTransfer::endTextureInUse(VideoFrameTransfer::GPUtoCPU);
@@ -1101,7 +1196,7 @@ void OpenGLComposite::PlayoutFrameCompleted(IDeckLinkVideoFrame* completedFrame,
// Finished with mCaptureTexture
VideoFrameTransfer::endTextureInUse(VideoFrameTransfer::CPUtoGPU);
if (! mPlayoutAllocator->transferFrame(pFrame, mFBOTexture))
if (! mPlayoutAllocator->transferFrame(pFrame, mOutputTexture))
OutputDebugStringA("Playback: transferFrame() failed\n");
paintGL();
@@ -1111,8 +1206,8 @@ void OpenGLComposite::PlayoutFrameCompleted(IDeckLinkVideoFrame* completedFrame,
}
else
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, mIdFrameBuf);
glReadPixels(0, 0, mFrameWidth, mFrameHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pFrame);
glBindFramebuffer(GL_READ_FRAMEBUFFER, mOutputFrameBuf);
glReadPixels(0, 0, mOutputFrameWidth, mOutputFrameHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pFrame);
paintGL();
}
@@ -1158,7 +1253,7 @@ bool OpenGLComposite::Start()
void* pFrame;
outputVideoFrameBuffer->GetBytes((void**)&pFrame);
memset(pFrame, 0, outputVideoFrame->GetRowBytes() * mFrameHeight); // 0 is black in RGBA format
memset(pFrame, 0, outputVideoFrame->GetRowBytes() * mOutputFrameHeight); // 0 is black in BGRA format
outputVideoFrameBuffer->EndAccess(bmdBufferAccessWrite);
outputVideoFrameBuffer->Release();
@@ -1347,7 +1442,7 @@ bool OpenGLComposite::compileSingleLayerProgram(const RuntimeRenderState& state,
bool OpenGLComposite::compileLayerPrograms(int errorMessageSize, char* errorMessage)
{
const std::vector<RuntimeRenderState> layerStates = mRuntimeHost ? mRuntimeHost->GetLayerRenderStates(mFrameWidth, mFrameHeight) : std::vector<RuntimeRenderState>();
const std::vector<RuntimeRenderState> layerStates = mRuntimeHost ? mRuntimeHost->GetLayerRenderStates(mInputFrameWidth, mInputFrameHeight) : std::vector<RuntimeRenderState>();
std::string temporalError;
if (!validateTemporalTextureUnitBudget(layerStates, temporalError))
{
@@ -1650,7 +1745,7 @@ bool OpenGLComposite::createHistoryRing(HistoryRing& ring, unsigned effectiveLen
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mFrameWidth, mFrameHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mInputFrameWidth, mInputFrameHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
glGenFramebuffers(1, &slot.framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, slot.framebuffer);
@@ -1768,7 +1863,7 @@ void OpenGLComposite::pushFramebufferToHistoryRing(GLuint sourceFramebuffer, His
HistorySlot& targetSlot = ring.slots[ring.nextWriteIndex];
glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, targetSlot.framebuffer);
glBlitFramebuffer(0, 0, mFrameWidth, mFrameHeight, 0, 0, mFrameWidth, mFrameHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBlitFramebuffer(0, 0, mInputFrameWidth, mInputFrameHeight, 0, 0, mInputFrameWidth, mInputFrameHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
ring.nextWriteIndex = (ring.nextWriteIndex + 1) % ring.slots.size();
ring.filledCount = std::min<std::size_t>(ring.filledCount + 1, ring.slots.size());
}
@@ -1837,12 +1932,12 @@ void OpenGLComposite::renderEffect()
glDisable(GL_DEPTH_TEST);
renderDecodePass();
const std::vector<RuntimeRenderState> layerStates = mRuntimeHost ? mRuntimeHost->GetLayerRenderStates(mFrameWidth, mFrameHeight) : std::vector<RuntimeRenderState>();
const std::vector<RuntimeRenderState> layerStates = mRuntimeHost ? mRuntimeHost->GetLayerRenderStates(mInputFrameWidth, mInputFrameHeight) : std::vector<RuntimeRenderState>();
if (layerStates.empty() || mLayerPrograms.empty())
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, mDecodeFrameBuf);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mIdFrameBuf);
glBlitFramebuffer(0, 0, mFrameWidth, mFrameHeight, 0, 0, mFrameWidth, mFrameHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBlitFramebuffer(0, 0, mInputFrameWidth, mInputFrameHeight, 0, 0, mInputFrameWidth, mInputFrameHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_FRAMEBUFFER, mIdFrameBuf);
}
else
@@ -1874,7 +1969,7 @@ void OpenGLComposite::renderEffect()
void OpenGLComposite::renderShaderProgram(GLuint sourceTexture, GLuint destinationFrameBuffer, const LayerProgram& layerProgram, const RuntimeRenderState& state)
{
glBindFramebuffer(GL_FRAMEBUFFER, destinationFrameBuffer);
glViewport(0, 0, mFrameWidth, mFrameHeight);
glViewport(0, 0, mInputFrameWidth, mInputFrameHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0 + kDecodedVideoTextureUnit);
glBindTexture(GL_TEXTURE_2D, sourceTexture);
@@ -1908,7 +2003,7 @@ void OpenGLComposite::renderShaderProgram(GLuint sourceTexture, GLuint destinati
void OpenGLComposite::renderDecodePass()
{
glBindFramebuffer(GL_FRAMEBUFFER, mDecodeFrameBuf);
glViewport(0, 0, mFrameWidth, mFrameHeight);
glViewport(0, 0, mInputFrameWidth, mInputFrameHeight);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0 + kPackedVideoTextureUnit);
glBindTexture(GL_TEXTURE_2D, mCaptureTexture);
@@ -1918,9 +2013,9 @@ void OpenGLComposite::renderDecodePass()
const GLint packedResolutionLocation = glGetUniformLocation(mDecodeProgram, "uPackedVideoResolution");
const GLint decodedResolutionLocation = glGetUniformLocation(mDecodeProgram, "uDecodedVideoResolution");
if (packedResolutionLocation >= 0)
glUniform2f(packedResolutionLocation, static_cast<float>(mFrameWidth / 2), static_cast<float>(mFrameHeight));
glUniform2f(packedResolutionLocation, static_cast<float>(mInputFrameWidth / 2), static_cast<float>(mInputFrameHeight));
if (decodedResolutionLocation >= 0)
glUniform2f(decodedResolutionLocation, static_cast<float>(mFrameWidth), static_cast<float>(mFrameHeight));
glUniform2f(decodedResolutionLocation, static_cast<float>(mInputFrameWidth), static_cast<float>(mInputFrameHeight));
glDrawArrays(GL_TRIANGLES, 0, 3);