]> git.sesse.net Git - nageru/commitdiff
Support DeckLink cards that don't have an HDMI connector.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 19 Jan 2017 23:44:10 +0000 (00:44 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 19 Jan 2017 23:44:10 +0000 (00:44 +0100)
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
decklink_output.cpp
decklink_output.h
decklink_util.cpp
decklink_util.h

index 2c255207c0bd5009fe85c362ff7be2d985fdeed9..892660da09eb64793c8f1490baf5368ace61c31d 100644 (file)
@@ -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;
index 46d9b140cb9214e5940e78c5a4656770769a8c00..7fa689e547610c0fb14696349a87f3e445e42422 100644 (file)
@@ -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);
        }
index 0aba5063839502ce77815a8af7c62ba5c138f816..0545bb7d697971dc5a408297b5ed57ff310b7779 100644 (file)
@@ -122,6 +122,7 @@ private:
 
        movit::ResourcePool *resource_pool;
        IDeckLinkOutput *output = nullptr;
+       BMDVideoConnection video_connection;
        QSurface *surface;
        unsigned width, height;
        unsigned card_index;
index 0e775dea4981b709077701389e30c40b4061b8ed..a6bdfd9cd65fe4831491a515346bd53322d600e7 100644 (file)
@@ -1,6 +1,8 @@
 #include <DeckLinkAPI.h>
 #include <DeckLinkAPIModes.h>
 
+#include <assert.h>
+
 #include "decklink_util.h"
 
 using namespace bmusb;
@@ -43,3 +45,43 @@ map<uint32_t, VideoMode> 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);
+       }
+}
index 2bef41589dade02ac2efda4f63d5dbe8269cce1c..2850a21cd9ec71000e918e62ea89f0f9fa517887 100644 (file)
@@ -11,4 +11,7 @@ class IDeckLinkDisplayModeIterator;
 
 std::map<uint32_t, bmusb::VideoMode> 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)