From 346775124875d76d1b87188fe8817fffd8d2240e Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Wed, 4 May 2016 11:58:37 +0200 Subject: [PATCH] DeckLink: Allow names as an identifier --- src/video_capture/decklink.cpp | 46 +++++++++++++++++++++++---------- src/video_display/decklink.cpp | 47 ++++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/src/video_capture/decklink.cpp b/src/video_capture/decklink.cpp index da1c7342f..85d2a3085 100644 --- a/src/video_capture/decklink.cpp +++ b/src/video_capture/decklink.cpp @@ -96,7 +96,7 @@ struct device_state { IDeckLinkInput* deckLinkInput; VideoDelegate* delegate; IDeckLinkConfiguration* deckLinkConfiguration; - int index; + string device_id; // either numeric value or device name }; struct vidcap_decklink_state { @@ -390,7 +390,7 @@ decklink_help() const char * deviceNameCString = NULL; // *** Print the model name of the DeckLink card - result = deckLink->GetModelName((BMD_STR *) &deviceNameString); + result = deckLink->GetDisplayName((BMD_STR *) &deviceNameString); deviceNameCString = get_cstr_from_bmd_api_str(deviceNameString); if (result == S_OK) { @@ -447,8 +447,8 @@ decklink_help() printf("\t%s -t decklink # captures autodetected video from first DeckLink in system\n", uv_argv[0]); printf("\t%s -t decklink:0:Hi50:UYVY # captures 1080i50, 8-bit yuv\n", uv_argv[0]); printf("\t%s -t decklink:0:10:v210:connection=HDMI # captures 10th format from a card (alternative syntax), 10-bit YUV, from HDMI\n", uv_argv[0]); - printf("\t%s -t decklink:mode=23ps # captures 1080p24, 8-bit yuv from frist device\n", uv_argv[0]); - printf("\t%s -t decklink:mode=Hp30:codec=v210:device=2 # captures 1080p30, 10-bit yuv from 3rd BMD device\n", uv_argv[0]); + printf("\t%s -t decklink:mode=23ps # captures 1080p24, 8-bit yuv from first device\n", uv_argv[0]); + printf("\t%s -t \"decklink:mode=Hp30:codec=v210:device=DeckLink 4K Extreme\" # captures 1080p30, 10-bit yuv from DeckLink 4K Extreme\n", uv_argv[0]); printf("\n"); @@ -471,7 +471,7 @@ static void parse_devices(struct vidcap_decklink_state *s, const char *devs) do { s->devices_cnt += 1; s->state.resize(s->devices_cnt); - s->state[s->devices_cnt - 1].index = atoi(ptr); + s->state[s->devices_cnt - 1].device_id = ptr; } while ((ptr = strtok_r(NULL, ",", &save_ptr_dev))); free (devices); } @@ -557,7 +557,7 @@ static int settings_init(struct vidcap_decklink_state *s, char *fmt) s->codec = UYVY; s->devices_cnt = 1; s->state.resize(s->devices_cnt); - s->state[0].index = 0; + s->state[0].device_id = "0"; char *tmp; char *save_ptr = NULL; @@ -575,6 +575,7 @@ static int settings_init(struct vidcap_decklink_state *s, char *fmt) // options are in format ::[:other_opts] if (isdigit(tmp[0])) { + LOG(LOG_LEVEL_WARNING) << MODULE_NAME "Deprecated syntax used, please use options in format \"key=value\"\n"; // choose device parse_devices(s, tmp); @@ -868,7 +869,29 @@ vidcap_decklink_init(const struct vidcap_params *params, void **state) } while (deckLinkIterator->Next(&deckLink) == S_OK) { - if (s->state[i].index != dnum) { + bool found = false; + + BMD_STR deviceNameString = NULL; + const char* deviceNameCString = NULL; + + result = deckLink->GetDisplayName(&deviceNameString); + if (result == S_OK) + { + deviceNameCString = get_cstr_from_bmd_api_str(deviceNameString); + + if (strcmp(deviceNameCString, s->state[i].device_id.c_str()) == 0) { + found = true; + } + + release_bmd_api_str(deviceNameString); + free((void *) deviceNameCString); + } + + if (isdigit(s->state[i].device_id.c_str()[0]) && atoi(s->state[i].device_id.c_str()) == dnum) { + found = true; + } + + if (!found) { dnum++; // Release the IDeckLink instance when we've finished with it to prevent leaks @@ -882,11 +905,8 @@ vidcap_decklink_init(const struct vidcap_params *params, void **state) s->state[i].deckLink = deckLink; - BMD_STR deviceNameString = NULL; - const char* deviceNameCString = NULL; - // Print the model name of the DeckLink card - result = deckLink->GetModelName(&deviceNameString); + result = deckLink->GetDisplayName(&deviceNameString); if (result == S_OK) { deviceNameCString = get_cstr_from_bmd_api_str(deviceNameString); @@ -1129,7 +1149,7 @@ vidcap_decklink_init(const struct vidcap_params *params, void **state) { if (device_found[i] == false) { - printf("Device %d wasn't found.\n", s->state[i].index); + LOG(LOG_LEVEL_ERROR) << "Device " << s->state[i].device_id << " was not found.\n"; goto error; } } @@ -1466,7 +1486,7 @@ static void print_input_modes (IDeckLink* deckLink) modeHeight = displayMode->GetHeight(); displayMode->GetFrameRate(&frameRateDuration, &frameRateScale); uint32_t mode = ntohl(displayMode->GetDisplayMode()); - printf("%d (%.4s)) %-20s \t %d x %d \t %2.2f FPS%s\n", displayModeNumber, (char *) &mode, displayModeCString, + printf("%2d (%.4s)) %-20s \t %d x %d \t %2.2f FPS%s\n", displayModeNumber, (char *) &mode, displayModeCString, modeWidth, modeHeight, (float) ((double)frameRateScale / (double)frameRateDuration), (flags & bmdDisplayModeSupports3D ? "\t (supports 3D)" : "")); release_bmd_api_str(displayModeString); diff --git a/src/video_display/decklink.cpp b/src/video_display/decklink.cpp index 3adec18a3..bcf8c90f4 100644 --- a/src/video_display/decklink.cpp +++ b/src/video_display/decklink.cpp @@ -63,6 +63,7 @@ #include #include #include +#include #include #include "DeckLinkAPIVersion.h" @@ -255,8 +256,8 @@ static void show_help(void) HRESULT result; printf("Decklink (output) options:\n"); - printf("\t-d decklink[:device=][:timecode][:single-link|:dual-link|:quad-link][:3D[:HDMI3DPacking=]][:audioConsumerLevels={true|false}][:conversion=][:Use1080pNotPsF={true|false}][:low-latency]\n"); - printf("\t\t is coma-separated indices of output devices\n"); + printf("\t-d decklink[:device=][:timecode][:single-link|:dual-link|:quad-link][:3D[:HDMI3DPacking=]][:audioConsumerLevels={true|false}][:conversion=][:Use1080pNotPsF={true|false}][:low-latency]\n"); + printf("\t\t is coma-separated indices or names of output devices\n"); printf("\t\tsingle-link/dual-link specifies if the video output will be in a single-link (HD/3G/6G/12G) or in dual-link HD-SDI mode\n"); // Create an IDeckLinkIterator object to enumerate all DeckLink cards in the system deckLinkIterator = create_decklink_iterator(true); @@ -270,7 +271,7 @@ static void show_help(void) BMD_STR deviceNameString = NULL; // *** Print the model name of the DeckLink card - result = deckLink->GetModelName(&deviceNameString); + result = deckLink->GetDisplayName(&deviceNameString); if (result == S_OK) { const char *deviceNameCString = get_cstr_from_bmd_api_str(deviceNameString); @@ -665,7 +666,7 @@ static void display_decklink_probe(struct device_info **available_cards, int *co BMD_STR deviceNameString = NULL; // *** Print the model name of the DeckLink card - HRESULT result = deckLink->GetModelName(&deviceNameString); + HRESULT result = deckLink->GetDisplayName(&deviceNameString); *count += 1; *available_cards = (struct device_info *) @@ -691,7 +692,7 @@ static void display_decklink_probe(struct device_info **available_cards, int *co decklink_uninitialize(); } -static bool parse_devices(const char *devices_str, int *cardIdx, int *devices_cnt) { +static bool parse_devices(const char *devices_str, string *cardId, int *devices_cnt) { if (strlen(devices_str) == 0) { log_msg(LOG_LEVEL_ERROR, MOD_NAME "Empty device string!\n"); return false; @@ -702,7 +703,7 @@ static bool parse_devices(const char *devices_str, int *cardIdx, int *devices_cn *devices_cnt = 0; char *item; while ((item = strtok_r(ptr, ",", &save_ptr))) { - cardIdx[*devices_cnt] = atoi(item); + cardId[*devices_cnt] = item; ++*devices_cnt; ptr = NULL; } @@ -717,7 +718,7 @@ static void *display_decklink_init(struct module *parent, const char *fmt, unsig struct state_decklink *s; IDeckLinkIterator* deckLinkIterator; HRESULT result; - int cardIdx[MAX_DEVICES]; + string cardId[MAX_DEVICES]; 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 @@ -736,7 +737,7 @@ static void *display_decklink_init(struct module *parent, const char *fmt, unsig s->stereo = FALSE; s->emit_timecode = false; s->link = 0; - cardIdx[0] = 0; + cardId[0] = "0"; s->devices_cnt = 1; if(fmt == NULL || strlen(fmt) == 0) { @@ -764,7 +765,7 @@ static void *display_decklink_init(struct module *parent, const char *fmt, unsig if (first_option_is_device) { log_msg(LOG_LEVEL_WARNING, MOD_NAME "Unnamed device index " "deprecated. Use \"device=%s\" instead.\n", ptr); - if (!parse_devices(ptr, cardIdx, &s->devices_cnt)) { + if (!parse_devices(ptr, cardId, &s->devices_cnt)) { delete s; return NULL; } @@ -773,7 +774,7 @@ static void *display_decklink_init(struct module *parent, const char *fmt, unsig while (ptr) { if (strncasecmp(ptr, "device=", strlen("device=")) == 0) { - if (!parse_devices(ptr + strlen("device="), cardIdx, &s->devices_cnt)) { + if (!parse_devices(ptr + strlen("device="), cardId, &s->devices_cnt)) { delete s; return NULL; } @@ -874,10 +875,30 @@ static void *display_decklink_init(struct module *parent, const char *fmt, unsig { bool found = false; for(int i = 0; i < s->devices_cnt; ++i) { - if (dnum == cardIdx[i]){ - s->state[i].deckLink = deckLink; + BMD_STR deviceNameString = NULL; + const char* deviceNameCString = NULL; + + result = deckLink->GetDisplayName(&deviceNameString); + if (result == S_OK) + { + deviceNameCString = get_cstr_from_bmd_api_str(deviceNameString); + + if (strcmp(deviceNameCString, cardId[i].c_str()) == 0) { + found = true; + } + + release_bmd_api_str(deviceNameString); + free((void *) deviceNameCString); + } + + + if (isdigit(cardId[i].c_str()[0]) && dnum == atoi(cardId[i].c_str())){ found = true; } + + if (found) { + s->state[i].deckLink = deckLink; + } } if(!found && deckLink != NULL) deckLink->Release(); @@ -885,7 +906,7 @@ static void *display_decklink_init(struct module *parent, const char *fmt, unsig } for(int i = 0; i < s->devices_cnt; ++i) { if(s->state[i].deckLink == NULL) { - log_msg(LOG_LEVEL_ERROR, "No DeckLink PCI card #%d found\n", cardIdx[i]); + LOG(LOG_LEVEL_ERROR) << "No DeckLink PCI card " << cardId[i] <<" found\n"; goto error; } }