diff --git a/src/blackmagic_common.cpp b/src/blackmagic_common.cpp index bd64f4ed5..ab73d598d 100644 --- a/src/blackmagic_common.cpp +++ b/src/blackmagic_common.cpp @@ -1097,12 +1097,12 @@ print_bmd_attribute(IDeckLinkProfileAttributes *deckLinkAttributes, * take care about the returned object lifetime (particularly not to * be destroyed after decklink_uninitialize()). */ -std::map> +std::vector bmd_get_sorted_devices(IDeckLinkIterator *deckLinkIterator) { IDeckLink *deckLink = nullptr; - std::map> out; - unsigned tid_substitute = UINT_MAX; + std::vector out; + int idx = 0; while (deckLinkIterator->Next(&deckLink) == S_OK) { IDeckLinkProfileAttributes *deckLinkAttributes = nullptr; HRESULT result = E_FAIL; @@ -1114,15 +1114,26 @@ bmd_get_sorted_devices(IDeckLinkIterator *deckLinkIterator) result = deckLinkAttributes->GetInt(BMDDeckLinkTopologicalID, &id); if (result != S_OK) { - id = tid_substitute--; + id = UINT_MAX - idx; } assert(id >= 0 && id <= UINT_MAX); deckLinkAttributes->Release(); auto release = [](IDeckLink *d) { d->Release(); }; - out.emplace(id, - std::unique_ptr{ - deckLink, release }); + auto &it = out.emplace_back( + std::unique_ptr{ + deckLink, release }, + 0, 0, 0); + std::get(it) = id; + std::get(it) = idx++; + } + std::sort(out.begin(), out.end(), [](bmd_dev &a, bmd_dev &b) { + return std::get(a) < std::get(b); + }); + // assign new indices + char new_idx = 'a'; + for (auto &d : out) { + std::get(d) = new_idx++; } return out; } diff --git a/src/blackmagic_common.hpp b/src/blackmagic_common.hpp index f22cdd699..771e8bbc5 100644 --- a/src/blackmagic_common.hpp +++ b/src/blackmagic_common.hpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -175,7 +176,16 @@ bool bmd_parse_audio_levels(const char *opt) noexcept(false); void print_bmd_attribute(IDeckLinkProfileAttributes *deckLinkAttributes, const char *query_prop_fcc); -std::map> +/** + * @details parameters: + * - first - IDeckLinkInstance + * - unsigned - topological ID + * - int - natural idx (the old, order as given by IDeckLinkIterator) + * - char - new index ('a', 'b', 'c'...); sorted by topological ID + */ +using bmd_dev = std::tuple, + unsigned, int, char>; +std::vector bmd_get_sorted_devices(IDeckLinkIterator *deckLinkIterator); #endif // defined BLACKMAGIC_COMMON_HPP diff --git a/src/video_capture/decklink.cpp b/src/video_capture/decklink.cpp index 38bde49da..4b13ea038 100644 --- a/src/video_capture/decklink.cpp +++ b/src/video_capture/decklink.cpp @@ -614,16 +614,16 @@ decklink_help(bool full, const char *query_prop_fcc = nullptr) // Enumerate all cards in this system int numDevices = 0; for (auto &d : bmd_get_sorted_devices(deckLinkIterator)) { - IDeckLink *deckLink = d.second.get(); + IDeckLink *deckLink = get<0>(d).get(); string deviceName = bmd_get_device_name(deckLink); if (deviceName.empty()) { deviceName = "(unable to get name)"; } // *** Print the model name of the DeckLink card - color_printf("\t" TBOLD("%d") ") " TBOLD("%6x") ") " TBOLD( - TGREEN("%s")) "\n", - numDevices, d.first, deviceName.c_str()); + color_printf("\t" TBOLD("%c") ") " TBOLD("%6x") ") " TBOLD( + TGREEN("%s")) "\n", + get(d), get(d), deviceName.c_str()); // Increment the total number of DeckLink cards found numDevices++; @@ -638,8 +638,6 @@ decklink_help(bool full, const char *query_prop_fcc = nullptr) "fullhelp") "\" to see full list of device modes " "and available connections)\n\n"; } - - deckLinkIterator->Release(); decklink_uninitialize(&com_initialized); @@ -653,9 +651,9 @@ decklink_help(bool full, const char *query_prop_fcc = nullptr) col() << "\t" << SBOLD(uv_argv[0] << " -t decklink") << " # captures autodetected video from first DeckLink (index 0) " "in system\n"; - col() - << "\t" << SBOLD(uv_argv[0] << " -t decklink:d=1:m=Hp30:c=v210") - << " # specify mode for device which doesn't have autodetection\n"; + col() << "\t" << SBOLD(uv_argv[0] << " -t decklink:d=b:m=Hp30:c=v210") + << " # specify mode for 2nd device which doesn't have " + "autodetection\n"; col() << "\t" << SBOLD(uv_argv[0] << " -t decklink:d=\"DeckLink 8K Pro (1)\":profile=1dfd") @@ -832,7 +830,6 @@ static void vidcap_decklink_probe(device_info **available_cards, int *card_count *deleter = free; IDeckLinkIterator* deckLinkIterator; - int numDevices = 0; // Create an IDeckLinkIterator object to enumerate all DeckLink cards in the system bool com_initialized = false; @@ -843,7 +840,7 @@ static void vidcap_decklink_probe(device_info **available_cards, int *card_count // Enumerate all cards in this system for (auto &d : bmd_get_sorted_devices(deckLinkIterator)) { - IDeckLink *deckLink = d.second.get(); + IDeckLink *deckLink = get<0>(d).get(); HRESULT result; IDeckLinkProfileAttributes *deckLinkAttributes; @@ -867,7 +864,7 @@ static void vidcap_decklink_probe(device_info **available_cards, int *card_count realloc(cards, *card_count * sizeof(struct device_info)); memset(&cards[*card_count - 1], 0, sizeof(struct device_info)); snprintf(cards[*card_count - 1].dev, sizeof cards[*card_count - 1].dev, - ":device=%d", numDevices); + ":device=%u", get(d)); snprintf(cards[*card_count - 1].name, sizeof cards[*card_count - 1].name, "%s", deviceName.c_str()); snprintf(cards[*card_count - 1].extra, sizeof cards[*card_count - 1].extra, @@ -930,9 +927,6 @@ static void vidcap_decklink_probe(device_info **available_cards, int *card_count dev_add_option(&cards[*card_count - 1], "3D", "3D", "3D", ":3D", true); dev_add_option(&cards[*card_count - 1], "Profile", "Duplex profile can be one of: 1dhd, 2dhd, 2dfd, 4dhd, keep", "profile", ":profile=", false); - // Increment the total number of DeckLink cards found - numDevices++; - RELEASE_IF_NOT_NULL(deckLinkAttributes); } @@ -1113,7 +1107,6 @@ 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(&com_initialized, true, false); @@ -1121,7 +1114,7 @@ bool device_state::init(struct vidcap_decklink_state *s, struct tile *t, BMDAudi return false; } for (auto &d : bmd_get_sorted_devices(deckLinkIterator)) { - deckLink = d.second.release(); // we must release manually! + deckLink = get<0>(d).release(); // we must release manually! string deviceName = bmd_get_device_name(deckLink); if (!deviceName.empty() && deviceName == device_id.c_str()) { break; @@ -1130,15 +1123,22 @@ bool device_state::init(struct vidcap_decklink_state *s, struct tile *t, BMDAudi // topological ID const unsigned long tid = strtoul(device_id.c_str(), nullptr, 16); - if (d.first == tid) { + if (get(d) == tid) { break; } - // idx - if (isdigit(device_id.c_str()[0]) && atoi(device_id.c_str()) == dnum) { - break; + // natural (old) index + if (isdigit(device_id.c_str()[0])) { + if (atoi(device_id.c_str()) == get(d)) { + break; + } + } + // new (character) index + if (device_id.length() == 1 && device_id[0] >= 'a') { + if (device_id[0] == get(d)) { + break; + } } - dnum++; // Release the IDeckLink instance when we've finished with it to prevent leaks deckLink->Release(); deckLink = NULL; diff --git a/src/video_display/decklink.cpp b/src/video_display/decklink.cpp index 07b8a91f3..3de92e25e 100644 --- a/src/video_display/decklink.cpp +++ b/src/video_display/decklink.cpp @@ -130,6 +130,7 @@ using std::atomic_bool; using std::cout; using std::copy; using std::exception; +using std::get; using std::invalid_argument; using std::lock_guard; using std::map; @@ -637,16 +638,17 @@ show_help(bool full, const char *query_prop_fcc = nullptr) // Enumerate all cards in this system for (auto &d : bmd_get_sorted_devices(deckLinkIterator)) { - IDeckLink *deckLink = d.second.get(); + IDeckLink *deckLink = get<0>(d).get(); string deviceName = bmd_get_device_name(deckLink); if (deviceName.empty()) { deviceName = "(unable to get name)"; } // *** Print the model name of the DeckLink card - color_printf("\t" TBOLD("%d") ") " TBOLD("%6x") ") " TBOLD( + color_printf("\t" TBOLD("%c") ") " TBOLD("%6x") ") " TBOLD( TGREEN("%s")) "\n", - numDevices, d.first, deviceName.c_str()); + get(d), get(d), + deviceName.c_str()); if (full) { print_output_modes(deckLink, query_prop_fcc); } @@ -1134,7 +1136,7 @@ static void display_decklink_probe(struct device_info **available_cards, int *co // Enumerate all cards in this system for (auto &d : bmd_get_sorted_devices(deckLinkIterator)) { - IDeckLink *deckLink = d.second.get(); + IDeckLink *deckLink = get<0>(d).get(); string deviceName = bmd_get_device_name(deckLink); if (deviceName.empty()) { deviceName = "(unknown)"; @@ -1144,7 +1146,9 @@ static void display_decklink_probe(struct device_info **available_cards, int *co *available_cards = (struct device_info *) realloc(*available_cards, *count * sizeof(struct device_info)); memset(*available_cards + *count - 1, 0, sizeof(struct device_info)); - snprintf((*available_cards)[*count - 1].dev, sizeof (*available_cards)[*count - 1].dev, ":device=%d", *count - 1); + snprintf((*available_cards)[*count - 1].dev, + sizeof(*available_cards)[*count - 1].dev, ":device=%u", + get(d)); snprintf((*available_cards)[*count - 1].extra, sizeof (*available_cards)[*count - 1].extra, "\"embeddedAudioAvailable\":\"t\""); (*available_cards)[*count - 1].repeatable = false; @@ -1387,7 +1391,6 @@ static void *display_decklink_init(struct module *parent, const char *fmt, unsig IDeckLinkIterator* deckLinkIterator; HRESULT result; string cardId("0"); - int dnum = 0; IDeckLinkConfiguration* deckLinkConfiguration = NULL; // for Decklink Studio which has switchable XLR - analog 3 and 4 or AES/EBU 3,4 and 5,6 @@ -1433,7 +1436,7 @@ static void *display_decklink_init(struct module *parent, const char *fmt, unsig // Connect to the first DeckLink instance for (auto &d : bmd_get_sorted_devices(deckLinkIterator)) { - s->deckLink = d.second.release(); // unmanage + s->deckLink = get<0>(d).release(); // unmanage string deviceName = bmd_get_device_name(s->deckLink); if (!deviceName.empty() && deviceName == cardId) { @@ -1441,17 +1444,24 @@ static void *display_decklink_init(struct module *parent, const char *fmt, unsig } // topological ID const unsigned long tid = strtoul(cardId.c_str(), nullptr, 16); - if (d.first == tid) { + if (get(d) == tid) { break; } - // idx - if (isdigit(cardId.c_str()[0]) && dnum == atoi(cardId.c_str())) { - break; + // natural (old) index + if (isdigit(cardId.c_str()[0])) { + if (atoi(cardId.c_str()) == get(d)) { + break; + } + } + // new (character) index + if (cardId.length() == 1 && cardId[0] >= 'a') { + if (cardId[0] == get(d)) { + break; + } } s->deckLink->Release(); s->deckLink = nullptr; - dnum++; } deckLinkIterator->Release(); if (s->deckLink == nullptr) {