mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
decklinkvideosink: Add support for Decklink hardware keying
Add two properties (keyer-mode and keyer-level) to control the built-in hardware keyer of Decklink cards. https://bugzilla.gnome.org/show_bug.cgi?id=773660
This commit is contained in:
parent
cbf4a44426
commit
0cd1bf13e8
4 changed files with 131 additions and 1 deletions
|
@ -168,6 +168,25 @@ gst_decklink_timecode_format_get_type (void)
|
|||
return (GType) id;
|
||||
}
|
||||
|
||||
GType
|
||||
gst_decklink_keyer_mode_get_type (void)
|
||||
{
|
||||
static gsize id = 0;
|
||||
static const GEnumValue keyermodes[] = {
|
||||
{GST_DECKLINK_KEYER_MODE_OFF, "Off", "off"},
|
||||
{GST_DECKLINK_KEYER_MODE_INTERNAL, "Internal", "internal"},
|
||||
{GST_DECKLINK_KEYER_MODE_EXTERNAL, "External", "external"},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
if (g_once_init_enter (&id)) {
|
||||
GType tmp = g_enum_register_static ("GstDecklinkKeyerMode", keyermodes);
|
||||
g_once_init_leave (&id, tmp);
|
||||
}
|
||||
|
||||
return (GType) id;
|
||||
}
|
||||
|
||||
GType
|
||||
gst_decklink_audio_connection_get_type (void)
|
||||
{
|
||||
|
@ -298,6 +317,18 @@ static const struct
|
|||
/* *INDENT-ON* */
|
||||
};
|
||||
|
||||
static const struct
|
||||
{
|
||||
BMDKeyerMode keymode;
|
||||
GstDecklinkKeyerMode gstkeymode;
|
||||
} kmodes[] = {
|
||||
/* *INDENT-OFF* */
|
||||
{bmdKeyerModeOff, GST_DECKLINK_KEYER_MODE_OFF},
|
||||
{bmdKeyerModeInternal, GST_DECKLINK_KEYER_MODE_INTERNAL},
|
||||
{bmdKeyerModeExternal, GST_DECKLINK_KEYER_MODE_EXTERNAL}
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
|
||||
const GstDecklinkMode *
|
||||
gst_decklink_get_mode (GstDecklinkModeEnum e)
|
||||
{
|
||||
|
@ -452,6 +483,25 @@ gst_decklink_timecode_format_to_enum (BMDTimecodeFormat f)
|
|||
return GST_DECKLINK_TIMECODE_FORMAT_RP188ANY;
|
||||
}
|
||||
|
||||
const BMDKeyerMode
|
||||
gst_decklink_keyer_mode_from_enum (GstDecklinkKeyerMode m)
|
||||
{
|
||||
return kmodes[m].keymode;
|
||||
}
|
||||
|
||||
const GstDecklinkKeyerMode
|
||||
gst_decklink_keyer_mode_to_enum (BMDKeyerMode m)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (kmodes); i++) {
|
||||
if (kmodes[i].keymode == m)
|
||||
return (GstDecklinkKeyerMode) i;
|
||||
}
|
||||
g_assert_not_reached ();
|
||||
return GST_DECKLINK_KEYER_MODE_OFF;
|
||||
}
|
||||
|
||||
static const BMDVideoConnection connections[] = {
|
||||
(BMDVideoConnection) 0, /* auto */
|
||||
bmdVideoConnectionSDI,
|
||||
|
@ -1177,6 +1227,13 @@ init_devices (gpointer data)
|
|||
"0x%08lx", (unsigned long) ret);
|
||||
}
|
||||
|
||||
ret = decklink->QueryInterface (IID_IDeckLinkKeyer,
|
||||
(void **) &devices[i].output.keyer);
|
||||
|
||||
/* We only warn of failure to obtain the keyer interface if the keyer
|
||||
* is enabled by keyer_mode
|
||||
*/
|
||||
|
||||
ret = iterator->Next (&decklink);
|
||||
i++;
|
||||
|
||||
|
|
|
@ -156,11 +156,32 @@ typedef enum {
|
|||
#define GST_TYPE_DECKLINK_TIMECODE_FORMAT (gst_decklink_timecode_format_get_type ())
|
||||
GType gst_decklink_timecode_format_get_type (void);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GST_DECKLINK_KEYER_MODE_OFF,
|
||||
GST_DECKLINK_KEYER_MODE_INTERNAL,
|
||||
GST_DECKLINK_KEYER_MODE_EXTERNAL
|
||||
} GstDecklinkKeyerMode;
|
||||
#define GST_TYPE_DECKLINK_KEYER_MODE (gst_decklink_keyer_mode_get_type ())
|
||||
GType gst_decklink_keyer_mode_get_type (void);
|
||||
|
||||
/* Enum BMDKeyerMode options of off, internal and external @@@ DJ @@@ */
|
||||
|
||||
typedef uint32_t BMDKeyerMode;
|
||||
enum _BMDKeyerMode
|
||||
{
|
||||
bmdKeyerModeOff = /* 'off' */ 0,
|
||||
bmdKeyerModeInternal = /* 'int' */ 1,
|
||||
bmdKeyerModeExternal = /* 'ext' */ 2
|
||||
};
|
||||
|
||||
const BMDPixelFormat gst_decklink_pixel_format_from_type (GstDecklinkVideoFormat t);
|
||||
const gint gst_decklink_bpp_from_type (GstDecklinkVideoFormat t);
|
||||
const GstDecklinkVideoFormat gst_decklink_type_from_video_format (GstVideoFormat f);
|
||||
const BMDTimecodeFormat gst_decklink_timecode_format_from_enum (GstDecklinkTimecodeFormat f);
|
||||
const GstDecklinkTimecodeFormat gst_decklink_timecode_format_to_enum (BMDTimecodeFormat f);
|
||||
const BMDKeyerMode gst_decklink_keyer_mode_from_enum (GstDecklinkKeyerMode m);
|
||||
const GstDecklinkKeyerMode gst_decklink_keyer_mode_to_enum (BMDKeyerMode m);
|
||||
|
||||
typedef struct _GstDecklinkMode GstDecklinkMode;
|
||||
struct _GstDecklinkMode {
|
||||
|
@ -187,6 +208,7 @@ struct _GstDecklinkOutput {
|
|||
IDeckLink *device;
|
||||
IDeckLinkOutput *output;
|
||||
IDeckLinkAttributes *attributes;
|
||||
IDeckLinkKeyer *keyer;
|
||||
GstClock *clock;
|
||||
GstClockTime clock_start_time, clock_last_time, clock_epoch;
|
||||
GstClockTimeDiff clock_offset;
|
||||
|
|
|
@ -120,7 +120,9 @@ enum
|
|||
PROP_MODE,
|
||||
PROP_DEVICE_NUMBER,
|
||||
PROP_VIDEO_FORMAT,
|
||||
PROP_TIMECODE_FORMAT
|
||||
PROP_TIMECODE_FORMAT,
|
||||
PROP_KEYER_MODE,
|
||||
PROP_KEYER_LEVEL
|
||||
};
|
||||
|
||||
static void gst_decklink_video_sink_set_property (GObject * object,
|
||||
|
@ -227,6 +229,20 @@ gst_decklink_video_sink_class_init (GstDecklinkVideoSinkClass * klass)
|
|||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT)));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_KEYER_MODE,
|
||||
g_param_spec_enum ("keyer-mode", "Keyer mode",
|
||||
"Keyer mode to be enabled",
|
||||
GST_TYPE_DECKLINK_KEYER_MODE,
|
||||
GST_DECKLINK_KEYER_MODE_OFF,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT)));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_KEYER_LEVEL,
|
||||
g_param_spec_int ("keyer-level", "Keyer level",
|
||||
"Keyer level", 0, 255, 255,
|
||||
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT)));
|
||||
|
||||
templ_caps = gst_decklink_mode_get_template_caps (FALSE);
|
||||
templ_caps = gst_caps_make_writable (templ_caps);
|
||||
/* For output we support any framerate and only really care about timestamps */
|
||||
|
@ -289,6 +305,14 @@ gst_decklink_video_sink_set_property (GObject * object, guint property_id,
|
|||
gst_decklink_timecode_format_from_enum ((GstDecklinkTimecodeFormat)
|
||||
g_value_get_enum (value));
|
||||
break;
|
||||
case PROP_KEYER_MODE:
|
||||
self->keyer_mode =
|
||||
gst_decklink_keyer_mode_from_enum ((GstDecklinkKeyerMode)
|
||||
g_value_get_enum (value));
|
||||
break;
|
||||
case PROP_KEYER_LEVEL:
|
||||
self->keyer_level = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
@ -315,6 +339,13 @@ gst_decklink_video_sink_get_property (GObject * object, guint property_id,
|
|||
g_value_set_enum (value,
|
||||
gst_decklink_timecode_format_to_enum (self->timecode_format));
|
||||
break;
|
||||
case PROP_KEYER_MODE:
|
||||
g_value_set_enum (value,
|
||||
gst_decklink_keyer_mode_to_enum (self->keyer_mode));
|
||||
break;
|
||||
case PROP_KEYER_LEVEL:
|
||||
g_value_set_int (value, self->keyer_level);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
|
@ -387,6 +418,24 @@ gst_decklink_video_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
|||
g_assert (mode != NULL);
|
||||
};
|
||||
|
||||
/* enable or disable keyer */
|
||||
if (self->output->keyer != NULL) {
|
||||
if (self->keyer_mode == bmdKeyerModeOff) {
|
||||
self->output->keyer->Disable ();
|
||||
} else if (self->keyer_mode == bmdKeyerModeInternal) {
|
||||
self->output->keyer->Enable (false);
|
||||
self->output->keyer->SetLevel (self->keyer_level);
|
||||
} else if (self->keyer_mode == bmdKeyerModeExternal) {
|
||||
self->output->keyer->Enable (true);
|
||||
self->output->keyer->SetLevel (self->keyer_level);
|
||||
} else {
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
} else if (self->keyer_mode != bmdKeyerModeOff) {
|
||||
GST_WARNING_OBJECT (self, "Failed to set keyer to mode %d",
|
||||
self->keyer_mode);
|
||||
}
|
||||
|
||||
/* The timecode_format itself is used when we embed the actual timecode data
|
||||
* into the frame. Now we only need to know which of the two standards the
|
||||
* timecode format will adhere to: VITC or RP188, and send the appropriate
|
||||
|
|
|
@ -53,6 +53,8 @@ struct _GstDecklinkVideoSink
|
|||
gint device_number;
|
||||
GstDecklinkVideoFormat video_format;
|
||||
BMDTimecodeFormat timecode_format;
|
||||
BMDKeyerMode keyer_mode;
|
||||
gint keyer_level;
|
||||
|
||||
GstVideoInfo info;
|
||||
|
||||
|
|
Loading…
Reference in a new issue