Decklink: Keyer support
parent
f1b9f6b3ce
commit
19bc92d267
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue