diff --git a/plugins/decklink/DecklinkInput.cpp b/plugins/decklink/DecklinkInput.cpp index b79a617cf..0f74aa6e8 100644 --- a/plugins/decklink/DecklinkInput.cpp +++ b/plugins/decklink/DecklinkInput.cpp @@ -26,16 +26,20 @@ void DeckLinkInput::DevicesChanged(void *param, DeckLinkDevice *device, bool add const char *hash; long long mode; obs_data_t *settings; + BMDVideoConnection videoConnection; + BMDAudioConnection audioConnection; settings = obs_source_get_settings(decklink->source); hash = obs_data_get_string(settings, "device_hash"); + videoConnection = (BMDVideoConnection) obs_data_get_int(settings, "video_connection"); + audioConnection = (BMDAudioConnection) obs_data_get_int(settings, "audio_connection"); mode = obs_data_get_int(settings, "mode_id"); obs_data_release(settings); if (device->GetHash().compare(hash) == 0) { if (!decklink->activateRefs) return; - if (decklink->Activate(device, mode)) + if (decklink->Activate(device, mode, videoConnection, audioConnection)) os_atomic_dec_long(&decklink->activateRefs); } @@ -47,7 +51,9 @@ void DeckLinkInput::DevicesChanged(void *param, DeckLinkDevice *device, bool add } } -bool DeckLinkInput::Activate(DeckLinkDevice *device, long long modeId) +bool DeckLinkInput::Activate(DeckLinkDevice *device, long long modeId, + BMDVideoConnection bmdVideoConnection, + BMDAudioConnection bmdAudioConnection) { std::lock_guard lock(deviceMutex); DeckLinkDevice *curDevice = GetDevice(); @@ -58,6 +64,8 @@ bool DeckLinkInput::Activate(DeckLinkDevice *device, long long modeId) if (!isActive) return false; if (instance->GetActiveModeId() == modeId && + instance->GetVideoConnection() == bmdVideoConnection && + instance->GetAudioConnection() == bmdAudioConnection && instance->GetActivePixelFormat() == pixelFormat && instance->GetActiveColorSpace() == colorSpace && instance->GetActiveColorRange() == colorRange && @@ -87,7 +95,7 @@ bool DeckLinkInput::Activate(DeckLinkDevice *device, long long modeId) return false; } - if (!instance->StartCapture(mode)) { + if (!instance->StartCapture(mode, bmdVideoConnection, bmdAudioConnection)) { instance = nullptr; return false; } diff --git a/plugins/decklink/DecklinkInput.hpp b/plugins/decklink/DecklinkInput.hpp index 5ec79bf6d..c90dd7e1d 100644 --- a/plugins/decklink/DecklinkInput.hpp +++ b/plugins/decklink/DecklinkInput.hpp @@ -39,7 +39,9 @@ public: channelFormat = format; } - bool Activate(DeckLinkDevice *device, long long modeId); + bool Activate(DeckLinkDevice *device, long long modeId, + BMDVideoConnection bmdVideoConnection, + BMDAudioConnection bmdAudioConnection); void Deactivate(); bool Capturing(); @@ -48,4 +50,6 @@ public: std::string hash; long long id; bool swap = false; + BMDVideoConnection videoConnection; + BMDAudioConnection audioConnection; }; diff --git a/plugins/decklink/const.h b/plugins/decklink/const.h index 595fbb1a0..4f67a77f2 100644 --- a/plugins/decklink/const.h +++ b/plugins/decklink/const.h @@ -1,18 +1,22 @@ -#define DEVICE_HASH "device_hash" -#define DEVICE_NAME "device_name" -#define MODE_ID "mode_id" -#define MODE_NAME "mode_name" -#define CHANNEL_FORMAT "channel_format" -#define PIXEL_FORMAT "pixel_format" -#define COLOR_SPACE "color_space" -#define COLOR_RANGE "color_range" -#define BUFFERING "buffering" -#define DEACTIVATE_WNS "deactivate_when_not_showing" -#define AUTO_START "auto_start" -#define KEYER "keyer" -#define SWAP "swap" +#define DEVICE_HASH "device_hash" +#define DEVICE_NAME "device_name" +#define VIDEO_CONNECTION "video_connection" +#define AUDIO_CONNECTION "audio_connection" +#define MODE_ID "mode_id" +#define MODE_NAME "mode_name" +#define CHANNEL_FORMAT "channel_format" +#define PIXEL_FORMAT "pixel_format" +#define COLOR_SPACE "color_space" +#define COLOR_RANGE "color_range" +#define BUFFERING "buffering" +#define DEACTIVATE_WNS "deactivate_when_not_showing" +#define AUTO_START "auto_start" +#define KEYER "keyer" +#define SWAP "swap" #define TEXT_DEVICE obs_module_text("Device") +#define TEXT_VIDEO_CONNECTION obs_module_text("VideoConnection") +#define TEXT_AUDIO_CONNECTION obs_module_text("AudioConnection") #define TEXT_MODE obs_module_text("Mode") #define TEXT_PIXEL_FORMAT obs_module_text("PixelFormat") #define TEXT_COLOR_SPACE obs_module_text("ColorSpace") diff --git a/plugins/decklink/data/locale/en-US.ini b/plugins/decklink/data/locale/en-US.ini index e3123fcc9..0eb5a5a99 100644 --- a/plugins/decklink/data/locale/en-US.ini +++ b/plugins/decklink/data/locale/en-US.ini @@ -20,4 +20,6 @@ ChannelFormat.7_1ch="7.1ch" DeactivateWhenNotShowing="Deactivate when not showing" AutoStart="Auto start on launch" SwapFC-LFE="Swap FC <-> LFE" -SwapFC-LFE.Tooltip="Swap Front Channel and LFE Channel" \ No newline at end of file +SwapFC-LFE.Tooltip="Swap Front Channel and LFE Channel" +VideoConnection="Video Connection" +AudioConnection="Audio Connection" diff --git a/plugins/decklink/decklink-device-instance.cpp b/plugins/decklink/decklink-device-instance.cpp index 6dbfd7616..9b7e48090 100644 --- a/plugins/decklink/decklink-device-instance.cpp +++ b/plugins/decklink/decklink-device-instance.cpp @@ -191,7 +191,9 @@ void DeckLinkDeviceInstance::SetupVideoFormat(DeckLinkDeviceMode *mode_) #endif } -bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_) +bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_, + BMDVideoConnection bmdVideoConnection, + BMDAudioConnection bmdAudioConnection) { if (mode != nullptr) return false; @@ -203,6 +205,40 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_) if (!device->GetInput(&input)) return false; + + IDeckLinkConfiguration *deckLinkConfiguration = NULL; + HRESULT result = input->QueryInterface(IID_IDeckLinkConfiguration, + (void**)&deckLinkConfiguration); + if (result != S_OK) + { + LOG(LOG_ERROR, + "Could not obtain the IDeckLinkConfiguration interface: %08x\n", + result); + } else { + if (bmdVideoConnection > 0) { + result = deckLinkConfiguration->SetInt( + bmdDeckLinkConfigVideoInputConnection, bmdVideoConnection); + if (result != S_OK) { + LOG(LOG_ERROR, + "Couldn't set input video port to %d\n\n", + bmdVideoConnection); + } + } + + if (bmdAudioConnection > 0) { + result = deckLinkConfiguration->SetInt( + bmdDeckLinkConfigAudioInputConnection, bmdAudioConnection); + if (result != S_OK) { + LOG(LOG_ERROR, + "Couldn't set input audio port to %d\n\n", + bmdVideoConnection); + } + } + } + + videoConnection = bmdVideoConnection; + audioConnection = bmdAudioConnection; + BMDVideoInputFlags flags; bool isauto = mode_->GetName() == "Auto"; diff --git a/plugins/decklink/decklink-device-instance.hpp b/plugins/decklink/decklink-device-instance.hpp index 2b1c78180..bf03d82af 100644 --- a/plugins/decklink/decklink-device-instance.hpp +++ b/plugins/decklink/decklink-device-instance.hpp @@ -16,6 +16,8 @@ protected: DecklinkBase *decklink = nullptr; DeckLinkDevice *device = nullptr; DeckLinkDeviceMode *mode = nullptr; + BMDVideoConnection videoConnection; + BMDAudioConnection audioConnection; BMDDisplayMode displayMode = bmdModeNTSC; BMDPixelFormat pixelFormat = bmdFormat8BitYUV; video_colorspace colorSpace = VIDEO_CS_DEFAULT; @@ -56,10 +58,14 @@ public: inline video_range_type GetActiveColorRange() const {return colorRange;} inline speaker_layout GetActiveChannelFormat() const {return channelFormat;} inline bool GetActiveSwapState() const {return swap;} + inline BMDVideoConnection GetVideoConnection() const {return videoConnection;} + inline BMDAudioConnection GetAudioConnection() const {return audioConnection;} inline DeckLinkDeviceMode *GetMode() const {return mode;} - bool StartCapture(DeckLinkDeviceMode *mode); + bool StartCapture(DeckLinkDeviceMode *mode, + BMDVideoConnection bmdVideoConnection, + BMDAudioConnection bmdAudioConnection); bool StopCapture(void); bool StartOutput(DeckLinkDeviceMode *mode_); diff --git a/plugins/decklink/decklink-device.cpp b/plugins/decklink/decklink-device.cpp index 6c9d1b0b8..c2166cd4e 100644 --- a/plugins/decklink/decklink-device.cpp +++ b/plugins/decklink/decklink-device.cpp @@ -72,6 +72,18 @@ bool DeckLinkDevice::Init() } } + // Get supported video connections + attributes->GetInt(BMDDeckLinkVideoInputConnections, + &supportedVideoInputConnections); + attributes->GetInt(BMDDeckLinkVideoOutputConnections, + &supportedVideoOutputConnections); + + // Get supported audio connections + attributes->GetInt(BMDDeckLinkAudioInputConnections, + &supportedAudioInputConnections); + attributes->GetInt(BMDDeckLinkAudioOutputConnections, + &supportedAudioOutputConnections); + // find output modes ComPtr output; if (device->QueryInterface(IID_IDeckLinkOutput, (void **) &output) == S_OK) { @@ -98,8 +110,14 @@ bool DeckLinkDevice::Init() } // get keyer support - attributes->GetFlag(BMDDeckLinkSupportsExternalKeying, &supportsExternalKeyer); - attributes->GetFlag(BMDDeckLinkSupportsInternalKeying, &supportsInternalKeyer); + attributes->GetFlag(BMDDeckLinkSupportsExternalKeying, + &supportsExternalKeyer); + attributes->GetFlag(BMDDeckLinkSupportsInternalKeying, + &supportsInternalKeyer); + + // Sub Device Counts + attributes->GetInt(BMDDeckLinkSubDeviceIndex, &subDeviceIndex); + attributes->GetInt(BMDDeckLinkNumberOfSubDevices, &numSubDevices); decklink_string_t decklinkModelName; decklink_string_t decklinkDisplayName; @@ -207,6 +225,17 @@ const std::vector& DeckLinkDevice::GetOutputModes(void) co return outputModes; } +int64_t DeckLinkDevice::GetVideoInputConnections() +{ + return supportedVideoInputConnections; +} + +int64_t DeckLinkDevice::GetAudioInputConnections() +{ + return supportedAudioInputConnections; +} + + bool DeckLinkDevice::GetSupportsExternalKeyer(void) const { return supportsExternalKeyer; @@ -217,6 +246,16 @@ bool DeckLinkDevice::GetSupportsInternalKeyer(void) const return supportsInternalKeyer; } +int64_t DeckLinkDevice::GetSubDeviceCount() +{ + return numSubDevices; +} + +int64_t DeckLinkDevice::GetSubDeviceIndex() +{ + return subDeviceIndex; +} + const std::string& DeckLinkDevice::GetName(void) const { return name; diff --git a/plugins/decklink/decklink-device.hpp b/plugins/decklink/decklink-device.hpp index 5aefc32c6..a882a6c45 100644 --- a/plugins/decklink/decklink-device.hpp +++ b/plugins/decklink/decklink-device.hpp @@ -21,6 +21,12 @@ class DeckLinkDevice { int32_t maxChannel = 0; decklink_bool_t supportsExternalKeyer = false; decklink_bool_t supportsInternalKeyer = false; + int64_t subDeviceIndex = 0; + int64_t numSubDevices = 0; + int64_t supportedVideoInputConnections = -1; + int64_t supportedVideoOutputConnections = -1; + int64_t supportedAudioInputConnections = -1; + int64_t supportedAudioOutputConnections = -1; int keyerMode = 0; volatile long refCount = 1; @@ -39,8 +45,12 @@ public: const std::string& GetHash(void) const; const std::vector& GetInputModes(void) const; const std::vector& GetOutputModes(void) const; + int64_t GetVideoInputConnections(); + int64_t GetAudioInputConnections(); bool GetSupportsExternalKeyer(void) const; bool GetSupportsInternalKeyer(void) const; + int64_t GetSubDeviceCount(); + int64_t GetSubDeviceIndex(); int GetKeyerMode(void); void SetKeyerMode(int newKeyerMode); const std::string& GetName(void) const; diff --git a/plugins/decklink/decklink-source.cpp b/plugins/decklink/decklink-source.cpp index a9a68d840..b7ed0babb 100644 --- a/plugins/decklink/decklink-source.cpp +++ b/plugins/decklink/decklink-source.cpp @@ -1,6 +1,7 @@ #include #include "const.h" +#include "util.hpp" #include "DecklinkInput.hpp" #include "decklink-device.hpp" @@ -42,6 +43,10 @@ static void decklink_update(void *data, obs_data_t *settings) DeckLinkInput *decklink = (DeckLinkInput *)data; const char *hash = obs_data_get_string(settings, DEVICE_HASH); long long id = obs_data_get_int(settings, MODE_ID); + BMDVideoConnection videoConnection = (BMDVideoConnection) obs_data_get_int(settings, + VIDEO_CONNECTION); + BMDAudioConnection audioConnection = (BMDAudioConnection) obs_data_get_int(settings, + AUDIO_CONNECTION); BMDPixelFormat pixelFormat = (BMDPixelFormat)obs_data_get_int(settings, PIXEL_FORMAT); video_colorspace colorSpace = (video_colorspace)obs_data_get_int(settings, @@ -72,7 +77,7 @@ static void decklink_update(void *data, obs_data_t *settings) decklink->SetChannelFormat(channelFormat); decklink->hash = std::string(hash); decklink->swap = obs_data_get_bool(settings, SWAP); - decklink->Activate(device, id); + decklink->Activate(device, id, videoConnection, audioConnection); } static void decklink_show(void *data) @@ -83,7 +88,8 @@ static void decklink_show(void *data) if (decklink->dwns && showing && !decklink->Capturing()) { ComPtr device; device.Set(deviceEnum->FindByHash(decklink->hash.c_str())); - decklink->Activate(device, decklink->id); + decklink->Activate(device, decklink->id, decklink->videoConnection, + decklink->audioConnection); } } static void decklink_hide(void *data) @@ -134,9 +140,16 @@ static bool decklink_device_changed(obs_properties_t *props, obs_property_list_item_disable(list, 0, true); } + obs_property_t *videoConnectionList = obs_properties_get(props, + VIDEO_CONNECTION); + obs_property_t *audioConnectionList = obs_properties_get(props, + AUDIO_CONNECTION); obs_property_t *modeList = obs_properties_get(props, MODE_ID); obs_property_t *channelList = obs_properties_get(props, CHANNEL_FORMAT); + obs_property_list_clear(videoConnectionList); + obs_property_list_clear(audioConnectionList); + obs_property_list_clear(modeList); obs_property_list_clear(channelList); @@ -149,9 +162,38 @@ static bool decklink_device_changed(obs_properties_t *props, device.Set(deviceEnum->FindByHash(hash)); if (!device) { + obs_property_list_item_disable(videoConnectionList, 0, true); + obs_property_list_item_disable(audioConnectionList, 0, true); obs_property_list_add_int(modeList, mode, modeId); obs_property_list_item_disable(modeList, 0, true); } else { + const BMDVideoConnection BMDVideoConnections[] = { + bmdVideoConnectionSDI, bmdVideoConnectionHDMI, + bmdVideoConnectionOpticalSDI, bmdVideoConnectionComponent, + bmdVideoConnectionComposite, bmdVideoConnectionSVideo + }; + + for (BMDVideoConnection conn : BMDVideoConnections) { + if ((device->GetVideoInputConnections() & conn) == conn) { + obs_property_list_add_int(videoConnectionList, + bmd_video_connection_to_name(conn), conn); + } + } + + const BMDAudioConnection BMDAudioConnections[] = { + bmdAudioConnectionEmbedded, bmdAudioConnectionAESEBU, + bmdAudioConnectionAnalog, bmdAudioConnectionAnalogXLR, + bmdAudioConnectionAnalogRCA, bmdAudioConnectionMicrophone, + bmdAudioConnectionHeadphones + }; + + for (BMDAudioConnection conn : BMDAudioConnections) { + if ((device->GetAudioInputConnections() & conn) == conn) { + obs_property_list_add_int(audioConnectionList, + bmd_audio_connection_to_name(conn), conn); + } + } + const std::vector &modes = device->GetInputModes(); @@ -220,6 +262,11 @@ static obs_properties_t *decklink_get_properties(void *data) fill_out_devices(list); + obs_properties_add_list(props, VIDEO_CONNECTION, TEXT_VIDEO_CONNECTION, + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + obs_properties_add_list(props, AUDIO_CONNECTION, TEXT_AUDIO_CONNECTION, + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + list = obs_properties_add_list(props, MODE_ID, TEXT_MODE, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); obs_property_set_modified_callback(list, mode_id_changed); diff --git a/plugins/decklink/linux/CMakeLists.txt b/plugins/decklink/linux/CMakeLists.txt index 67da0210a..4f006ec4e 100644 --- a/plugins/decklink/linux/CMakeLists.txt +++ b/plugins/decklink/linux/CMakeLists.txt @@ -33,6 +33,7 @@ set(linux-decklink_HEADERS ../decklink-device-mode.hpp ../audio-repack.h ../audio-repack.hpp + ../util.hpp ) set(linux-decklink_SOURCES @@ -49,6 +50,7 @@ set(linux-decklink_SOURCES ../decklink-device-mode.cpp ../audio-repack.c platform.cpp + ../util.cpp ) add_library(linux-decklink MODULE diff --git a/plugins/decklink/mac/CMakeLists.txt b/plugins/decklink/mac/CMakeLists.txt index 2a2ed216f..04a2a1a0c 100644 --- a/plugins/decklink/mac/CMakeLists.txt +++ b/plugins/decklink/mac/CMakeLists.txt @@ -36,6 +36,7 @@ set(mac-decklink_HEADERS ../decklink-device-mode.hpp ../audio-repack.h ../audio-repack.hpp + ../util.hpp ) set(mac-decklink_SOURCES @@ -52,6 +53,7 @@ set(mac-decklink_SOURCES ../decklink-device-mode.cpp ../audio-repack.c platform.cpp + ../util.cpp ) list(APPEND decklink_HEADERS ${decklink_UI_HEADERS}) diff --git a/plugins/decklink/util.cpp b/plugins/decklink/util.cpp new file mode 100644 index 000000000..c3055e809 --- /dev/null +++ b/plugins/decklink/util.cpp @@ -0,0 +1,43 @@ +#include "util.hpp" + +const char *bmd_video_connection_to_name(BMDVideoConnection connection) +{ + switch (connection) { + case bmdVideoConnectionSDI: + return "SDI"; + case bmdVideoConnectionHDMI: + return "HDMI"; + case bmdVideoConnectionOpticalSDI: + return "Optical SDI"; + case bmdVideoConnectionComponent: + return "Component"; + case bmdVideoConnectionComposite: + return "Composite"; + case bmdVideoConnectionSVideo: + return "S-Video"; + default: + return "Unknown"; + } +} + +const char *bmd_audio_connection_to_name(BMDAudioConnection connection) +{ + switch (connection) { + case bmdAudioConnectionEmbedded: + return "Embedded"; + case bmdAudioConnectionAESEBU: + return "AES/EBU"; + case bmdAudioConnectionAnalog: + return "Analog"; + case bmdAudioConnectionAnalogXLR: + return "Analog XLR"; + case bmdAudioConnectionAnalogRCA: + return "Analog RCA"; + case bmdAudioConnectionMicrophone: + return "Microphone"; + case bmdAudioConnectionHeadphones: + return "Headphones"; + default: + return "Unknown"; + } +} \ No newline at end of file diff --git a/plugins/decklink/util.hpp b/plugins/decklink/util.hpp new file mode 100644 index 000000000..f264a0b5c --- /dev/null +++ b/plugins/decklink/util.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "decklink-device.hpp" + +const char *bmd_video_connection_to_name(BMDVideoConnection connection); + +const char *bmd_audio_connection_to_name(BMDAudioConnection connection); \ No newline at end of file diff --git a/plugins/decklink/win/CMakeLists.txt b/plugins/decklink/win/CMakeLists.txt index 19ecaaeb3..005dbb845 100644 --- a/plugins/decklink/win/CMakeLists.txt +++ b/plugins/decklink/win/CMakeLists.txt @@ -28,6 +28,7 @@ set(win-decklink_HEADERS ../decklink-device-mode.hpp ../audio-repack.h ../audio-repack.hpp + ../util.hpp ) set(win-decklink_SOURCES @@ -44,6 +45,7 @@ set(win-decklink_SOURCES ../decklink-device-mode.cpp ../audio-repack.c platform.cpp + ../util.cpp ) add_idl_files(win-decklink-sdk_GENERATED_FILES