com updates
This commit is contained in:
@@ -32,7 +32,7 @@ jobs:
|
|||||||
|
|
||||||
ui-ubuntu:
|
ui-ubuntu:
|
||||||
name: React UI Build
|
name: React UI Build
|
||||||
runs-on: nubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
23
README.md
23
README.md
@@ -125,7 +125,7 @@ Current native test coverage includes:
|
|||||||
|
|
||||||
- JSON parsing and serialization.
|
- JSON parsing and serialization.
|
||||||
- Parameter normalization and preset filename safety.
|
- Parameter normalization and preset filename safety.
|
||||||
- Shader manifest parsing and package registry scanning.
|
- Shader manifest parsing, temporal manifest validation, and package registry scanning.
|
||||||
|
|
||||||
## Runtime Configuration
|
## Runtime Configuration
|
||||||
|
|
||||||
@@ -230,14 +230,15 @@ The Gitea workflow expects two act runners:
|
|||||||
If your Windows runner stores the Blackmagic SDK outside the repo, configure `GPUDIRECT_DIR` in the runner environment or adjust the workflow configure command to pass `-DGPUDIRECT_DIR=...`.
|
If your Windows runner stores the Blackmagic SDK outside the repo, configure `GPUDIRECT_DIR` in the runner environment or adjust the workflow configure command to pass `-DGPUDIRECT_DIR=...`.
|
||||||
|
|
||||||
|
|
||||||
## Still todo
|
## Still Todo
|
||||||
Audio
|
|
||||||
improve text rendering
|
- Audio.
|
||||||
genlock
|
- Improve text rendering.
|
||||||
find a better UI libary
|
- Genlock.
|
||||||
Logs
|
- Find a better UI library.
|
||||||
refactor, cleanup of source files
|
- Logs.
|
||||||
display URL (Maybe clicakable) for control in the windows app (Not on the output)
|
- Continue source cleanup/refactoring.
|
||||||
Sound shader as seperate .slang in shader package?
|
- Display the control URL in the Windows app, ideally clickable, without rendering it on the video output.
|
||||||
runtime date time UTC and offset from PCs internal clock
|
- Support a separate sound shader `.slang` file in shader packages.
|
||||||
|
- Add runtime date/time uniforms using UTC and the PC's local offset.
|
||||||

|

