#include "DeckLinkSession.h" #include "GlRenderConstants.h" #include 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; }