decklink separation
Some checks failed
CI / Native Windows Build And Tests (push) Has been cancelled
CI / React UI Build (push) Has been cancelled
CI / Windows Release Package (push) Has been cancelled

This commit is contained in:
2026-05-06 10:31:21 +10:00
parent 8ec87685b8
commit 6918306336
7 changed files with 319 additions and 298 deletions

View File

@@ -0,0 +1,148 @@
#include "DeckLinkSession.h"
#include "GlRenderConstants.h"
#include <cstring>
DeckLinkSession::~DeckLinkSession()
{
ReleaseResources();
}
void DeckLinkSession::ReleaseResources()
{
if (input != nullptr)
{
input->SetCallback(nullptr);
if (captureDelegate != nullptr)
{
captureDelegate->Release();
captureDelegate = nullptr;
}
input->Release();
input = nullptr;
}
while (!outputVideoFrameQueue.empty())
{
IDeckLinkMutableVideoFrame* frameToRelease = outputVideoFrameQueue.front();
if (frameToRelease != nullptr)
frameToRelease->Release();
outputVideoFrameQueue.pop_front();
}
if (output != nullptr)
{
if (keyer != nullptr)
{
keyer->Disable();
keyer->Release();
keyer = nullptr;
externalKeyingActive = false;
}
output->SetScheduledFrameCompletionCallback(nullptr);
if (playoutDelegate != nullptr)
{
playoutDelegate->Release();
playoutDelegate = nullptr;
}
output->Release();
output = nullptr;
}
if (playoutAllocator != nullptr)
{
playoutAllocator->Release();
playoutAllocator = nullptr;
}
}
bool DeckLinkSession::Start(unsigned outputHeight)
{
totalPlayoutFrames = 0;
if (!output)
{
MessageBoxA(NULL, "Cannot start playout because no DeckLink output device is available.", "DeckLink start failed", MB_OK | MB_ICONERROR);
return false;
}
if (outputVideoFrameQueue.empty())
{
MessageBoxA(NULL, "Cannot start playout because the output frame queue is empty.", "DeckLink start failed", MB_OK | MB_ICONERROR);
return false;
}
for (unsigned i = 0; i < kPrerollFrameCount; i++)
{
IDeckLinkMutableVideoFrame* outputVideoFrame = outputVideoFrameQueue.front();
outputVideoFrameQueue.push_back(outputVideoFrame);
outputVideoFrameQueue.pop_front();
IDeckLinkVideoBuffer* outputVideoFrameBuffer;
if (outputVideoFrame->QueryInterface(IID_IDeckLinkVideoBuffer, (void**)&outputVideoFrameBuffer) != S_OK)
{
MessageBoxA(NULL, "Could not query the preroll output frame buffer.", "DeckLink start failed", MB_OK | MB_ICONERROR);
return false;
}
if (outputVideoFrameBuffer->StartAccess(bmdBufferAccessWrite) != S_OK)
{
outputVideoFrameBuffer->Release();
MessageBoxA(NULL, "Could not write to the preroll output frame buffer.", "DeckLink start failed", MB_OK | MB_ICONERROR);
return false;
}
void* pFrame;
outputVideoFrameBuffer->GetBytes((void**)&pFrame);
memset(pFrame, 0, outputVideoFrame->GetRowBytes() * outputHeight);
outputVideoFrameBuffer->EndAccess(bmdBufferAccessWrite);
outputVideoFrameBuffer->Release();
if (output->ScheduleVideoFrame(outputVideoFrame, (totalPlayoutFrames * frameDuration), frameDuration, frameTimescale) != S_OK)
{
MessageBoxA(NULL, "Could not schedule a preroll output frame.", "DeckLink start failed", MB_OK | MB_ICONERROR);
return false;
}
totalPlayoutFrames++;
}
if (input)
{
if (input->StartStreams() != S_OK)
{
MessageBoxA(NULL, "Could not start the DeckLink input stream.", "DeckLink start failed", MB_OK | MB_ICONERROR);
return false;
}
}
if (output->StartScheduledPlayback(0, frameTimescale, 1.0) != S_OK)
{
MessageBoxA(NULL, "Could not start DeckLink scheduled playback.", "DeckLink start failed", MB_OK | MB_ICONERROR);
return false;
}
return true;
}
bool DeckLinkSession::Stop()
{
if (keyer != nullptr)
{
keyer->Disable();
externalKeyingActive = false;
}
if (input)
{
input->StopStreams();
input->DisableVideoInput();
}
if (output)
{
output->StopScheduledPlayback(0, NULL, 0);
output->DisableVideoOutput();
}
return true;
}