Browse Source

Decklink: Keyer support

Colin Edwards 7 years ago
parent
commit
19bc92d267

+ 9 - 2
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");

+ 1 - 0
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);

+ 2 - 0
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")

+ 16 - 4
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<DeckLinkOutput*>(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);
 }

+ 36 - 1
plugins/decklink/decklink-device.cpp

@@ -1,4 +1,4 @@
-#include <sstream>
+#include <sstream>
 
 #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<DeckLinkDeviceMode *>& 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;

+ 11 - 1
plugins/decklink/decklink-device.hpp

@@ -1,4 +1,4 @@
-#pragma once
+#pragma once
 
 #include "decklink-device-mode.hpp"
 
@@ -7,6 +7,8 @@
 #include <vector>
 #include <stdint.h>
 
+
+
 class DeckLinkDevice {
 	ComPtr<IDeckLink>                         device;
 	std::map<long long, DeckLinkDeviceMode *> 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<DeckLinkDeviceMode *>& GetInputModes(void) const;
 	const std::vector<DeckLinkDeviceMode *>& 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_)
 	{

+ 19 - 1
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<DeckLinkDevice> 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<DeckLinkDeviceMode*> &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;
 }