From c1d6bb84b03b05b02b048f717300b7c31b198dfd Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Fri, 24 Feb 2023 11:18:18 +0100 Subject: [PATCH] DeckLink: continue if CoInit fails on diff. mode --- src/audio/playback/decklink.cpp | 10 ++++++---- src/blackmagic_common.cpp | 21 ++++++++++++++++----- src/blackmagic_common.hpp | 9 ++++++--- src/video_capture/decklink.cpp | 18 +++++++++++------- src/video_display/decklink.cpp | 16 +++++++++------- 5 files changed, 48 insertions(+), 26 deletions(-) diff --git a/src/audio/playback/decklink.cpp b/src/audio/playback/decklink.cpp index c2b03f7a1..8a49ed534 100644 --- a/src/audio/playback/decklink.cpp +++ b/src/audio/playback/decklink.cpp @@ -78,6 +78,7 @@ struct state_decklink { int output_audio_channel_count; PlaybackDelegate *delegate; + bool com_initialized; IDeckLink *deckLink; IDeckLinkOutput *deckLinkOutput; IDeckLinkMutableVideoFrame *deckLinkFrame; @@ -143,7 +144,8 @@ static void audio_play_decklink_help(const char *driver_name) UNUSED(driver_name); // Create an IDeckLinkIterator object to enumerate all DeckLink cards in the system - deckLinkIterator = create_decklink_iterator(true); + bool com_initialized = false; + deckLinkIterator = create_decklink_iterator(&com_initialized, true); if (deckLinkIterator == NULL) { return; @@ -174,7 +176,7 @@ static void audio_play_decklink_help(const char *driver_name) } deckLinkIterator->Release(); - decklink_uninitialize(); + decklink_uninitialize(&com_initialized); // If no DeckLink cards were found in the system, inform the user if (numDevices == 0) @@ -244,7 +246,7 @@ static void *audio_play_decklink_init(const char *cfg) "\"-d decklink -r analog\" instead.\n"); // Initialize the DeckLink API - deckLinkIterator = create_decklink_iterator(true); + deckLinkIterator = create_decklink_iterator(&s->com_initialized, true); if (!deckLinkIterator) { goto error; } @@ -452,8 +454,8 @@ static void audio_play_decklink_done(void *state) s->deckLinkFrame->Release(); s->deckLink->Release(); s->deckLinkOutput->Release(); + decklink_uninitialize(&s->com_initialized); free(s); - decklink_uninitialize(); } static const struct audio_playback_info aplay_decklink_info = { diff --git a/src/blackmagic_common.cpp b/src/blackmagic_common.cpp index 0581147db..6c95b7003 100644 --- a/src/blackmagic_common.cpp +++ b/src/blackmagic_common.cpp @@ -142,21 +142,22 @@ std::string get_str_from_bmd_api_str(BMD_STR string) * should be followed by decklink_uninitialize() when done with DeckLink (not when releasing * IDeckLinkIterator!), typically on application shutdown. */ -IDeckLinkIterator *create_decklink_iterator(bool verbose, bool coinit) +IDeckLinkIterator *create_decklink_iterator(bool *com_initialized, bool verbose, bool coinit) { IDeckLinkIterator *deckLinkIterator = nullptr; #ifdef WIN32 if (coinit) { - decklink_initialize(); + decklink_initialize(com_initialized); } HRESULT result = CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void **) &deckLinkIterator); if (FAILED(result)) { - CoUninitialize(); + decklink_uninitialize(com_initialized); deckLinkIterator = nullptr; } #else UNUSED(coinit); + *com_initialized = false; deckLinkIterator = CreateDeckLinkIteratorInstance(); #endif @@ -171,12 +172,18 @@ IDeckLinkIterator *create_decklink_iterator(bool verbose, bool coinit) } /// called automatically by create_decklink_iterator() if second parameter is true (default) -bool decklink_initialize() +bool decklink_initialize(bool *com_initialized) { + *com_initialized = false; #ifdef WIN32 // Initialize COM on this thread HRESULT result = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (SUCCEEDED(result)) { + *com_initialized = true; + return true; + } + if (result == RPC_E_CHANGED_MODE) { + LOG(LOG_LEVEL_WARNING) << "[BMD] COM already intiialized with a different mode!\n"; return true; } log_msg(LOG_LEVEL_ERROR, "Initialize of COM failed - result = " @@ -187,8 +194,12 @@ bool decklink_initialize() #endif } -void decklink_uninitialize() +void decklink_uninitialize(bool *com_initialized) { + if (!*com_initialized) { + return; + } + *com_initialized = false; #ifdef WIN32 CoUninitialize(); #endif diff --git a/src/blackmagic_common.hpp b/src/blackmagic_common.hpp index 8402addd8..a946b02db 100644 --- a/src/blackmagic_common.hpp +++ b/src/blackmagic_common.hpp @@ -98,9 +98,12 @@ void release_bmd_api_str(BMD_STR string); std::string get_str_from_bmd_api_str(BMD_STR string); #endif -IDeckLinkIterator *create_decklink_iterator(bool verbose = true, bool coinit = true); -bool decklink_initialize(); -void decklink_uninitialize(); +///< @param[out] com_initialized - pass a pointer to bool +IDeckLinkIterator *create_decklink_iterator(bool *com_initialized, bool verbose = true, bool coinit = true); +///< param pass a pointer to a bool that will be passed to decklink_uninintialize() +bool decklink_initialize(bool *com_initialized); +///< @param com_initialized - pointer passed to decklink_initialize (or create_decklink_iterator) +void decklink_uninitialize(bool *com_initialized); bool blackmagic_api_version_check(); void print_decklink_version(void); diff --git a/src/video_capture/decklink.cpp b/src/video_capture/decklink.cpp index 3e8fe06ea..fbddc5de3 100644 --- a/src/video_capture/decklink.cpp +++ b/src/video_capture/decklink.cpp @@ -146,6 +146,7 @@ struct device_state { }; struct vidcap_decklink_state { + bool com_initialized = true; vector state{vector (1)}; int devices_cnt = 1; string mode; @@ -181,12 +182,12 @@ struct vidcap_decklink_state { void set_codec(codec_t c); vidcap_decklink_state() { - if (!decklink_initialize()) { + if (!decklink_initialize(&com_initialized)) { throw 1; } } ~vidcap_decklink_state() { - decklink_uninitialize(); + decklink_uninitialize(&com_initialized); } }; @@ -563,7 +564,8 @@ decklink_help(bool full) cout << "\n"; // Create an IDeckLinkIterator object to enumerate all DeckLink cards in the system - IDeckLinkIterator *deckLinkIterator = create_decklink_iterator(); + bool com_initialized = false; + IDeckLinkIterator *deckLinkIterator = create_decklink_iterator(&com_initialized); if (deckLinkIterator == NULL) { return 0; } @@ -596,7 +598,7 @@ decklink_help(bool full) deckLinkIterator->Release(); - decklink_uninitialize(); + decklink_uninitialize(&com_initialized); // If no DeckLink cards were found in the system, inform the user if (numDevices == 0) @@ -792,7 +794,8 @@ static void vidcap_decklink_probe(device_info **available_cards, int *card_count int numDevices = 0; // Create an IDeckLinkIterator object to enumerate all DeckLink cards in the system - deckLinkIterator = create_decklink_iterator(false); + bool com_initialized = false; + deckLinkIterator = create_decklink_iterator(&com_initialized, false); if (deckLinkIterator == nullptr) { return; } @@ -889,7 +892,7 @@ static void vidcap_decklink_probe(device_info **available_cards, int *card_count } deckLinkIterator->Release(); - decklink_uninitialize(); + decklink_uninitialize(&com_initialized); *available_cards = cards; } @@ -1058,8 +1061,9 @@ bool device_state::init(struct vidcap_decklink_state *s, struct tile *t, BMDAudi tile = t; int dnum = 0; + bool com_initialized = false; // Create an IDeckLinkIterator object to enumerate all DeckLink cards in the system - IDeckLinkIterator *deckLinkIterator = create_decklink_iterator(true, false); + IDeckLinkIterator *deckLinkIterator = create_decklink_iterator(&com_initialized, true, false); if (deckLinkIterator == NULL) { return false; } diff --git a/src/video_display/decklink.cpp b/src/video_display/decklink.cpp index 4d492c425..cc4a82052 100644 --- a/src/video_display/decklink.cpp +++ b/src/video_display/decklink.cpp @@ -321,6 +321,7 @@ struct device_state { struct state_decklink { uint32_t magic = DECKLINK_MAGIC; chrono::high_resolution_clock::time_point t0 = chrono::high_resolution_clock::now(); + bool com_initialized = false; vector state; @@ -428,7 +429,8 @@ static void show_help(bool full) col() << "\nDevices:\n"; // Create an IDeckLinkIterator object to enumerate all DeckLink cards in the system - deckLinkIterator = create_decklink_iterator(true); + bool com_initialized = false; + deckLinkIterator = create_decklink_iterator(&com_initialized, true); if (deckLinkIterator == NULL) { return; } @@ -460,7 +462,7 @@ static void show_help(bool full) deckLinkIterator->Release(); - decklink_uninitialize(); + decklink_uninitialize(&com_initialized); // If no DeckLink cards were found in the system, inform the user if (numDevices == 0) @@ -897,7 +899,8 @@ static void display_decklink_probe(struct device_info **available_cards, int *co *count = 0; *available_cards = nullptr; - deckLinkIterator = create_decklink_iterator(false); + bool com_initialized = false; + deckLinkIterator = create_decklink_iterator(&com_initialized, false); if (deckLinkIterator == NULL) { return; } @@ -926,7 +929,7 @@ static void display_decklink_probe(struct device_info **available_cards, int *co } deckLinkIterator->Release(); - decklink_uninitialize(); + decklink_uninitialize(&com_initialized); } static auto parse_devices(const char *devices_str, vector *cardId) { @@ -1129,7 +1132,7 @@ static void *display_decklink_init(struct module *parent, const char *fmt, unsig } // Initialize the DeckLink API - deckLinkIterator = create_decklink_iterator(true); + deckLinkIterator = create_decklink_iterator(&s->com_initialized, true); if (!deckLinkIterator) { delete s; @@ -1380,9 +1383,8 @@ static void display_decklink_done(void *state) delete s->timecode; + decklink_uninitialize(&s->com_initialized); delete s; - - decklink_uninitialize(); } /**