From 41f99ea4da78522f8d3e25619d8e619e4ba7681e Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Fri, 20 Jan 2017 00:44:10 +0100 Subject: [PATCH] Support DeckLink cards that don't have an HDMI connector. Setting input or output to HDMI on SDI-only cards is an error, even if HDMI/SDI generally outputs to both on combined cards. --- decklink_capture.cpp | 4 +++- decklink_output.cpp | 10 +++++++--- decklink_output.h | 1 + decklink_util.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ decklink_util.h | 3 +++ 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/decklink_capture.cpp b/decklink_capture.cpp index 2c25520..892660d 100644 --- a/decklink_capture.cpp +++ b/decklink_capture.cpp @@ -213,7 +213,9 @@ DeckLinkCapture::DeckLinkCapture(IDeckLink *card, int card_index) exit(1); } - set_video_input(bmdVideoConnectionHDMI); + BMDVideoConnection connection = pick_default_video_connection(card, BMDDeckLinkVideoInputConnections, card_index); + + set_video_input(connection); set_audio_input(bmdAudioConnectionEmbedded); IDeckLinkDisplayModeIterator *mode_it; diff --git a/decklink_output.cpp b/decklink_output.cpp index 46d9b14..7fa689e 100644 --- a/decklink_output.cpp +++ b/decklink_output.cpp @@ -52,6 +52,12 @@ void DeckLinkOutput::set_device(IDeckLink *decklink) } mode_it->Release(); + + // HDMI or SDI generally mean “both HDMI and SDI at the same time” on DeckLink cards + // that support both; pick_default_video_connection() will generally pick one of those + // if they exist. We're not very likely to need analog outputs, so we don't need a way + // to change beyond that. + video_connection = pick_default_video_connection(decklink, BMDDeckLinkVideoOutputConnections, card_index); } void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts) @@ -71,9 +77,7 @@ void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts) fprintf(stderr, "Failed to set low latency output\n"); exit(1); } - // HDMI or SDI generally mean “both HDMI and SDI at the same time” on DeckLink cards. - // We're not very likely to need analog outputs. - if (config->SetInt(bmdDeckLinkConfigVideoOutputConnection, bmdVideoConnectionHDMI) != S_OK) { + if (config->SetInt(bmdDeckLinkConfigVideoOutputConnection, video_connection) != S_OK) { fprintf(stderr, "Failed to set video output connection for card %u\n", card_index); exit(1); } diff --git a/decklink_output.h b/decklink_output.h index 0aba506..0545bb7 100644 --- a/decklink_output.h +++ b/decklink_output.h @@ -122,6 +122,7 @@ private: movit::ResourcePool *resource_pool; IDeckLinkOutput *output = nullptr; + BMDVideoConnection video_connection; QSurface *surface; unsigned width, height; unsigned card_index; diff --git a/decklink_util.cpp b/decklink_util.cpp index 0e775de..a6bdfd9 100644 --- a/decklink_util.cpp +++ b/decklink_util.cpp @@ -1,6 +1,8 @@ #include #include +#include + #include "decklink_util.h" using namespace bmusb; @@ -43,3 +45,43 @@ map summarize_video_modes(IDeckLinkDisplayModeIterator *mod return video_modes; } + +BMDVideoConnection pick_default_video_connection(IDeckLink *card, BMDDeckLinkAttributeID attribute_id, unsigned card_index) +{ + assert(attribute_id == BMDDeckLinkVideoInputConnections || + attribute_id == BMDDeckLinkVideoOutputConnections); + + IDeckLinkAttributes *attr; + if (card->QueryInterface(IID_IDeckLinkAttributes, (void**)&attr) != S_OK) { + fprintf(stderr, "Card %u has no attributes\n", card_index); + exit(1); + } + + int64_t connection_mask; + if (attr->GetInt(attribute_id, &connection_mask) != S_OK) { + if (attribute_id == BMDDeckLinkVideoInputConnections) { + fprintf(stderr, "Failed to enumerate video inputs for card %u\n", card_index); + } else { + fprintf(stderr, "Failed to enumerate video outputs for card %u\n", card_index); + } + exit(1); + } + attr->Release(); + if (connection_mask == 0) { + if (attribute_id == BMDDeckLinkVideoInputConnections) { + fprintf(stderr, "Card %u has no input connections\n", card_index); + } else { + fprintf(stderr, "Card %u has no outpu connectionss\n", card_index); + } + exit(1); + } + + if (connection_mask & bmdVideoConnectionHDMI) { + return bmdVideoConnectionHDMI; + } else if (connection_mask & bmdVideoConnectionSDI) { + return bmdVideoConnectionSDI; + } else { + // Fallback: Return lowest-set bit, whatever that might be. + return connection_mask & (-connection_mask); + } +} diff --git a/decklink_util.h b/decklink_util.h index 2bef415..2850a21 100644 --- a/decklink_util.h +++ b/decklink_util.h @@ -11,4 +11,7 @@ class IDeckLinkDisplayModeIterator; std::map summarize_video_modes(IDeckLinkDisplayModeIterator *mode_it, unsigned card_index); +// Picks a video connection that the card supports. Priority list: HDMI, SDI, anything else. +BMDVideoConnection pick_default_video_connection(IDeckLink *card, BMDDeckLinkAttributeID attribute_id, unsigned card_index); + #endif // !defined(_DECKLINK_UTIL) -- 2.39.2