"readable": true,
"type": "gchararray",
"writable": false
+ },
+ "persistent-id": {
+ "blurb": "Output device instance to use. Higher priority than \"device-number\".",
+ "conditionally-available": false,
+ "construct": true,
+ "construct-only": false,
+ "controllable": false,
+ "default": "18446744073709551615",
+ "max": "9223372036854775807",
+ "min": "-1",
+ "mutable": "null",
+ "readable": true,
+ "type": "gint64",
+ "writable": true
}
},
"rank": "none"
"readable": true,
"type": "gchararray",
"writable": false
+ },
+ "persistent-id": {
+ "blurb": "Output device instance to use. Higher priority than \"device-number\".",
+ "conditionally-available": false,
+ "construct": true,
+ "construct-only": false,
+ "controllable": false,
+ "default": "18446744073709551615",
+ "max": "9223372036854775807",
+ "min": "-1",
+ "mutable": "null",
+ "readable": true,
+ "type": "gint64",
+ "writable": true
}
},
"rank": "none"
"type": "GstDecklinkModes",
"writable": true
},
+ "persistent-id": {
+ "blurb": "Output device instance to use. Higher priority than \"device-number\".",
+ "conditionally-available": false,
+ "construct": true,
+ "construct-only": false,
+ "controllable": false,
+ "default": "18446744073709551615",
+ "max": "9223372036854775807",
+ "min": "-1",
+ "mutable": "null",
+ "readable": true,
+ "type": "gint64",
+ "writable": true
+ },
"profile": {
"blurb": "Certain DeckLink devices such as the DeckLink 8K Pro, the DeckLink Quad 2 and the DeckLink Duo 2 support multiple profiles to configure the capture and playback behavior of its sub-devices.For the DeckLink Duo 2 and DeckLink Quad 2, a profile is shared between any 2 sub-devices that utilize the same connectors. For the DeckLink 8K Pro, a profile is shared between all 4 sub-devices. Any sub-devices that share a profile are considered to be part of the same profile group.DeckLink Duo 2 support configuration of the duplex mode of individual sub-devices.",
"conditionally-available": false,
"type": "gboolean",
"writable": true
},
+ "persistent-id": {
+ "blurb": "Output device instance to use. Higher priority than \"device-number\".",
+ "conditionally-available": false,
+ "construct": true,
+ "construct-only": false,
+ "controllable": false,
+ "default": "18446744073709551615",
+ "max": "9223372036854775807",
+ "min": "-1",
+ "mutable": "null",
+ "readable": true,
+ "type": "gint64",
+ "writable": true
+ },
"profile": {
"blurb": "Certain DeckLink devices such as the DeckLink 8K Pro, the DeckLink Quad 2 and the DeckLink Duo 2 support multiple profiles to configure the capture and playback behavior of its sub-devices.For the DeckLink Duo 2 and DeckLink Quad 2, a profile is shared between any 2 sub-devices that utilize the same connectors. For the DeckLink 8K Pro, a profile is shared between all 4 sub-devices. Any sub-devices that share a profile are considered to be part of the same profile group.DeckLink Duo 2 support configuration of the duplex mode of individual sub-devices.",
"conditionally-available": false,
GST_DEBUG_CATEGORY_STATIC (gst_decklink_debug);
#define GST_CAT_DEFAULT gst_decklink_debug
+#define DEFAULT_PERSISTENT_ID (-1)
GType
gst_decklink_mode_get_type (void)
static MappingFormatSetOperationResult gst_decklink_configure_mapping_format (Device *
device, GstDecklinkMappingFormat mapping_format);
+static gboolean
+persistent_id_is_equal_input (const Device * a, const gint64 * b)
+{
+ return a->input.persistent_id == *b;
+}
+
+static gboolean
+persistent_id_is_equal_output (const Device * a, const gint64 * b)
+{
+ return a->output.persistent_id == *b;
+}
+
class GStreamerDecklinkInputCallback:public IDeckLinkInputCallback
{
private:
static GstDecklinkDevice *
gst_decklink_device_new (const gchar * model_name, const gchar * display_name,
- const gchar * serial_number, gboolean supports_format_detection,
- GstCaps * video_caps, guint max_channels, gboolean video, gboolean capture,
- guint device_number)
+ const gchar * serial_number, gint64 persistent_id,
+ gboolean supports_format_detection, GstCaps * video_caps,
+ guint max_channels, gboolean video, gboolean capture, guint device_number)
{
GstDevice *ret;
gchar *name;
gst_structure_set (properties, "serial-number", G_TYPE_STRING,
serial_number, NULL);
+ if (persistent_id)
+ gst_structure_set (properties, "persistent-id", G_TYPE_INT64,
+ persistent_id, NULL);
+
ret = GST_DEVICE (g_object_new (GST_TYPE_DECKLINK_DEVICE,
"display-name", name,
"device-class", device_class, "caps", caps, "properties", properties,
GST_DECKLINK_DEVICE (ret)->video = video;
GST_DECKLINK_DEVICE (ret)->capture = capture;
- GST_DECKLINK_DEVICE (ret)->device_number = device_number;
+ GST_DECKLINK_DEVICE (ret)->persistent_id = persistent_id;
return GST_DECKLINK_DEVICE (ret);
}
+static gint
+compare_persistent_id (gconstpointer a, gconstpointer b)
+{
+ const Device *const dev1 = *(Device **) a;
+ const Device *const dev2 = *(Device **) b;
+ return dev1->input.persistent_id - dev2->input.persistent_id;
+}
+
static gpointer
init_devices (gpointer data)
{
gchar *model_name = NULL;
gchar *display_name = NULL;
gchar *serial_number = NULL;
+ gint64 persistent_id = 0;
gboolean supports_format_detection = 0;
gint64 max_channels = 2;
GstCaps *video_input_caps = gst_caps_new_empty ();
} else {
bool tmp_bool = false;
int64_t tmp_int = 2;
+ int64_t tmp_int_persistent_id = 0;
dev->input.attributes->GetInt (BMDDeckLinkMaximumAudioChannels, &tmp_int);
dev->input.attributes->GetFlag (BMDDeckLinkSupportsInputFormatDetection,
&tmp_bool);
supports_format_detection = tmp_bool;
max_channels = tmp_int;
+
+ ret =
+ dev->input.attributes->GetInt (BMDDeckLinkPersistentID,
+ &tmp_int_persistent_id);
+ if (ret == S_OK) {
+ persistent_id = tmp_int_persistent_id;
+ dev->output.persistent_id = persistent_id;
+ dev->input.persistent_id = persistent_id;
+ GST_DEBUG ("device %d has persistent id %" G_GINT64_FORMAT, i, persistent_id);
+ } else {
+ persistent_id = i;
+ dev->output.persistent_id = i;
+ dev->input.persistent_id = i;
+ GST_DEBUG ("device %d does not have persistent id. Value set to %d", i, i);
+ }
}
decklink->GetModelName ((COMSTR_T *) & model_name);
if (capture) {
dev->devices[0] =
gst_decklink_device_new (model_name, display_name, serial_number,
- supports_format_detection, video_input_caps, max_channels, TRUE, TRUE,
- i);
+ persistent_id, supports_format_detection, video_input_caps,
+ max_channels, TRUE, TRUE, i);
dev->devices[1] =
gst_decklink_device_new (model_name, display_name, serial_number,
- supports_format_detection, video_input_caps, max_channels, FALSE,
- TRUE, i);
+ persistent_id, supports_format_detection, video_input_caps,
+ max_channels, FALSE, TRUE, i);
}
if (output) {
dev->devices[2] =
gst_decklink_device_new (model_name, display_name, serial_number,
- supports_format_detection, video_output_caps, max_channels, TRUE,
- FALSE, i);
+ persistent_id, supports_format_detection, video_output_caps,
+ max_channels, TRUE, FALSE, i);
dev->devices[3] =
gst_decklink_device_new (model_name, display_name, serial_number,
- supports_format_detection, video_output_caps, max_channels, FALSE,
- FALSE, i);
+ persistent_id, supports_format_detection, video_output_caps,
+ max_channels, FALSE, FALSE, i);
}
if (model_name)
iterator->Release ();
+ g_ptr_array_sort (devices, compare_persistent_id);
+
return NULL;
}
}
GstDecklinkOutput *
-gst_decklink_acquire_nth_output (gint n, GstElement * sink, gboolean is_audio)
+gst_decklink_acquire_nth_output (gint n, gint64 persistent_id,
+ GstElement * sink, gboolean is_audio)
{
GstDecklinkOutput *output;
Device *device;
+ guint found_index;
g_once (&devices_once, init_devices, NULL);
if (devices == NULL)
return NULL;
+ if (persistent_id != DEFAULT_PERSISTENT_ID) {
+ if (g_ptr_array_find_with_equal_func (devices, &persistent_id,
+ (GEqualFunc) persistent_id_is_equal_output, &found_index)) {
+ n = found_index;
+ GST_DEBUG ("Persistent ID: %" G_GINT64_FORMAT ", used", persistent_id);
+ } else {
+ return NULL;
+ }
+ }
+
if (n < 0 || (guint) n >= devices->len)
return NULL;
}
void
-gst_decklink_release_nth_output (gint n, GstElement * sink, gboolean is_audio)
+gst_decklink_release_nth_output (gint n, gint64 persistent_id,
+ GstElement * sink, gboolean is_audio)
{
GstDecklinkOutput *output;
Device *device;
+ guint found_index;
if (devices == NULL)
return;
+ if (persistent_id != DEFAULT_PERSISTENT_ID) {
+ if (g_ptr_array_find_with_equal_func (devices, &persistent_id,
+ (GEqualFunc) persistent_id_is_equal_output, &found_index)) {
+ n = found_index;
+ GST_DEBUG ("Persistent ID: %" G_GINT64_FORMAT ", used", persistent_id);
+ } else {
+ return;
+ }
+ }
+
if (n < 0 || (guint) n >= devices->len)
return;
}
GstDecklinkInput *
-gst_decklink_acquire_nth_input (gint n, GstElement * src, gboolean is_audio)
+gst_decklink_acquire_nth_input (gint n, gint64 persistent_id, GstElement * src,
+ gboolean is_audio)
{
GstDecklinkInput *input;
Device *device;
+ guint found_index;
g_once (&devices_once, init_devices, NULL);
if (devices == NULL)
return NULL;
+ if (persistent_id != DEFAULT_PERSISTENT_ID) {
+ if (g_ptr_array_find_with_equal_func (devices, &persistent_id,
+ (GEqualFunc) persistent_id_is_equal_input, &found_index)) {
+ n = found_index;
+ GST_DEBUG ("Persistent ID: %" G_GINT64_FORMAT ", used", persistent_id);
+ } else {
+ return NULL;
+ }
+ }
+
if (n < 0 || (guint) n >= devices->len)
return NULL;
}
void
-gst_decklink_release_nth_input (gint n, GstElement * src, gboolean is_audio)
+gst_decklink_release_nth_input (gint n, gint64 persistent_id, GstElement * src,
+ gboolean is_audio)
{
GstDecklinkInput *input;
Device *device;
+ guint found_index;
if (devices == NULL)
return;
+ if (persistent_id != DEFAULT_PERSISTENT_ID) {
+ if (g_ptr_array_find_with_equal_func (devices, &persistent_id,
+ (GEqualFunc) persistent_id_is_equal_input, &found_index)) {
+ n = found_index;
+ GST_DEBUG ("Persistent ID: %" G_GINT64_FORMAT ", used", persistent_id);
+ } else {
+ return;
+ }
+ }
+
if (n < 0 || (guint) n >= devices->len)
return;
IDeckLinkKeyer *keyer;
gchar *hw_serial_number;
+ gint64 persistent_id;
GstClock *clock;
GstClockTime clock_start_time, clock_last_time, clock_epoch;
IDeckLinkProfileAttributes *attributes;
gchar *hw_serial_number;
+ gint64 persistent_id;
/* Everything below protected by mutex */
GMutex lock;
void (*start_streams) (GstElement *videosrc);
};
-GstDecklinkOutput * gst_decklink_acquire_nth_output (gint n, GstElement * sink, gboolean is_audio);
-void gst_decklink_release_nth_output (gint n, GstElement * sink, gboolean is_audio);
+GstDecklinkOutput * gst_decklink_acquire_nth_output (gint n, gint64 persistent_id, GstElement * sink, gboolean is_audio);
+void gst_decklink_release_nth_output (gint n, gint64 persistent_id, GstElement * sink, gboolean is_audio);
-GstDecklinkInput * gst_decklink_acquire_nth_input (gint n, GstElement * src, gboolean is_audio);
-void gst_decklink_release_nth_input (gint n, GstElement * src, gboolean is_audio);
+GstDecklinkInput * gst_decklink_acquire_nth_input (gint n, gint64 persistent_id, GstElement * src, gboolean is_audio);
+void gst_decklink_release_nth_input (gint n, gint64 persistent_id, GstElement * src, gboolean is_audio);
const GstDecklinkMode * gst_decklink_find_mode_for_caps (GstCaps * caps);
const GstDecklinkMode * gst_decklink_find_mode_and_format_for_caps (GstCaps * caps, BMDPixelFormat * format);
GstDevice parent;
gboolean video;
gboolean capture;
- guint device_number;
+ gint64 persistent_id;
};
GType gst_decklink_device_get_type (void);
// Microseconds for audiobasesink compatibility...
#define DEFAULT_BUFFER_TIME (50 * GST_MSECOND / 1000)
+#define DEFAULT_PERSISTENT_ID (-1)
+
enum
{
PROP_0,
PROP_ALIGNMENT_THRESHOLD,
PROP_DISCONT_WAIT,
PROP_BUFFER_TIME,
+ PROP_PERSISTENT_ID
};
static void gst_decklink_audio_sink_set_property (GObject * object,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
G_PARAM_CONSTRUCT)));
+ /**
+ * GstDecklinkAudioSink:persistent-id
+ *
+ * Decklink device to use. Higher priority than "device-number".
+ * BMDDeckLinkPersistentID is a device specific, 32-bit unique identifier.
+ * It is stable even when the device is plugged in a different connector,
+ * across reboots, and when plugged into different computers.
+ *
+ * Since: 1.22
+ */
+ g_object_class_install_property (gobject_class, PROP_PERSISTENT_ID,
+ g_param_spec_int64 ("persistent-id", "Persistent id",
+ "Output device instance to use. Higher priority than \"device-number\".",
+ DEFAULT_PERSISTENT_ID, G_MAXINT64, DEFAULT_PERSISTENT_ID,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT)));
+
g_object_class_install_property (gobject_class, PROP_HW_SERIAL_NUMBER,
g_param_spec_string ("hw-serial-number", "Hardware serial number",
"The serial number (hardware ID) of the Decklink card",
DEFAULT_DISCONT_WAIT);
self->buffer_time = DEFAULT_BUFFER_TIME * 1000;
+ self->persistent_id = DEFAULT_PERSISTENT_ID;
+
gst_base_sink_set_max_lateness (GST_BASE_SINK_CAST (self), 20 * GST_MSECOND);
}
self->buffer_time = g_value_get_uint64 (value) * 1000;
GST_OBJECT_UNLOCK (self);
break;
+ case PROP_PERSISTENT_ID:
+ self->persistent_id = g_value_get_int64 (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
g_value_set_uint64 (value, self->buffer_time / 1000);
GST_OBJECT_UNLOCK (self);
break;
+ case PROP_PERSISTENT_ID:
+ g_value_set_int64 (value, self->persistent_id);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
GST_DEBUG_OBJECT (self, "Starting");
self->output =
- gst_decklink_acquire_nth_output (self->device_number,
+ gst_decklink_acquire_nth_output (self->device_number, self->persistent_id,
GST_ELEMENT_CAST (self), TRUE);
if (!self->output) {
GST_ERROR_OBJECT (self, "Failed to acquire output");
g_mutex_unlock (&self->output->lock);
self->output->output->DisableAudioOutput ();
- gst_decklink_release_nth_output (self->device_number,
+ gst_decklink_release_nth_output (self->device_number, self->persistent_id,
GST_ELEMENT_CAST (self), TRUE);
self->output = NULL;
}
GstAudioStreamAlign *stream_align;
GstAudioResampler *resampler;
guint resampler_in_rate, resampler_out_rate;
+
+ gint64 persistent_id;
};
struct _GstDecklinkAudioSinkClass
#define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
#endif
+#define DEFAULT_PERSISTENT_ID (-1)
+
enum
{
PROP_0,
PROP_DISCONT_WAIT,
PROP_BUFFER_SIZE,
PROP_CHANNELS,
- PROP_HW_SERIAL_NUMBER
+ PROP_HW_SERIAL_NUMBER,
+ PROP_PERSISTENT_ID
};
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("src",
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
G_PARAM_CONSTRUCT)));
+ /**
+ * GstDecklinkAudioSrc:persistent-id
+ *
+ * Decklink device to use. Higher priority than "device-number".
+ * BMDDeckLinkPersistentID is a device specific, 32-bit unique identifier.
+ * It is stable even when the device is plugged in a different connector,
+ * across reboots, and when plugged into different computers.
+ *
+ * Since: 1.22
+ */
+ g_object_class_install_property (gobject_class, PROP_PERSISTENT_ID,
+ g_param_spec_int64 ("persistent-id", "Persistent id",
+ "Output device instance to use. Higher priority than \"device-number\".",
+ DEFAULT_PERSISTENT_ID, G_MAXINT64, DEFAULT_PERSISTENT_ID,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT)));
+
g_object_class_install_property (gobject_class, PROP_ALIGNMENT_THRESHOLD,
g_param_spec_uint64 ("alignment-threshold", "Alignment Threshold",
"Timestamp alignment threshold in nanoseconds", 0,
self->skipped_last = 0;
self->skip_from_timestamp = GST_CLOCK_TIME_NONE;
self->skip_to_timestamp = GST_CLOCK_TIME_NONE;
+
+ self->persistent_id = DEFAULT_PERSISTENT_ID;
}
void
case PROP_CHANNELS:
self->channels = (GstDecklinkAudioChannelsEnum) g_value_get_enum (value);
break;
+ case PROP_PERSISTENT_ID:
+ self->persistent_id = g_value_get_int64 (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
else
g_value_set_string (value, NULL);
break;
+ case PROP_PERSISTENT_ID:
+ g_value_set_int64 (value, self->persistent_id);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
GST_DEBUG_OBJECT (self, "Opening");
self->input =
- gst_decklink_acquire_nth_input (self->device_number,
+ gst_decklink_acquire_nth_input (self->device_number, self->persistent_id,
GST_ELEMENT_CAST (self), TRUE);
if (!self->input) {
GST_ERROR_OBJECT (self, "Failed to acquire input");
self->input->got_audio_packet = NULL;
g_mutex_unlock (&self->input->lock);
- gst_decklink_release_nth_input (self->device_number,
+ gst_decklink_release_nth_input (self->device_number, self->persistent_id,
GST_ELEMENT_CAST (self), TRUE);
self->input = NULL;
}
GstDecklinkModeEnum mode;
GstDecklinkAudioConnectionEnum connection;
gint device_number;
+ gint64 persistent_id;
GstDecklinkAudioChannelsEnum channels;
gint64 channels_found;
#include "gstdecklinkdeviceprovider.h"
#include "gstdecklink.h"
+#define DEFAULT_PERSISTENT_ID (-1)
+
G_DEFINE_TYPE (GstDecklinkDeviceProvider, gst_decklink_device_provider,
GST_TYPE_DEVICE_PROVIDER);
GST_DEVICE_PROVIDER_REGISTER_DEFINE (decklinkdeviceprovider, "decklinkdeviceprovider",
}
if (ret) {
- g_object_set (ret, "device-number", self->device_number, NULL);
+ g_object_set (ret, "persistent-id", self->persistent_id, NULL);
}
return ret;
GST_DEBUG_CATEGORY_STATIC (gst_decklink_video_sink_debug);
#define GST_CAT_DEFAULT gst_decklink_video_sink_debug
+#define DEFAULT_PERSISTENT_ID (-1)
+
class GStreamerVideoOutputCallback:public IDeckLinkVideoOutputCallback
{
public:
PROP_CC_LINE,
PROP_AFD_BAR_LINE,
PROP_MAPPING_FORMAT,
+ PROP_PERSISTENT_ID
};
static void gst_decklink_video_sink_set_property (GObject * object,
"Output device instance to use", 0, G_MAXINT, 0,
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
G_PARAM_CONSTRUCT)));
+ /**
+ * GstDecklinkVideoSink:persistent-id
+ *
+ * Decklink device to use. Higher priority than "device-number".
+ * BMDDeckLinkPersistentID is a device specific, 32-bit unique identifier.
+ * It is stable even when the device is plugged in a different connector,
+ * across reboots, and when plugged into different computers.
+ *
+ * Since: 1.22
+ */
+ g_object_class_install_property (gobject_class, PROP_PERSISTENT_ID,
+ g_param_spec_int64 ("persistent-id", "Persistent id",
+ "Output device instance to use. Higher priority than \"device-number\".",
+ DEFAULT_PERSISTENT_ID, G_MAXINT64, DEFAULT_PERSISTENT_ID,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT)));
g_object_class_install_property (gobject_class, PROP_VIDEO_FORMAT,
g_param_spec_enum ("video-format", "Video format",
{
self->mode = GST_DECKLINK_MODE_NTSC;
self->device_number = 0;
+ self->persistent_id = DEFAULT_PERSISTENT_ID;
self->video_format = GST_DECKLINK_VIDEO_FORMAT_8BIT_YUV;
self->profile_id = GST_DECKLINK_PROFILE_ID_DEFAULT;
/* VITC is legacy, we should expect RP188 in modern use cases */
self->mapping_format =
(GstDecklinkMappingFormat) g_value_get_enum (value);
break;
+ case PROP_PERSISTENT_ID:
+ self->persistent_id = g_value_get_int64 (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
case PROP_MAPPING_FORMAT:
g_value_set_enum (value, self->mapping_format);
break;
+ case PROP_PERSISTENT_ID:
+ g_value_set_int64 (value, self->persistent_id);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
GST_DEBUG_OBJECT (self, "Starting");
self->output =
- gst_decklink_acquire_nth_output (self->device_number,
+ gst_decklink_acquire_nth_output (self->device_number, self->persistent_id,
GST_ELEMENT_CAST (self), FALSE);
if (!self->output) {
GST_ERROR_OBJECT (self, "Failed to acquire output");
g_mutex_unlock (&self->output->lock);
self->output->output->DisableVideoOutput ();
- gst_decklink_release_nth_output (self->device_number,
+ gst_decklink_release_nth_output (self->device_number, self->persistent_id,
GST_ELEMENT_CAST (self), FALSE);
self->output = NULL;
}
GstDecklinkModeEnum mode;
gint device_number;
+ gint64 persistent_id;
GstDecklinkVideoFormat video_format;
GstDecklinkProfileId profile_id;
BMDTimecodeFormat timecode_format;
#define DEFAULT_DROP_NO_SIGNAL_FRAMES (FALSE)
#define DEFAULT_OUTPUT_CC (FALSE)
#define DEFAULT_OUTPUT_AFD_BAR (FALSE)
+#define DEFAULT_PERSISTENT_ID (-1)
#ifndef ABSDIFF
#define ABSDIFF(x, y) ( (x) > (y) ? ((x) - (y)) : ((y) - (x)) )
PROP_DROP_NO_SIGNAL_FRAMES,
PROP_SIGNAL,
PROP_HW_SERIAL_NUMBER,
+ PROP_PERSISTENT_ID,
PROP_OUTPUT_CC,
PROP_OUTPUT_AFD_BAR,
};
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
G_PARAM_CONSTRUCT)));
+ /**
+ * GstDecklinkVideoSrc:persistent-id
+ *
+ * Decklink device to use. Higher priority than "device-number".
+ * BMDDeckLinkPersistentID is a device specific, 32-bit unique identifier.
+ * It is stable even when the device is plugged in a different connector,
+ * across reboots, and when plugged into different computers.
+ *
+ * Since: 1.22
+ */
+ g_object_class_install_property (gobject_class, PROP_PERSISTENT_ID,
+ g_param_spec_int64 ("persistent-id", "Persistent id",
+ "Output device instance to use. Higher priority than \"device-number\".",
+ DEFAULT_PERSISTENT_ID, G_MAXINT64, DEFAULT_PERSISTENT_ID,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT)));
+
g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
g_param_spec_uint ("buffer-size", "Buffer Size",
"Size of internal buffer in number of video frames", 1,
self->caps_format = bmdFormat8BitYUV;
self->connection = DEFAULT_CONNECTION;
self->device_number = 0;
+ self->persistent_id = DEFAULT_PERSISTENT_ID;
self->buffer_size = DEFAULT_BUFFER_SIZE;
self->video_format = GST_DECKLINK_VIDEO_FORMAT_AUTO;
self->profile_id = GST_DECKLINK_PROFILE_ID_DEFAULT;
case PROP_DROP_NO_SIGNAL_FRAMES:
self->drop_no_signal_frames = g_value_get_boolean (value);
break;
+ case PROP_PERSISTENT_ID:
+ self->persistent_id = g_value_get_int64 (value);
+ break;
case PROP_OUTPUT_CC:
self->output_cc = g_value_get_boolean (value);
break;
case PROP_DROP_NO_SIGNAL_FRAMES:
g_value_set_boolean (value, self->drop_no_signal_frames);
break;
+ case PROP_PERSISTENT_ID:
+ g_value_set_int64 (value, self->persistent_id);
+ break;
case PROP_SIGNAL:
g_value_set_boolean (value, self->signal_state == SIGNAL_STATE_AVAILABLE);
break;
GST_DEBUG_OBJECT (self, "Opening");
self->input =
- gst_decklink_acquire_nth_input (self->device_number,
+ gst_decklink_acquire_nth_input (self->device_number, self->persistent_id,
GST_ELEMENT_CAST (self), FALSE);
if (!self->input) {
GST_ERROR_OBJECT (self, "Failed to acquire input");
self->input->start_streams = NULL;
g_mutex_unlock (&self->input->lock);
- gst_decklink_release_nth_input (self->device_number,
+ gst_decklink_release_nth_input (self->device_number, self->persistent_id,
GST_ELEMENT_CAST (self), FALSE);
self->input = NULL;
}
BMDPixelFormat caps_format;
GstDecklinkConnectionEnum connection;
gint device_number;
+ gint64 persistent_id;
gboolean output_stream_time;
GstClockTime skip_first_time;
gboolean drop_no_signal_frames;