|
||||||
@@ -13,7 +13,7 @@ namespace
|
|||||||
{
|
{
|
||||||
std::string BstrToUtf8(BSTR value)
|
std::string BstrToUtf8(BSTR value)
|
||||||
{
|
{
|
||||||
if (value == NULL)
|
if (value == nullptr)
|
||||||
return std::string();
|
return std::string();
|
||||||
|
|
||||||
const int requiredBytes = WideCharToMultiByte(CP_UTF8, 0, value, -1, NULL, 0, NULL, NULL);
|
const int requiredBytes = WideCharToMultiByte(CP_UTF8, 0, value, -1, NULL, 0, NULL, NULL);
|
||||||
@@ -36,84 +36,56 @@ DeckLinkSession::~DeckLinkSession()
|
|||||||
void DeckLinkSession::ReleaseResources()
|
void DeckLinkSession::ReleaseResources()
|
||||||
{
|
{
|
||||||
if (input != nullptr)
|
if (input != nullptr)
|
||||||
{
|
|
||||||
input->SetCallback(nullptr);
|
input->SetCallback(nullptr);
|
||||||
if (captureDelegate != nullptr)
|
captureDelegate.Release();
|
||||||
{
|
input.Release();
|
||||||
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 (output != nullptr)
|
||||||
{
|
|
||||||
if (keyer != nullptr)
|
|
||||||
{
|
|
||||||
keyer->Disable();
|
|
||||||
keyer->Release();
|
|
||||||
keyer = nullptr;
|
|
||||||
externalKeyingActive = false;
|
|
||||||
}
|
|
||||||
output->SetScheduledFrameCompletionCallback(nullptr);
|
output->SetScheduledFrameCompletionCallback(nullptr);
|
||||||
if (playoutDelegate != nullptr)
|
|
||||||
{
|
|
||||||
playoutDelegate->Release();
|
|
||||||
playoutDelegate = nullptr;
|
|
||||||
}
|
|
||||||
output->Release();
|
|
||||||
output = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (playoutAllocator != nullptr)
|
if (keyer != nullptr)
|
||||||
{
|
{
|
||||||
playoutAllocator->Release();
|
keyer->Disable();
|
||||||
playoutAllocator = nullptr;
|
externalKeyingActive = false;
|
||||||
}
|
}
|
||||||
|
keyer.Release();
|
||||||
|
|
||||||
|
playoutDelegate.Release();
|
||||||
|
outputVideoFrameQueue.clear();
|
||||||
|
output.Release();
|
||||||
|
|
||||||
|
playoutAllocator.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeckLinkSession::DiscoverDevicesAndModes(BMDDisplayMode inputDisplayMode, BMDDisplayMode outputDisplayMode, const std::string& requestedInputDisplayModeName, const std::string& requestedOutputDisplayModeName, std::string& error)
|
bool DeckLinkSession::DiscoverDevicesAndModes(BMDDisplayMode inputDisplayMode, BMDDisplayMode outputDisplayMode, const std::string& requestedInputDisplayModeName, const std::string& requestedOutputDisplayModeName, std::string& error)
|
||||||
{
|
{
|
||||||
bool success = false;
|
CComPtr<IDeckLinkIterator> deckLinkIterator;
|
||||||
IDeckLinkIterator* deckLinkIterator = NULL;
|
CComPtr<IDeckLinkDisplayMode> inputMode;
|
||||||
IDeckLink* deckLink = NULL;
|
CComPtr<IDeckLinkDisplayMode> outputMode;
|
||||||
IDeckLinkProfileAttributes* deckLinkAttributes = NULL;
|
|
||||||
IDeckLinkDisplayModeIterator* inputDisplayModeIterator = NULL;
|
|
||||||
IDeckLinkDisplayModeIterator* outputDisplayModeIterator = NULL;
|
|
||||||
IDeckLinkDisplayMode* inputMode = NULL;
|
|
||||||
IDeckLinkDisplayMode* outputMode = NULL;
|
|
||||||
|
|
||||||
inputDisplayModeName = requestedInputDisplayModeName;
|
inputDisplayModeName = requestedInputDisplayModeName;
|
||||||
outputDisplayModeName = requestedOutputDisplayModeName;
|
outputDisplayModeName = requestedOutputDisplayModeName;
|
||||||
|
|
||||||
HRESULT result = CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void**)&deckLinkIterator);
|
HRESULT result = CoCreateInstance(CLSID_CDeckLinkIterator, nullptr, CLSCTX_ALL, IID_IDeckLinkIterator, reinterpret_cast<void**>(&deckLinkIterator));
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
error = "Please install the Blackmagic DeckLink drivers to use the features of this application.";
|
error = "Please install the Blackmagic DeckLink drivers to use the features of this application.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CComPtr<IDeckLink> deckLink;
|
||||||
while (deckLinkIterator->Next(&deckLink) == S_OK)
|
while (deckLinkIterator->Next(&deckLink) == S_OK)
|
||||||
{
|
{
|
||||||
int64_t duplexMode;
|
int64_t duplexMode;
|
||||||
bool deviceSupportsInternalKeying = false;
|
bool deviceSupportsInternalKeying = false;
|
||||||
bool deviceSupportsExternalKeying = false;
|
bool deviceSupportsExternalKeying = false;
|
||||||
std::string modelName;
|
std::string modelName;
|
||||||
|
CComPtr<IDeckLinkProfileAttributes> deckLinkAttributes;
|
||||||
|
|
||||||
if (deckLink->QueryInterface(IID_IDeckLinkProfileAttributes, (void**)&deckLinkAttributes) != S_OK)
|
if (deckLink->QueryInterface(IID_IDeckLinkProfileAttributes, (void**)&deckLinkAttributes) != S_OK)
|
||||||
{
|
{
|
||||||
printf("Could not obtain the IDeckLinkProfileAttributes interface\n");
|
printf("Could not obtain the IDeckLinkProfileAttributes interface\n");
|
||||||
deckLink->Release();
|
deckLink.Release();
|
||||||
deckLink = NULL;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,20 +96,13 @@ bool DeckLinkSession::DiscoverDevicesAndModes(BMDDisplayMode inputDisplayMode, B
|
|||||||
attributeFlag = FALSE;
|
attributeFlag = FALSE;
|
||||||
if (deckLinkAttributes->GetFlag(BMDDeckLinkSupportsExternalKeying, &attributeFlag) == S_OK)
|
if (deckLinkAttributes->GetFlag(BMDDeckLinkSupportsExternalKeying, &attributeFlag) == S_OK)
|
||||||
deviceSupportsExternalKeying = (attributeFlag != FALSE);
|
deviceSupportsExternalKeying = (attributeFlag != FALSE);
|
||||||
BSTR modelNameBstr = NULL;
|
CComBSTR modelNameBstr;
|
||||||
if (deckLinkAttributes->GetString(BMDDeckLinkModelName, &modelNameBstr) == S_OK)
|
if (deckLinkAttributes->GetString(BMDDeckLinkModelName, &modelNameBstr) == S_OK)
|
||||||
{
|
|
||||||
modelName = BstrToUtf8(modelNameBstr);
|
modelName = BstrToUtf8(modelNameBstr);
|
||||||
if (modelNameBstr != NULL)
|
|
||||||
SysFreeString(modelNameBstr);
|
|
||||||
}
|
|
||||||
deckLinkAttributes->Release();
|
|
||||||
deckLinkAttributes = NULL;
|
|
||||||
|
|
||||||
if (result != S_OK || duplexMode == bmdDuplexInactive)
|
if (result != S_OK || duplexMode == bmdDuplexInactive)
|
||||||
{
|
{
|
||||||
deckLink->Release();
|
deckLink.Release();
|
||||||
deckLink = NULL;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +113,7 @@ bool DeckLinkSession::DiscoverDevicesAndModes(BMDDisplayMode inputDisplayMode, B
|
|||||||
if (!output && (!inputUsed || (duplexMode == bmdDuplexFull)))
|
if (!output && (!inputUsed || (duplexMode == bmdDuplexFull)))
|
||||||
{
|
{
|
||||||
if (deckLink->QueryInterface(IID_IDeckLinkOutput, (void**)&output) != S_OK)
|
if (deckLink->QueryInterface(IID_IDeckLinkOutput, (void**)&output) != S_OK)
|
||||||
output = NULL;
|
output.Release();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outputModelName = modelName;
|
outputModelName = modelName;
|
||||||
@@ -157,8 +122,7 @@ bool DeckLinkSession::DiscoverDevicesAndModes(BMDDisplayMode inputDisplayMode, B
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deckLink->Release();
|
deckLink.Release();
|
||||||
deckLink = NULL;
|
|
||||||
|
|
||||||
if (output && input)
|
if (output && input)
|
||||||
break;
|
break;
|
||||||
@@ -167,39 +131,40 @@ bool DeckLinkSession::DiscoverDevicesAndModes(BMDDisplayMode inputDisplayMode, B
|
|||||||
if (!output)
|
if (!output)
|
||||||
{
|
{
|
||||||
error = "Expected an Output DeckLink device";
|
error = "Expected an Output DeckLink device";
|
||||||
goto cleanup;
|
ReleaseResources();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CComPtr<IDeckLinkDisplayModeIterator> inputDisplayModeIterator;
|
||||||
if (input && input->GetDisplayModeIterator(&inputDisplayModeIterator) != S_OK)
|
if (input && input->GetDisplayModeIterator(&inputDisplayModeIterator) != S_OK)
|
||||||
{
|
{
|
||||||
error = "Cannot get input Display Mode Iterator.";
|
error = "Cannot get input Display Mode Iterator.";
|
||||||
goto cleanup;
|
ReleaseResources();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input && !FindDeckLinkDisplayMode(inputDisplayModeIterator, inputDisplayMode, &inputMode))
|
if (input && !FindDeckLinkDisplayMode(inputDisplayModeIterator, inputDisplayMode, &inputMode))
|
||||||
{
|
{
|
||||||
error = "Cannot get specified input BMDDisplayMode for configured mode: " + requestedInputDisplayModeName;
|
error = "Cannot get specified input BMDDisplayMode for configured mode: " + requestedInputDisplayModeName;
|
||||||
goto cleanup;
|
ReleaseResources();
|
||||||
}
|
return false;
|
||||||
if (inputDisplayModeIterator)
|
|
||||||
{
|
|
||||||
inputDisplayModeIterator->Release();
|
|
||||||
inputDisplayModeIterator = NULL;
|
|
||||||
}
|
}
|
||||||
|
inputDisplayModeIterator.Release();
|
||||||
|
|
||||||
|
CComPtr<IDeckLinkDisplayModeIterator> outputDisplayModeIterator;
|
||||||
if (output->GetDisplayModeIterator(&outputDisplayModeIterator) != S_OK)
|
if (output->GetDisplayModeIterator(&outputDisplayModeIterator) != S_OK)
|
||||||
{
|
{
|
||||||
error = "Cannot get output Display Mode Iterator.";
|
error = "Cannot get output Display Mode Iterator.";
|
||||||
goto cleanup;
|
ReleaseResources();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FindDeckLinkDisplayMode(outputDisplayModeIterator, outputDisplayMode, &outputMode))
|
if (!FindDeckLinkDisplayMode(outputDisplayModeIterator, outputDisplayMode, &outputMode))
|
||||||
{
|
{
|
||||||
error = "Cannot get specified output BMDDisplayMode for configured mode: " + requestedOutputDisplayModeName;
|
error = "Cannot get specified output BMDDisplayMode for configured mode: " + requestedOutputDisplayModeName;
|
||||||
goto cleanup;
|
ReleaseResources();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
outputDisplayModeIterator->Release();
|
|
||||||
outputDisplayModeIterator = NULL;
|
|
||||||
|
|
||||||
outputFrameWidth = outputMode->GetWidth();
|
outputFrameWidth = outputMode->GetWidth();
|
||||||
outputFrameHeight = outputMode->GetHeight();
|
outputFrameHeight = outputMode->GetHeight();
|
||||||
@@ -209,26 +174,7 @@ bool DeckLinkSession::DiscoverDevicesAndModes(BMDDisplayMode inputDisplayMode, B
|
|||||||
inputDisplayModeName = "No input - black frame";
|
inputDisplayModeName = "No input - black frame";
|
||||||
outputMode->GetFrameRate(&frameDuration, &frameTimescale);
|
outputMode->GetFrameRate(&frameDuration, &frameTimescale);
|
||||||
|
|
||||||
success = true;
|
return true;
|
||||||
|
|
||||||
cleanup:
|
|
||||||
if (!success)
|
|
||||||
ReleaseResources();
|
|
||||||
if (deckLink != NULL)
|
|
||||||
deckLink->Release();
|
|
||||||
if (deckLinkAttributes != NULL)
|
|
||||||
deckLinkAttributes->Release();
|
|
||||||
if (inputMode != NULL)
|
|
||||||
inputMode->Release();
|
|
||||||
if (outputMode != NULL)
|
|
||||||
outputMode->Release();
|
|
||||||
if (inputDisplayModeIterator != NULL)
|
|
||||||
inputDisplayModeIterator->Release();
|
|
||||||
if (outputDisplayModeIterator != NULL)
|
|
||||||
outputDisplayModeIterator->Release();
|
|
||||||
if (deckLinkIterator != NULL)
|
|
||||||
deckLinkIterator->Release();
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeckLinkSession::ConfigureInput(OpenGLComposite* owner, HDC hdc, HGLRC hglrc, BMDDisplayMode inputDisplayMode, std::string& error)
|
bool DeckLinkSession::ConfigureInput(OpenGLComposite* owner, HDC hdc, HGLRC hglrc, BMDDisplayMode inputDisplayMode, std::string& error)
|
||||||
@@ -245,14 +191,18 @@ bool DeckLinkSession::ConfigureInput(OpenGLComposite* owner, HDC hdc, HGLRC hglr
|
|||||||
if (input->EnableVideoInputWithAllocatorProvider(inputDisplayMode, bmdFormat8BitYUV, bmdVideoInputFlagDefault, captureAllocator) != S_OK)
|
if (input->EnableVideoInputWithAllocatorProvider(inputDisplayMode, bmdFormat8BitYUV, bmdVideoInputFlagDefault, captureAllocator) != S_OK)
|
||||||
{
|
{
|
||||||
OutputDebugStringA("DeckLink input could not be enabled; continuing in output-only black-frame mode.\n");
|
OutputDebugStringA("DeckLink input could not be enabled; continuing in output-only black-frame mode.\n");
|
||||||
input->Release();
|
input.Release();
|
||||||
input = NULL;
|
|
||||||
hasNoInputSource = true;
|
hasNoInputSource = true;
|
||||||
inputDisplayModeName = "No input - black frame";
|
inputDisplayModeName = "No input - black frame";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
captureDelegate = new CaptureDelegate(owner);
|
captureDelegate.Attach(new (std::nothrow) CaptureDelegate(owner));
|
||||||
|
if (captureDelegate == nullptr)
|
||||||
|
{
|
||||||
|
error = "DeckLink input setup failed while creating the capture callback.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (input->SetCallback(captureDelegate) != S_OK)
|
if (input->SetCallback(captureDelegate) != S_OK)
|
||||||
{
|
{
|
||||||
error = "DeckLink input setup failed while installing the capture callback.";
|
error = "DeckLink input setup failed while installing the capture callback.";
|
||||||
@@ -271,7 +221,12 @@ bool DeckLinkSession::ConfigureOutput(OpenGLComposite* owner, HDC hdc, HGLRC hgl
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
playoutAllocator = new PinnedMemoryAllocator(hdc, hglrc, VideoFrameTransfer::GPUtoCPU, 1, outputFrameRowBytes * outputFrameHeight);
|
playoutAllocator.Attach(new (std::nothrow) PinnedMemoryAllocator(hdc, hglrc, VideoFrameTransfer::GPUtoCPU, 1, outputFrameRowBytes * outputFrameHeight));
|
||||||
|
if (playoutAllocator == nullptr)
|
||||||
|
{
|
||||||
|
error = "DeckLink output setup failed while creating the playout allocator.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (output->EnableVideoOutput(outputDisplayMode, bmdVideoOutputFlagDefault) != S_OK)
|
if (output->EnableVideoOutput(outputDisplayMode, bmdVideoOutputFlagDefault) != S_OK)
|
||||||
{
|
{
|
||||||
@@ -309,8 +264,8 @@ bool DeckLinkSession::ConfigureOutput(OpenGLComposite* owner, HDC hdc, HGLRC hgl
|
|||||||
|
|
||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
IDeckLinkMutableVideoFrame* outputFrame = NULL;
|
CComPtr<IDeckLinkMutableVideoFrame> outputFrame;
|
||||||
IDeckLinkVideoBuffer* outputFrameBuffer = NULL;
|
CComPtr<IDeckLinkVideoBuffer> outputFrameBuffer;
|
||||||
|
|
||||||
if (playoutAllocator->AllocateVideoBuffer(&outputFrameBuffer) != S_OK)
|
if (playoutAllocator->AllocateVideoBuffer(&outputFrameBuffer) != S_OK)
|
||||||
{
|
{
|
||||||
@@ -321,15 +276,14 @@ bool DeckLinkSession::ConfigureOutput(OpenGLComposite* owner, HDC hdc, HGLRC hgl
|
|||||||
if (output->CreateVideoFrameWithBuffer(outputFrameWidth, outputFrameHeight, outputFrameRowBytes, bmdFormat8BitBGRA, bmdFrameFlagFlipVertical, outputFrameBuffer, &outputFrame) != S_OK)
|
if (output->CreateVideoFrameWithBuffer(outputFrameWidth, outputFrameHeight, outputFrameRowBytes, bmdFormat8BitBGRA, bmdFrameFlagFlipVertical, outputFrameBuffer, &outputFrame) != S_OK)
|
||||||
{
|
{
|
||||||
error = "DeckLink output setup failed while creating an output video frame.";
|
error = "DeckLink output setup failed while creating an output video frame.";
|
||||||
outputFrameBuffer->Release();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
outputVideoFrameQueue.push_back(outputFrame);
|
outputVideoFrameQueue.push_back(outputFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
playoutDelegate = new PlayoutDelegate(owner);
|
playoutDelegate.Attach(new (std::nothrow) PlayoutDelegate(owner));
|
||||||
if (playoutDelegate == NULL)
|
if (playoutDelegate == nullptr)
|
||||||
{
|
{
|
||||||
error = "DeckLink output setup failed while creating the playout callback.";
|
error = "DeckLink output setup failed while creating the playout callback.";
|
||||||
return false;
|
return false;
|
||||||
@@ -353,10 +307,10 @@ double DeckLinkSession::FrameBudgetMilliseconds() const
|
|||||||
|
|
||||||
IDeckLinkMutableVideoFrame* DeckLinkSession::RotateOutputFrame()
|
IDeckLinkMutableVideoFrame* DeckLinkSession::RotateOutputFrame()
|
||||||
{
|
{
|
||||||
IDeckLinkMutableVideoFrame* outputVideoFrame = outputVideoFrameQueue.front();
|
CComPtr<IDeckLinkMutableVideoFrame> outputVideoFrame = outputVideoFrameQueue.front();
|
||||||
outputVideoFrameQueue.push_back(outputVideoFrame);
|
outputVideoFrameQueue.push_back(outputVideoFrame);
|
||||||
outputVideoFrameQueue.pop_front();
|
outputVideoFrameQueue.pop_front();
|
||||||
return outputVideoFrame;
|
return outputVideoFrame.p;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeckLinkSession::TransferPlayoutFrame(void* address, GLuint outputTexture)
|
bool DeckLinkSession::TransferPlayoutFrame(void* address, GLuint outputTexture)
|
||||||
@@ -401,11 +355,11 @@ bool DeckLinkSession::Start()
|
|||||||
|
|
||||||
for (unsigned i = 0; i < kPrerollFrameCount; i++)
|
for (unsigned i = 0; i < kPrerollFrameCount; i++)
|
||||||
{
|
{
|
||||||
IDeckLinkMutableVideoFrame* outputVideoFrame = outputVideoFrameQueue.front();
|
CComPtr<IDeckLinkMutableVideoFrame> outputVideoFrame = outputVideoFrameQueue.front();
|
||||||
outputVideoFrameQueue.push_back(outputVideoFrame);
|
outputVideoFrameQueue.push_back(outputVideoFrame);
|
||||||
outputVideoFrameQueue.pop_front();
|
outputVideoFrameQueue.pop_front();
|
||||||
|
|
||||||
IDeckLinkVideoBuffer* outputVideoFrameBuffer;
|
CComPtr<IDeckLinkVideoBuffer> outputVideoFrameBuffer;
|
||||||
if (outputVideoFrame->QueryInterface(IID_IDeckLinkVideoBuffer, (void**)&outputVideoFrameBuffer) != S_OK)
|
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);
|
MessageBoxA(NULL, "Could not query the preroll output frame buffer.", "DeckLink start failed", MB_OK | MB_ICONERROR);
|
||||||
@@ -414,7 +368,6 @@ bool DeckLinkSession::Start()
|
|||||||
|
|
||||||
if (outputVideoFrameBuffer->StartAccess(bmdBufferAccessWrite) != S_OK)
|
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);
|
MessageBoxA(NULL, "Could not write to the preroll output frame buffer.", "DeckLink start failed", MB_OK | MB_ICONERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -424,7 +377,6 @@ bool DeckLinkSession::Start()
|
|||||||
memset(pFrame, 0, outputVideoFrame->GetRowBytes() * outputFrameHeight);
|
memset(pFrame, 0, outputVideoFrame->GetRowBytes() * outputFrameHeight);
|
||||||
|
|
||||||
outputVideoFrameBuffer->EndAccess(bmdBufferAccessWrite);
|
outputVideoFrameBuffer->EndAccess(bmdBufferAccessWrite);
|
||||||
outputVideoFrameBuffer->Release();
|
|
||||||
|
|
||||||
if (output->ScheduleVideoFrame(outputVideoFrame, (totalPlayoutFrames * frameDuration), frameDuration, frameTimescale) != S_OK)
|
if (output->ScheduleVideoFrame(outputVideoFrame, (totalPlayoutFrames * frameDuration), frameDuration, frameTimescale) != S_OK)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "DeckLinkAPI_h.h"
|
#include "DeckLinkAPI_h.h"
|
||||||
#include "DeckLinkFrameTransfer.h"
|
#include "DeckLinkFrameTransfer.h"
|
||||||
|
|
||||||
|
#include <atlbase.h>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -45,13 +46,13 @@ public:
|
|||||||
bool ScheduleOutputFrame(IDeckLinkMutableVideoFrame* outputVideoFrame);
|
bool ScheduleOutputFrame(IDeckLinkMutableVideoFrame* outputVideoFrame);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CaptureDelegate* captureDelegate = nullptr;
|
CComPtr<CaptureDelegate> captureDelegate;
|
||||||
PlayoutDelegate* playoutDelegate = nullptr;
|
CComPtr<PlayoutDelegate> playoutDelegate;
|
||||||
IDeckLinkInput* input = nullptr;
|
CComPtr<IDeckLinkInput> input;
|
||||||
IDeckLinkOutput* output = nullptr;
|
CComPtr<IDeckLinkOutput> output;
|
||||||
IDeckLinkKeyer* keyer = nullptr;
|
CComPtr<IDeckLinkKeyer> keyer;
|
||||||
std::deque<IDeckLinkMutableVideoFrame*> outputVideoFrameQueue;
|
std::deque<CComPtr<IDeckLinkMutableVideoFrame>> outputVideoFrameQueue;
|
||||||
PinnedMemoryAllocator* playoutAllocator = nullptr;
|
CComPtr<PinnedMemoryAllocator> playoutAllocator;
|
||||||
BMDTimeValue frameDuration = 0;
|
BMDTimeValue frameDuration = 0;
|
||||||
BMDTimeScale frameTimescale = 0;
|
BMDTimeScale frameTimescale = 0;
|
||||||
unsigned totalPlayoutFrames = 0;
|
unsigned totalPlayoutFrames = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user