From a563cbbc1c6d3aa65e9f034857e1f42048553545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 4 Oct 2017 13:53:35 +0200 Subject: [PATCH] decklink: Add read-only property to read the device serial number https://bugzilla.gnome.org/show_bug.cgi?id=788510 --- sys/decklink/gstdecklink.cpp | 12 ++++++++++++ sys/decklink/gstdecklink.h | 5 +++++ sys/decklink/gstdecklinkaudiosink.cpp | 20 +++++++++++++++++++- sys/decklink/gstdecklinkaudiosrc.cpp | 14 ++++++++++++++ sys/decklink/gstdecklinkvideosink.cpp | 16 +++++++++++++++- sys/decklink/gstdecklinkvideosrc.cpp | 16 +++++++++++++++- 6 files changed, 80 insertions(+), 3 deletions(-) diff --git a/sys/decklink/gstdecklink.cpp b/sys/decklink/gstdecklink.cpp index f47f696364..58af0c6074 100644 --- a/sys/decklink/gstdecklink.cpp +++ b/sys/decklink/gstdecklink.cpp @@ -1232,6 +1232,18 @@ init_devices (gpointer data) if (ret != S_OK) { GST_WARNING ("selected device does not have config interface: 0x%08lx", (unsigned long) ret); + } else { + char *serial_number; + + ret = + devices[i].input. + config->GetString (bmdDeckLinkConfigDeviceInformationSerialNumber, + (COMSTR_T *) & serial_number); + CONVERT_COM_STRING (serial_number); + devices[i].output.hw_serial_number = g_strdup (serial_number); + devices[i].input.hw_serial_number = g_strdup (serial_number); + GST_DEBUG ("device %d has serial number %s", i, serial_number); + FREE_COM_STRING (serial_number); } ret = decklink->QueryInterface (IID_IDeckLinkAttributes, diff --git a/sys/decklink/gstdecklink.h b/sys/decklink/gstdecklink.h index 817358ae62..29809716eb 100644 --- a/sys/decklink/gstdecklink.h +++ b/sys/decklink/gstdecklink.h @@ -209,6 +209,9 @@ struct _GstDecklinkOutput { IDeckLinkOutput *output; IDeckLinkAttributes *attributes; IDeckLinkKeyer *keyer; + + gchar *hw_serial_number; + GstClock *clock; GstClockTime clock_start_time, clock_last_time, clock_epoch; GstClockTimeDiff clock_offset; @@ -238,6 +241,8 @@ struct _GstDecklinkInput { IDeckLinkConfiguration *config; IDeckLinkAttributes *attributes; + gchar *hw_serial_number; + /* Everything below protected by mutex */ GMutex lock; diff --git a/sys/decklink/gstdecklinkaudiosink.cpp b/sys/decklink/gstdecklinkaudiosink.cpp index de603c8d4d..84cd2eaa4b 100644 --- a/sys/decklink/gstdecklinkaudiosink.cpp +++ b/sys/decklink/gstdecklinkaudiosink.cpp @@ -487,6 +487,8 @@ gst_decklink_audio_sink_ringbuffer_open_device (GstAudioRingBuffer * rb) return FALSE; } + g_object_notify (G_OBJECT (self->sink), "hw-serial-number"); + gst_decklink_output_set_audio_clock (self->output, GST_AUDIO_BASE_SINK_CAST (self->sink)->provided_clock); @@ -514,7 +516,8 @@ gst_decklink_audio_sink_ringbuffer_close_device (GstAudioRingBuffer * rb) enum { PROP_0, - PROP_DEVICE_NUMBER + PROP_DEVICE_NUMBER, + PROP_HW_SERIAL_NUMBER }; static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", @@ -570,6 +573,11 @@ gst_decklink_audio_sink_class_init (GstDecklinkAudioSinkClass * klass) (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", + NULL, (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); + gst_element_class_add_static_pad_template (element_class, &sink_template); gst_element_class_set_static_metadata (element_class, "Decklink Audio Sink", @@ -619,6 +627,16 @@ gst_decklink_audio_sink_get_property (GObject * object, guint property_id, case PROP_DEVICE_NUMBER: g_value_set_int (value, self->device_number); break; + case PROP_HW_SERIAL_NUMBER:{ + GstDecklinkAudioSinkRingBuffer *buf = + GST_DECKLINK_AUDIO_SINK_RING_BUFFER_CAST (GST_AUDIO_BASE_SINK_CAST + (self)->ringbuffer); + if (buf && buf->output) + g_value_set_string (value, buf->output->hw_serial_number); + else + g_value_set_string (value, NULL); + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; diff --git a/sys/decklink/gstdecklinkaudiosrc.cpp b/sys/decklink/gstdecklinkaudiosrc.cpp index a9144281d3..a9b503638e 100644 --- a/sys/decklink/gstdecklinkaudiosrc.cpp +++ b/sys/decklink/gstdecklinkaudiosrc.cpp @@ -45,6 +45,7 @@ enum PROP_DISCONT_WAIT, PROP_BUFFER_SIZE, PROP_CHANNELS, + PROP_HW_SERIAL_NUMBER }; static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("src", @@ -184,6 +185,11 @@ gst_decklink_audio_src_class_init (GstDecklinkAudioSrcClass * klass) (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", + NULL, (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); + gst_element_class_add_static_pad_template (element_class, &sink_template); gst_element_class_set_static_metadata (element_class, "Decklink Audio Source", @@ -271,6 +277,12 @@ gst_decklink_audio_src_get_property (GObject * object, guint property_id, case PROP_CHANNELS: g_value_set_enum (value, self->channels); break; + case PROP_HW_SERIAL_NUMBER: + if (self->input) + g_value_set_string (value, self->input->hw_serial_number); + else + g_value_set_string (value, NULL); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -792,6 +804,8 @@ gst_decklink_audio_src_open (GstDecklinkAudioSrc * self) return FALSE; } + g_object_notify (G_OBJECT (self), "hw-serial-number"); + g_mutex_lock (&self->input->lock); if (self->channels > 0) { self->channels_found = self->channels; diff --git a/sys/decklink/gstdecklinkvideosink.cpp b/sys/decklink/gstdecklinkvideosink.cpp index 4096941c24..81ca083d06 100644 --- a/sys/decklink/gstdecklinkvideosink.cpp +++ b/sys/decklink/gstdecklinkvideosink.cpp @@ -122,7 +122,8 @@ enum PROP_VIDEO_FORMAT, PROP_TIMECODE_FORMAT, PROP_KEYER_MODE, - PROP_KEYER_LEVEL + PROP_KEYER_LEVEL, + PROP_HW_SERIAL_NUMBER }; static void gst_decklink_video_sink_set_property (GObject * object, @@ -243,6 +244,11 @@ 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_HW_SERIAL_NUMBER, + g_param_spec_string ("hw-serial-number", "Hardware serial number", + "The serial number (hardware ID) of the Decklink card", + NULL, (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); + 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 */ @@ -346,6 +352,12 @@ gst_decklink_video_sink_get_property (GObject * object, guint property_id, case PROP_KEYER_LEVEL: g_value_set_int (value, self->keyer_level); break; + case PROP_HW_SERIAL_NUMBER: + if (self->output) + g_value_set_string (value, self->output->hw_serial_number); + else + g_value_set_string (value, NULL); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -762,6 +774,8 @@ gst_decklink_video_sink_open (GstBaseSink * bsink) return FALSE; } + g_object_notify (G_OBJECT (self), "hw-serial-number"); + mode = gst_decklink_get_mode (self->mode); g_assert (mode != NULL); diff --git a/sys/decklink/gstdecklinkvideosrc.cpp b/sys/decklink/gstdecklinkvideosrc.cpp index 5a630e9fd4..e070e7e804 100644 --- a/sys/decklink/gstdecklinkvideosrc.cpp +++ b/sys/decklink/gstdecklinkvideosrc.cpp @@ -48,7 +48,8 @@ enum PROP_OUTPUT_STREAM_TIME, PROP_SKIP_FIRST_TIME, PROP_DROP_NO_SIGNAL_FRAMES, - PROP_SIGNAL + PROP_SIGNAL, + PROP_HW_SERIAL_NUMBER }; typedef struct @@ -211,6 +212,11 @@ gst_decklink_video_src_class_init (GstDecklinkVideoSrcClass * klass) "True if there is a valid input signal available", FALSE, (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); + 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", + NULL, (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); + templ_caps = gst_decklink_mode_get_template_caps (TRUE); gst_element_class_add_pad_template (element_class, gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, templ_caps)); @@ -359,6 +365,12 @@ gst_decklink_video_src_get_property (GObject * object, guint property_id, case PROP_SIGNAL: g_value_set_boolean (value, !self->no_signal); break; + case PROP_HW_SERIAL_NUMBER: + if (self->input) + g_value_set_string (value, self->input->hw_serial_number); + else + g_value_set_string (value, NULL); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -970,6 +982,8 @@ gst_decklink_video_src_open (GstDecklinkVideoSrc * self) return FALSE; } + g_object_notify (G_OBJECT (self), "hw-serial-number"); + mode = gst_decklink_get_mode (self->mode); g_assert (mode != NULL); g_mutex_lock (&self->input->lock);