#pragma once #include "AppState.h" #include "D3DProcessor.h" #include "DeckLinkApi.h" #include #include #include #include class DeckLinkPipeline; class DeckLinkInputCallback final : public IDeckLinkInputCallback { public: explicit DeckLinkInputCallback(DeckLinkPipeline& pipeline); HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID* ppv) override; ULONG STDMETHODCALLTYPE AddRef() override; ULONG STDMETHODCALLTYPE Release() override; HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(BMDVideoInputFormatChangedEvents events, IDeckLinkDisplayMode* mode, BMDDetectedVideoInputFormatFlags flags) override; HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(IDeckLinkVideoInputFrame* videoFrame, IDeckLinkAudioInputPacket* audioPacket) override; private: std::atomic m_refCount = 1; DeckLinkPipeline& m_pipeline; }; class DeckLinkOutputCallback final : public IDeckLinkVideoOutputCallback { public: explicit DeckLinkOutputCallback(DeckLinkPipeline& pipeline); HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID* ppv) override; ULONG STDMETHODCALLTYPE AddRef() override; ULONG STDMETHODCALLTYPE Release() override; HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult result) override; HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped() override; private: std::atomic m_refCount = 1; DeckLinkPipeline& m_pipeline; }; class DeckLinkPipeline { public: DeckLinkPipeline(AppState& appState, D3DProcessor& processor); ~DeckLinkPipeline(); bool initialize(std::string& error); bool start(std::string& error); void stop(); void onFormatChanged(IDeckLinkDisplayMode* mode, BMDDetectedVideoInputFormatFlags flags); void onFrameArrived(IDeckLinkVideoInputFrame* videoFrame); void onOutputFrameCompleted(BMDOutputFrameCompletionResult result); private: friend class DeckLinkInputCallback; friend class DeckLinkOutputCallback; bool selectDevice(std::string& error); bool findStartupMode(Microsoft::WRL::ComPtr& selectedMode, std::string& error); bool configureForMode(IDeckLinkDisplayMode* mode, BMDPixelFormat inputFormat, std::string& error); bool chooseOutputFormat(BMDDisplayMode displayMode, BMDPixelFormat& outputFormat); void updateStatusLocked(); std::string deckLinkName(IDeckLink* deckLink) const; std::string displayModeName(IDeckLinkDisplayMode* mode) const; AppState& m_appState; D3DProcessor& m_processor; mutable std::recursive_mutex m_mutex; Microsoft::WRL::ComPtr m_deckLink; Microsoft::WRL::ComPtr m_input; Microsoft::WRL::ComPtr m_output; Microsoft::WRL::ComPtr m_configuration; Microsoft::WRL::ComPtr m_converter; Microsoft::WRL::ComPtr m_activeMode; Microsoft::WRL::ComPtr m_inputCallback; Microsoft::WRL::ComPtr m_outputCallback; PipelineStatus m_status; BMDPixelFormat m_inputFormat = bmdFormat8BitYUV; BMDPixelFormat m_outputFormat = bmdFormat8BitARGB; BMDTimeValue m_frameDuration = 1001; BMDTimeScale m_frameTimescale = 30000; uint64_t m_totalScheduled = 0; bool m_initialized = false; bool m_streamStarted = false; };