deck: return back original numeric indices

The numeric indices now use the "natural" index as devices given by
IDeckLinkIterator. The idea is to keep the index consistent with previous
versions.

For the devices ordered newly by topological ID, use character indices
instead ('a', 'b' etc.).

Do not advertise numeric indices for now, anyways, even though now left -
it can now be considered as a legacy feature, it can be later added to
the output if considered useful.
This commit is contained in:
Martin Pulec
2024-06-10 09:51:15 +02:00
parent 1a49de5695
commit e0a1d4fca9
4 changed files with 73 additions and 42 deletions

View File

@@ -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<unsigned, std::unique_ptr<IDeckLink, void (*)(IDeckLink *)>>
std::vector<bmd_dev>
bmd_get_sorted_devices(IDeckLinkIterator *deckLinkIterator)
{
IDeckLink *deckLink = nullptr;
std::map<unsigned, std::unique_ptr<IDeckLink, void (*)(IDeckLink *)>> out;
unsigned tid_substitute = UINT_MAX;
std::vector<bmd_dev> 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<IDeckLink, void (*)(IDeckLink *)>{
deckLink, release });
auto &it = out.emplace_back(
std::unique_ptr<IDeckLink, void (*)(IDeckLink *)>{
deckLink, release },
0, 0, 0);
std::get<unsigned>(it) = id;
std::get<int>(it) = idx++;
}
std::sort(out.begin(), out.end(), [](bmd_dev &a, bmd_dev &b) {
return std::get<unsigned>(a) < std::get<unsigned>(b);
});
// assign new indices
char new_idx = 'a';
for (auto &d : out) {
std::get<char>(d) = new_idx++;
}
return out;
}

View File

@@ -49,6 +49,7 @@
#include <cstdint>
#include <map>
#include <memory>
#include <tuple>
#include <vector>
#include <string>
#include <type_traits>
@@ -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<unsigned, std::unique_ptr<IDeckLink, void (*)(IDeckLink *)>>
/**
* @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<std::unique_ptr<IDeckLink, void (*)(IDeckLink *)>,
unsigned, int, char>;
std::vector<bmd_dev>
bmd_get_sorted_devices(IDeckLinkIterator *deckLinkIterator);
#endif // defined BLACKMAGIC_COMMON_HPP

View File

@@ -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<char>(d), get<unsigned>(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<unsigned>(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<unsigned>(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<int>(d)) {
break;
}
}
// new (character) index
if (device_id.length() == 1 && device_id[0] >= 'a') {
if (device_id[0] == get<char>(d)) {
break;
}
}
dnum++;
// Release the IDeckLink instance when we've finished with it to prevent leaks
deckLink->Release();
deckLink = NULL;

View File

@@ -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<char>(d), get<unsigned>(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<unsigned>(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<unsigned>(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<int>(d)) {
break;
}
}
// new (character) index
if (cardId.length() == 1 && cardId[0] >= 'a') {
if (cardId[0] == get<char>(d)) {
break;
}
}
s->deckLink->Release();
s->deckLink = nullptr;
dnum++;
}
deckLinkIterator->Release();
if (s->deckLink == nullptr) {