From 5f81d4117fe69874a5e5224858175b533bbdee1b Mon Sep 17 00:00:00 2001 From: Paul Hindt Date: Thu, 27 Jan 2022 00:18:07 -0800 Subject: [PATCH] aja: Clear previous crosspoints when signal changes Fix for a bug where stale crosspoint connections could result in video glitches upon next connection. --- plugins/aja/aja-output.cpp | 23 ++++++++++++++++++++--- plugins/aja/aja-output.hpp | 5 +++++ plugins/aja/aja-source.cpp | 19 ++++++++++++++++++- plugins/aja/aja-source.hpp | 5 +++++ 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/plugins/aja/aja-output.cpp b/plugins/aja/aja-output.cpp index aad454eda..08b2bba3f 100644 --- a/plugins/aja/aja-output.cpp +++ b/plugins/aja/aja-output.cpp @@ -106,7 +106,8 @@ AJAOutput::AJAOutput(CNTV2Card *card, const std::string &cardID, mRunThreadLock{}, mVideoQueue{}, mAudioQueue{}, - mOBSOutput{nullptr} + mOBSOutput{nullptr}, + mCrosspoints{} { mVideoQueue = std::make_unique(); mAudioQueue = std::make_unique(); @@ -173,6 +174,20 @@ OutputProps AJAOutput::GetOutputProps() const return mOutputProps; } +void AJAOutput::CacheConnections(const NTV2XptConnections &cnx) +{ + mCrosspoints.clear(); + mCrosspoints = cnx; +} + +void AJAOutput::ClearConnections() +{ + for (auto &&xpt : mCrosspoints) { + mCard->Connect(xpt.first, NTV2_XptBlack); + } + mCrosspoints.clear(); +} + void AJAOutput::GenerateTestPattern(NTV2VideoFormat vf, NTV2PixelFormat pf, NTV2TestPatternSelect pattern) { @@ -1068,6 +1083,7 @@ static bool aja_output_start(void *data) } // Configures crosspoint routing on AJA card + ajaOutput->ClearConnections(); NTV2XptConnections xpt_cnx; if (!aja::Routing::ConfigureOutputRoute(outputProps, NTV2_MODE_DISPLAY, card, xpt_cnx)) { @@ -1075,7 +1091,7 @@ static bool aja_output_start(void *data) "aja_output_start: Error configuring output route!"); return false; } - + ajaOutput->CacheConnections(xpt_cnx); aja::Routing::ConfigureOutputAudio(outputProps, card); const auto &formatDesc = outputProps.FormatDesc(); @@ -1144,14 +1160,15 @@ static void aja_output_stop(void *data, uint64_t ts) aja::IOSelectionToString(outputProps.ioSelect).c_str(), cardID.c_str()); } + ajaOutput->GenerateTestPattern(outputProps.videoFormat, outputProps.pixelFormat, NTV2_TestPatt_Black); obs_output_end_data_capture(ajaOutput->GetOBSOutput()); - auto audioSystem = outputProps.AudioSystem(); card->StopAudioOutput(audioSystem); + ajaOutput->ClearConnections(); blog(LOG_INFO, "AJA Output stopped."); } diff --git a/plugins/aja/aja-output.hpp b/plugins/aja/aja-output.hpp index 4fec33bbd..007299b70 100644 --- a/plugins/aja/aja-output.hpp +++ b/plugins/aja/aja-output.hpp @@ -58,6 +58,9 @@ public: void SetOutputProps(const OutputProps &props); OutputProps GetOutputProps() const; + void CacheConnections(const NTV2XptConnections &cnx); + void ClearConnections(); + void GenerateTestPattern(NTV2VideoFormat vf, NTV2PixelFormat pf, NTV2TestPatternSelect pattern); @@ -147,4 +150,6 @@ private: std::unique_ptr mAudioQueue; obs_output_t *mOBSOutput; + + NTV2XptConnections mCrosspoints; }; diff --git a/plugins/aja/aja-source.cpp b/plugins/aja/aja-source.cpp index ba7f66c7b..2a60f1f66 100644 --- a/plugins/aja/aja-source.cpp +++ b/plugins/aja/aja-source.cpp @@ -27,7 +27,8 @@ AJASource::AJASource(obs_source_t *source) mTestPattern{}, mCaptureThread{nullptr}, mMutex{}, - mSource{source} + mSource{source}, + mCrosspoints{} { } @@ -458,6 +459,20 @@ SourceProps AJASource::GetSourceProps() const return mSourceProps; } +void AJASource::CacheConnections(const NTV2XptConnections &cnx) +{ + mCrosspoints.clear(); + mCrosspoints = cnx; +} + +void AJASource::ClearConnections() +{ + for (auto &&xpt : mCrosspoints) { + mCard->Connect(xpt.first, NTV2_XptBlack); + } + mCrosspoints.clear(); +} + bool AJASource::ReadChannelVPIDs(NTV2Channel channel, VPIDData &vpids) { ULWord vpid_a = 0; @@ -1014,9 +1029,11 @@ static void aja_source_update(void *data, obs_data_t *settings) // Change capture format and restart capture thread if (!initialized || want_props != ajaSource->GetSourceProps()) { + ajaSource->ClearConnections(); NTV2XptConnections xpt_cnx; aja::Routing::ConfigureSourceRoute( want_props, NTV2_MODE_CAPTURE, card, xpt_cnx); + ajaSource->CacheConnections(xpt_cnx); ajaSource->Deactivate(); initialized = true; } diff --git a/plugins/aja/aja-source.hpp b/plugins/aja/aja-source.hpp index a4279cba6..81e3831ab 100644 --- a/plugins/aja/aja-source.hpp +++ b/plugins/aja/aja-source.hpp @@ -48,6 +48,9 @@ public: void SetSourceProps(const SourceProps &props); SourceProps GetSourceProps() const; + void CacheConnections(const NTV2XptConnections &cnx); + void ClearConnections(); + bool ReadChannelVPIDs(NTV2Channel channel, VPIDData &vpids); bool ReadWireFormats(NTV2DeviceID device_id, IOSelection io_select, @@ -79,4 +82,6 @@ private: std::mutex mMutex; obs_source_t *mSource; + + NTV2XptConnections mCrosspoints; };