diff --git a/libobs/obs-video.c b/libobs/obs-video.c index aaae79abe2b21939f556c0cf80e25e8d4518d732..4f962861fb2ebefe06743a4d811bc8c9b69c3fc7 100644 --- a/libobs/obs-video.c +++ b/libobs/obs-video.c @@ -117,7 +117,7 @@ static inline void render_main_texture(struct obs_core_video *video, profile_start(render_main_texture_name); struct vec4 clear_color; - vec4_set(&clear_color, 0.0f, 0.0f, 0.0f, 1.0f); + vec4_set(&clear_color, 0.0f, 0.0f, 0.0f, 0.0f); gs_set_render_target(video->render_textures[cur_texture], NULL); gs_clear(GS_CLEAR_COLOR, &clear_color, 1.0f, 0); @@ -207,7 +207,14 @@ static inline void render_output_texture(struct obs_core_video *video, 1.0f / (float)video->base_height); gs_effect_t *effect = get_scale_effect(video, width, height); - gs_technique_t *tech = gs_effect_get_technique(effect, "DrawMatrix"); + gs_technique_t *tech; + + if (video->ovi.output_format == VIDEO_FORMAT_RGBA) { + tech = gs_effect_get_technique(effect, "Draw"); + } else { + tech = gs_effect_get_technique(effect, "DrawMatrix"); + } + gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image"); gs_eparam_t *matrix = gs_effect_get_param_by_name(effect, "color_matrix"); diff --git a/plugins/decklink/DecklinkOutput.hpp b/plugins/decklink/DecklinkOutput.hpp index bdd873bca18878056b1a90f0475973ea4533575e..0a4fe85e386115a5e3fda55c6d075ed04d3d40cb 100644 --- a/plugins/decklink/DecklinkOutput.hpp +++ b/plugins/decklink/DecklinkOutput.hpp @@ -19,6 +19,7 @@ public: uint32_t audio_samplerate; size_t audio_planes; size_t audio_size; + int keyerMode; DeckLinkOutput(obs_output_t *output, DeckLinkDeviceDiscovery *discovery); virtual ~DeckLinkOutput(void); diff --git a/plugins/decklink/const.h b/plugins/decklink/const.h index 166777f20f757cd07eb5f50f34b6892e05c4af7e..872d04499c6de6b4837dede740ac41cf1f7cf4b9 100644 --- a/plugins/decklink/const.h +++ b/plugins/decklink/const.h @@ -9,6 +9,7 @@ #define BUFFERING "buffering" #define DEACTIVATE_WNS "deactivate_when_not_showing" #define AUTO_START "auto_start" +#define KEYER "keyer" #define TEXT_DEVICE obs_module_text("Device") #define TEXT_MODE obs_module_text("Mode") @@ -30,3 +31,4 @@ #define TEXT_BUFFERING obs_module_text("Buffering") #define TEXT_DWNS obs_module_text("DeactivateWhenNotShowing") #define TEXT_AUTO_START obs_module_text("AutoStart") +#define TEXT_ENABLE_KEYER obs_module_text("Keyer") diff --git a/plugins/decklink/decklink-device-instance.cpp b/plugins/decklink/decklink-device-instance.cpp index a685889974fe1155b45ca83577341e1af7141e29..5185d7fc5d05995f483081bb63cdef07c7dbb451 100644 --- a/plugins/decklink/decklink-device-instance.cpp +++ b/plugins/decklink/decklink-device-instance.cpp @@ -1,4 +1,4 @@ -#include "decklink-device-instance.hpp" +#include "decklink-device-instance.hpp" #include "audio-repack.hpp" #include "DecklinkInput.hpp" @@ -312,6 +312,18 @@ bool DeckLinkDeviceInstance::StartOutput(DeckLinkDeviceMode *mode_) mode = mode_; + + IDeckLinkKeyer *deckLinkKeyer = nullptr; + if (device->GetKeyer(&deckLinkKeyer)) { + int keyerMode = device->GetKeyerMode(); + if (keyerMode) { + deckLinkKeyer->Enable(keyerMode == 1); + deckLinkKeyer->SetLevel(255); + } else { + deckLinkKeyer->Disable(); + } + } + auto decklinkOutput = dynamic_cast(decklink); if (decklinkOutput == nullptr) return false; @@ -319,8 +331,8 @@ bool DeckLinkDeviceInstance::StartOutput(DeckLinkDeviceMode *mode_) HRESULT result; result = output->CreateVideoFrame(decklinkOutput->GetWidth(), decklinkOutput->GetHeight(), - decklinkOutput->GetWidth() * 2, - bmdFormat8BitYUV, + decklinkOutput->GetWidth() * 4, + bmdFormat8BitBGRA, bmdFrameFlagDefault, &decklinkOutputFrame); if (result != S_OK) { @@ -362,7 +374,7 @@ void DeckLinkDeviceInstance::DisplayVideoFrame(video_data *frame) uint8_t *outData = frame->data[0]; std::copy(outData, outData + (decklinkOutput->GetWidth() * - decklinkOutput->GetHeight() * 2), destData); + decklinkOutput->GetHeight() * 4), destData); output->DisplayVideoFrameSync(decklinkOutputFrame); } diff --git a/plugins/decklink/decklink-device.cpp b/plugins/decklink/decklink-device.cpp index 9d0f35c6531fe6280ef7ac05d3c17eb7ad5b6612..0bd182fc16ce1c6a4320b9902ebe5c30afe392bc 100644 --- a/plugins/decklink/decklink-device.cpp +++ b/plugins/decklink/decklink-device.cpp @@ -1,4 +1,4 @@ -#include +#include #include "decklink-device.hpp" @@ -97,6 +97,10 @@ bool DeckLinkDevice::Init() } } + // get keyer support + attributes->GetFlag(BMDDeckLinkSupportsExternalKeying, &supportsExternalKeyer); + attributes->GetFlag(BMDDeckLinkSupportsInternalKeying, &supportsInternalKeyer); + decklink_string_t decklinkModelName; decklink_string_t decklinkDisplayName; @@ -152,6 +156,27 @@ bool DeckLinkDevice::GetOutput(IDeckLinkOutput **output) return true; } +bool DeckLinkDevice::GetKeyer(IDeckLinkKeyer **deckLinkKeyer) +{ + if (device->QueryInterface(IID_IDeckLinkKeyer, (void**)deckLinkKeyer) != S_OK) + { + fprintf(stderr, "Could not obtain the IDeckLinkKeyer interface\n"); + return false; + } + + return true; +} + +void DeckLinkDevice::SetKeyerMode(int newKeyerMode) +{ + keyerMode = newKeyerMode; +} + +int DeckLinkDevice::GetKeyerMode(void) +{ + return keyerMode; +} + DeckLinkDeviceMode *DeckLinkDevice::FindInputMode(long long id) { return inputModeIdMap[id]; @@ -182,6 +207,16 @@ const std::vector& DeckLinkDevice::GetOutputModes(void) co return outputModes; } +const bool DeckLinkDevice::GetSupportsExternalKeyer(void) const +{ + return supportsExternalKeyer; +} + +const bool DeckLinkDevice::GetSupportsInternalKeyer(void) const +{ + return supportsInternalKeyer; +} + const std::string& DeckLinkDevice::GetName(void) const { return name; diff --git a/plugins/decklink/decklink-device.hpp b/plugins/decklink/decklink-device.hpp index acf0e98d14ead08894612520503f31d994b541c2..8791c6008800d40e37049c74dcd86dfa20f3cda7 100644 --- a/plugins/decklink/decklink-device.hpp +++ b/plugins/decklink/decklink-device.hpp @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "decklink-device-mode.hpp" @@ -7,6 +7,8 @@ #include #include + + class DeckLinkDevice { ComPtr device; std::map inputModeIdMap; @@ -17,6 +19,9 @@ class DeckLinkDevice { std::string displayName; std::string hash; int32_t maxChannel; + decklink_bool_t supportsExternalKeyer; + decklink_bool_t supportsInternalKeyer; + int keyerMode; volatile long refCount = 1; public: @@ -34,11 +39,16 @@ public: const std::string& GetHash(void) const; const std::vector& GetInputModes(void) const; const std::vector& GetOutputModes(void) const; + const bool GetSupportsExternalKeyer(void) const; + const bool GetSupportsInternalKeyer(void) const; + int GetKeyerMode(void); + void SetKeyerMode(int newKeyerMode); const std::string& GetName(void) const; int32_t GetMaxChannel(void) const; bool GetInput(IDeckLinkInput **input); bool GetOutput(IDeckLinkOutput **output); + bool GetKeyer(IDeckLinkKeyer **keyer); inline bool IsDevice(IDeckLink *device_) { diff --git a/plugins/decklink/decklink-output.cpp b/plugins/decklink/decklink-output.cpp index 19edc3e27f50d1110f33f9295659562c5f015ec7..2317c3aca8083c885c2c99731d151bdac32cc7be 100644 --- a/plugins/decklink/decklink-output.cpp +++ b/plugins/decklink/decklink-output.cpp @@ -22,6 +22,7 @@ static void *decklink_output_create(obs_data_t *settings, obs_output_t *output) decklinkOutput->deviceHash = obs_data_get_string(settings, DEVICE_HASH); decklinkOutput->modeID = obs_data_get_int(settings, MODE_ID); + decklinkOutput->keyerMode = obs_data_get_int(settings, KEYER); return decklinkOutput; } @@ -32,6 +33,7 @@ static void decklink_output_update(void *data, obs_data_t *settings) decklink->deviceHash = obs_data_get_string(settings, DEVICE_HASH); decklink->modeID = obs_data_get_int(settings, MODE_ID); + decklink->keyerMode = obs_data_get_int(settings, KEYER); } static bool decklink_output_start(void *data) @@ -59,12 +61,13 @@ static bool decklink_output_start(void *data) decklink->SetSize(mode->GetWidth(), mode->GetHeight()); struct video_scale_info to = {}; - to.format = VIDEO_FORMAT_UYVY; + to.format = VIDEO_FORMAT_BGRA; to.width = mode->GetWidth(); to.height = mode->GetHeight(); obs_output_set_video_conversion(decklink->GetOutput(), &to); + device->SetKeyerMode(decklink->keyerMode); decklink->Activate(device, decklink->modeID); struct audio_convert_info conversion = {}; @@ -172,8 +175,10 @@ static bool decklink_output_device_changed(obs_properties_t *props, } obs_property_t *modeList = obs_properties_get(props, MODE_ID); + obs_property_t *keyerList = obs_properties_get(props, KEYER); obs_property_list_clear(modeList); + obs_property_list_clear(keyerList); ComPtr device; device.Set(deviceEnum->FindByHash(hash)); @@ -181,6 +186,7 @@ static bool decklink_output_device_changed(obs_properties_t *props, if (!device) { obs_property_list_add_int(modeList, mode, modeId); obs_property_list_item_disable(modeList, 0, true); + obs_property_list_item_disable(keyerList, 0, true); } else { const std::vector &modes = device->GetOutputModes(); @@ -190,6 +196,16 @@ static bool decklink_output_device_changed(obs_properties_t *props, mode->GetName().c_str(), mode->GetId()); } + + obs_property_list_add_int(keyerList, "Disabled", 0); + + if (device->GetSupportsExternalKeyer()) { + obs_property_list_add_int(keyerList, "External", 1); + } + + if (device->GetSupportsInternalKeyer()) { + obs_property_list_add_int(keyerList, "Internal", 2); + } } return true; @@ -211,6 +227,8 @@ static obs_properties_t *decklink_output_properties(void *unused) obs_properties_add_bool(props, AUTO_START, TEXT_AUTO_START); + obs_properties_add_list(props, KEYER, TEXT_ENABLE_KEYER, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + return props; }