decklink: Allow selecting input connections.

master
Colin Edwards 2019-02-25 23:19:35 -06:00
parent 8429724d64
commit 818001fb59
14 changed files with 236 additions and 24 deletions

View File

@ -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<std::recursive_mutex> 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;
}

View File

@ -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;
};

View File

@ -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")

View File

@ -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"
SwapFC-LFE.Tooltip="Swap Front Channel and LFE Channel"
VideoConnection="Video Connection"
AudioConnection="Audio Connection"

View File

@ -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";

View File

@ -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_);

View File

@ -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<IDeckLinkOutput> 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<DeckLinkDeviceMode *>& 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;

View File

@ -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<DeckLinkDeviceMode *>& GetInputModes(void) const;
const std::vector<DeckLinkDeviceMode *>& 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;

View File

@ -1,6 +1,7 @@
#include <obs-module.h>
#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<DeckLinkDevice> 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<DeckLinkDeviceMode*> &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);

View File

@ -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

View File

@ -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})

43
plugins/decklink/util.cpp Normal file
View File

@ -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";
}
}

View File

@ -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);

View File

@ -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