From 63731a3b6fc945b5596951d4ebba43c0fc94e97d Mon Sep 17 00:00:00 2001 From: "Joshua M. Doe" Date: Fri, 4 Jun 2021 10:50:30 -0400 Subject: [PATCH] gentlsrc: allow two interfaces of the same producer to be opened in one process Need to make it producer specific, and allow for multiple devices on the same interface --- sys/gentl/gstgentlsrc.c | 174 +++++++++++++++++++++++++++------------- sys/gentl/gstgentlsrc.h | 5 ++ 2 files changed, 125 insertions(+), 54 deletions(-) diff --git a/sys/gentl/gstgentlsrc.c b/sys/gentl/gstgentlsrc.c index 3baa110..59df264 100644 --- a/sys/gentl/gstgentlsrc.c +++ b/sys/gentl/gstgentlsrc.c @@ -137,6 +137,7 @@ static gboolean gst_gentlsrc_unlock_stop (GstBaseSrc * src); static GstFlowReturn gst_gentlsrc_create (GstPushSrc * src, GstBuffer ** buf); static gchar *gst_gentlsrc_get_error_string (GstGenTlSrc * src); +static void gst_gentlsrc_cleanup_tl (GstGenTlSrc * src); enum { @@ -404,6 +405,9 @@ gst_gentlsrc_class_init (GstGenTlSrcClass * klass) "Attributes", "Attributes to change, comma separated key=value pairs", DEFAULT_PROP_ATTRIBUTES, G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE)); + klass->hTL = NULL; + g_mutex_init (&klass->tl_mutex); + klass->tl_refcount = 0; } static void @@ -967,60 +971,63 @@ gst_gentlsrc_set_attributes (GstGenTlSrc * src) } static gboolean -gst_gentlsrc_start (GstBaseSrc * bsrc) +gst_gentlsrc_open_tl (GstGenTlSrc * src) { - GstGenTlSrc *src = GST_GENTL_SRC (bsrc); + GstGenTlSrcClass *klass = GST_GENTL_SRC_GET_CLASS (src); GC_ERROR ret; - uint32_t i, num_ifaces, num_devs; - guint32 width, height, stride; - GstVideoInfo vinfo; + uint32_t i, num_ifaces; - GST_DEBUG_OBJECT (src, "start"); - - if (src->producer_prop == GST_GENTLSRC_PRODUCER_BASLER) { - initialize_basler_addresses (&src->producer); - } else if (src->producer_prop == GST_GENTLSRC_PRODUCER_EVT) { - initialize_evt_addresses (&src->producer); + /* open framegrabber if it isn't already opened */ + if (klass->tl_refcount > 0) { + GST_DEBUG_OBJECT (src, + "Framegrabber interface already opened in this process, reusing"); + src->hTL = klass->hTL; + klass->tl_refcount++; } else { - g_assert_not_reached (); - } + /* initialize library and print info */ + ret = GTL_GCInitLib (); + //HANDLE_GTL_ERROR ("GenTL Producer library could not be initialized"); - /* bind functions from CTI */ - /* TODO: Enumerate CTI files in env var GENTL_GENTL64_PATH */ - if (!gst_gentlsrc_bind_functions (src)) { - GST_ELEMENT_ERROR (src, LIBRARY, INIT, - ("GenTL CTI could not be opened: %s", g_module_error ()), (NULL)); - return FALSE; - } + gst_gentl_print_gentl_impl_info (src); - /* initialize library and print info */ - ret = GTL_GCInitLib (); - HANDLE_GTL_ERROR ("GenTL Producer library could not be initialized"); + /* open GenTL, print info, and update interface list */ + ret = GTL_TLOpen (&src->hTL); + HANDLE_GTL_ERROR ("System module failed to open"); - gst_gentl_print_gentl_impl_info (src); + gst_gentl_print_system_info (src); - /* open GenTL, print info, and update interface list */ - ret = GTL_TLOpen (&src->hTL); - HANDLE_GTL_ERROR ("System module failed to open"); + ret = GTL_TLUpdateInterfaceList (src->hTL, NULL, src->timeout); + HANDLE_GTL_ERROR ("Failed to update interface list within timeout"); - gst_gentl_print_system_info (src); - - ret = GTL_TLUpdateInterfaceList (src->hTL, NULL, src->timeout); - HANDLE_GTL_ERROR ("Failed to update interface list within timeout"); - - /* print info for all interfaces and open specified interface */ - ret = GTL_TLGetNumInterfaces (src->hTL, &num_ifaces); - HANDLE_GTL_ERROR ("Failed to get number of interfaces"); - if (num_ifaces > 0) { - GST_DEBUG_OBJECT (src, "Found %d GenTL interfaces", num_ifaces); - for (i = 0; i < num_ifaces; ++i) { - gst_gentl_print_interface_info (src, i); + /* print info for all interfaces and open specified interface */ + ret = GTL_TLGetNumInterfaces (src->hTL, &num_ifaces); + HANDLE_GTL_ERROR ("Failed to get number of interfaces"); + if (num_ifaces > 0) { + GST_DEBUG_OBJECT (src, "Found %d GenTL interfaces", num_ifaces); + for (i = 0; i < num_ifaces; ++i) { + gst_gentl_print_interface_info (src, i); + } + } else { + GST_ELEMENT_ERROR (src, LIBRARY, FAILED, ("No interfaces found"), (NULL)); + goto error; } - } else { - GST_ELEMENT_ERROR (src, LIBRARY, FAILED, ("No interfaces found"), (NULL)); - goto error; + + klass->hTL = src->hTL; + klass->tl_refcount++; } + return TRUE; + +error: + return FALSE; +} + +static gboolean +gst_gentlsrc_open_interface (GstGenTlSrc * src) +{ + GstGenTlSrcClass *klass = GST_GENTL_SRC_GET_CLASS (src); + GC_ERROR ret; + if (!src->interface_id || src->interface_id[0] == 0) { size_t id_size; GST_DEBUG_OBJECT (src, "Trying to find interface ID at index %d", @@ -1042,6 +1049,54 @@ gst_gentlsrc_start (GstBaseSrc * bsrc) ret = GTL_TLOpenInterface (src->hTL, src->interface_id, &src->hIF); HANDLE_GTL_ERROR ("Interface module failed to open"); + return TRUE; + +error: + return FALSE; +} + +static gboolean +gst_gentlsrc_start (GstBaseSrc * bsrc) +{ + GstGenTlSrc *src = GST_GENTL_SRC (bsrc); + GstGenTlSrcClass *klass = GST_GENTL_SRC_GET_CLASS (src); + GC_ERROR ret; + uint32_t i, num_devs; + guint32 width, height, stride; + GstVideoInfo vinfo; + + GST_DEBUG_OBJECT (src, "start"); + + if (src->producer_prop == GST_GENTLSRC_PRODUCER_BASLER) { + initialize_basler_addresses (&src->producer); + } else if (src->producer_prop == GST_GENTLSRC_PRODUCER_EVT) { + initialize_evt_addresses (&src->producer); + } else { + g_assert_not_reached (); + } + + /* bind functions from CTI */ + /* TODO: Enumerate CTI files in env var GENTL_GENTL64_PATH */ + if (!gst_gentlsrc_bind_functions (src)) { + GST_ELEMENT_ERROR (src, LIBRARY, INIT, + ("GenTL CTI could not be opened: %s", g_module_error ()), (NULL)); + return FALSE; + } + + g_mutex_lock (&klass->tl_mutex); + + if (!gst_gentlsrc_open_tl (src)) { + g_mutex_unlock (&klass->tl_mutex); + goto error; + } + + if (!gst_gentlsrc_open_interface (src)) { + g_mutex_unlock (&klass->tl_mutex); + goto error; + } + + g_mutex_unlock (&klass->tl_mutex); + ret = GTL_IFUpdateDeviceList (src->hIF, NULL, src->timeout); HANDLE_GTL_ERROR ("Failed to update device list within timeout"); @@ -1392,16 +1447,32 @@ error: src->hIF = NULL; } - if (src->hTL) { - GTL_TLClose (src->hTL); - src->hTL = NULL; - } - - GTL_GCCloseLib (); + gst_gentlsrc_cleanup_tl (src); return FALSE; } +static void +gst_gentlsrc_cleanup_tl (GstGenTlSrc * src) +{ + GstGenTlSrcClass *klass = GST_GENTL_SRC_GET_CLASS (src); + if (src->hTL) { + g_mutex_lock (&klass->tl_mutex); + GST_DEBUG_OBJECT (src, "Framegrabber open with refcount=%d", + klass->tl_refcount); + klass->tl_refcount--; + if (klass->tl_refcount == 0) { + GST_DEBUG_OBJECT (src, "Framegrabber ref dropped to 0, closing"); + GTL_TLClose (src->hTL); + src->hTL = NULL; + } + g_mutex_unlock (&klass->tl_mutex); + src->hTL = NULL; + + GTL_GCCloseLib (); + } +} + static gboolean gst_gentlsrc_stop (GstBaseSrc * bsrc) { @@ -1434,12 +1505,7 @@ gst_gentlsrc_stop (GstBaseSrc * bsrc) src->hIF = NULL; } - if (src->hTL) { - GTL_TLClose (src->hTL); - src->hTL = NULL; - } - - GTL_GCCloseLib (); + gst_gentlsrc_cleanup_tl (src); GST_DEBUG_OBJECT (src, "Closed data stream, device, interface, and library"); diff --git a/sys/gentl/gstgentlsrc.h b/sys/gentl/gstgentlsrc.h index 83f9869..9090c31 100644 --- a/sys/gentl/gstgentlsrc.h +++ b/sys/gentl/gstgentlsrc.h @@ -34,6 +34,8 @@ G_BEGIN_DECLS #define GST_GENTL_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GENTL_SRC,GstGenTlSrcClass)) #define GST_IS_GENTL_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GENTL_SRC)) #define GST_IS_GENTL_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GENTL_SRC)) +#define GST_GENTL_SRC_GET_CLASS(klass) \ + (G_TYPE_INSTANCE_GET_CLASS ((klass), GST_TYPE_GENTL_SRC, GstGenTlSrcClass)) typedef struct _GstGenTlSrc GstGenTlSrc; typedef struct _GstGenTlSrcClass GstGenTlSrcClass; @@ -116,6 +118,9 @@ struct _GstGenTlSrc struct _GstGenTlSrcClass { GstPushSrcClass base_gentlsrc_class; + TL_HANDLE hTL; + GMutex tl_mutex; + guint tl_refcount; }; GType gst_gentlsrc_get_type (void);