diff --git a/CMakeLists.txt b/CMakeLists.txt index b848ef4..8c1a665 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,9 @@ macro_log_feature(EDT_FOUND "EDT" "Required to build EDT PDV source element" "ht find_package(Euresys) macro_log_feature(EURESYS_FOUND "Euresys" "Required to build Euresys source element" "http://www.euresys.com/" FALSE) +find_package(GigESim) +macro_log_feature(GIGESIM_FOUND "GigESim" "Required to build A&B Soft GigESim sink element" "http://www.ab-soft.com/" FALSE) + find_package(IDSuEye) macro_log_feature(IDSUEYE_FOUND "IDS uEye" "Required to build IDS uEye source element" "http://en.ids-imaging.com/" FALSE) diff --git a/README.md b/README.md index 99894b4..b1cceb0 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Image acquisition elements - edtpdvsrc: Video source for [EDT PDV frame grabbers][1] (Camera Link) - edtpdvsink: Video sink for [EDT PDV Camera Link simulator][2] - euresyssrc: Video source for [Euresys PICOLO, DOMINO and GRABLINK series frame grabbers][3] (analog, Camera Link) +- gigesimsink: Video sink for [A&B Soft GigESim][18] GigE Vision simulator - idsueyesrc: Video source for [IDS uEye cameras][11] (GigE Vision, USB 2/3, USB3 Vision) - imperxflexsrc: Video source for [IMPERX FrameLink and FrameLink Express frame grabbers][5] (Camera Link) - imperxsdisrc: Video source for [IMPERX HD-SDI Express frame grabbers][15] (SDI, HD-SDI) @@ -52,4 +53,5 @@ See also [14]: https://www.onsemi.com [15]: https://www.imperx.com/framegrabbers [16]: https://kayainstruments.com -[17]: https://www.pleora.com \ No newline at end of file +[17]: https://www.pleora.com +[18]: http://www.ab-soft.com/gigesim.php diff --git a/cmake/modules/FindGigESim.cmake b/cmake/modules/FindGigESim.cmake new file mode 100644 index 0000000..28f93d9 --- /dev/null +++ b/cmake/modules/FindGigESim.cmake @@ -0,0 +1,35 @@ +# - Try to find A&B Soft GigESim +# Once done this will define +# +# GIGESIM_FOUND - system has A&B Soft GigESim +# GIGESIM_INCLUDE_DIR - the A&B Soft GigESim include directory +# GIGESIM_LIBRARIES - the libraries needed to use the A&B Soft GigESim + +# Copyright (c) 2006, Tim Beaulen +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +if (NOT GIGESIM_DIR) + set (GIGESIM_DIR "C:/Program Files/GigESim" CACHE PATH "Directory containing A&B Soft GigESim") +endif (NOT GIGESIM_DIR) + +find_path (GIGESIM_INCLUDE_DIR GigeSimSDK.h + PATHS + "${GIGESIM_DIR}/Include" + DOC "Directory containing GigESim include file") + +if (CMAKE_SIZEOF_VOID_P MATCHES "8") +find_library (GIGESIM_LIBRARIES NAMES gigesimsdk64.lib + PATHS + "${GIGESIM_DIR}/Lib" + DOC "GIGESIM library to link with") +else () +find_library (GIGESIM_LIBRARIES NAMES gigesimsdk + PATHS + "${GIGESIM_DIR}/Lib" + DOC "GIGESIM library to link with") +endif () + +include (FindPackageHandleStandardArgs) +find_package_handle_standard_args (GIGESIM DEFAULT_MSG GIGESIM_INCLUDE_DIR GIGESIM_LIBRARIES) diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt index e14d79c..7e2dbf4 100644 --- a/ext/CMakeLists.txt +++ b/ext/CMakeLists.txt @@ -1,3 +1,7 @@ if(FREEIMAGE_FOUND) add_subdirectory (freeimage) endif(FREEIMAGE_FOUND) + +if(GIGESIM_FOUND) + add_subdirectory (gigesim) +endif(GIGESIM_FOUND) diff --git a/ext/gigesim/CMakeLists.txt b/ext/gigesim/CMakeLists.txt new file mode 100644 index 0000000..d34259b --- /dev/null +++ b/ext/gigesim/CMakeLists.txt @@ -0,0 +1,27 @@ +set (SOURCES + gstgigesim.cpp) + +set (HEADERS + gstgigesim.h) + +include_directories (AFTER + ${GIGESIM_INCLUDE_DIR}) + +set (libname libgstgigesim) + +add_library (${libname} MODULE + ${SOURCES} + ${HEADERS}) + +target_link_libraries (${libname} + ${GLIB2_LIBRARIES} + ${GOBJECT_LIBRARIES} + ${GSTREAMER_LIBRARY} + ${GSTREAMER_BASE_LIBRARY} + ${GSTREAMER_VIDEO_LIBRARY} + ${GIGESIM_LIBRARIES}) + +set (pdbfile "${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}/${libname}.pdb") +install (FILES ${pdbfile} DESTINATION lib/gstreamer-1.0 COMPONENT pdb) +install(TARGETS ${libname} + LIBRARY DESTINATION lib/gstreamer-1.0) diff --git a/ext/gigesim/gstgigesim.cpp b/ext/gigesim/gstgigesim.cpp new file mode 100644 index 0000000..62405df --- /dev/null +++ b/ext/gigesim/gstgigesim.cpp @@ -0,0 +1,556 @@ +/* GStreamer + * Copyright (C) 2011 FIXME + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Suite 500, + * Boston, MA 02110-1335, USA. + */ +/** + * SECTION:element-gstgigesimsink + * + * The gigesimsink element is a sink for A&B Soft GigESim to output a GigE Vision video stream. + * + * + * Example launch line + * |[ + * gst-launch -v videotestsrc ! autovideoconvert ! gigesimsink + * ]| + * Outputs test pattern using GigESim. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "gstgigesim.h" + +/* GObject prototypes */ +static void gst_gigesimsink_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec); +static void gst_gigesimsink_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec); +static void gst_gigesimsink_dispose (GObject * object); + +/* GstBaseSink prototypes */ +static gboolean gst_gigesimsink_start (GstBaseSink * basesink); +static gboolean gst_gigesimsink_stop (GstBaseSink * basesink); +static GstCaps *gst_gigesimsink_get_caps (GstBaseSink * basesink, + GstCaps * filter_caps); +static gboolean gst_gigesimsink_set_caps (GstBaseSink * basesink, + GstCaps * caps); +static GstFlowReturn gst_gigesimsink_render (GstBaseSink * basesink, + GstBuffer * buffer); +static gboolean gst_gigesimsink_unlock (GstBaseSink * basesink); +static gboolean gst_gigesimsink_unlock_stop (GstBaseSink * basesink); + +enum +{ + PROP_0, + PROP_TIMEOUT, + PROP_ADDRESS, + PROP_MANUFACTURER, + PROP_MODEL, + PROP_VERSION, + PROP_INFO, + PROP_SERIAL, + PROP_MAC +}; + +#define DEFAULT_PROP_TIMEOUT 10000 +#define DEFAULT_PROP_ADDRESS "" +#define DEFAULT_PROP_MANUFACTURER "A&B Software" +#define DEFAULT_PROP_MODEL "GigESim GStreamer" +#define DEFAULT_PROP_VERSION "0.1" +#define DEFAULT_PROP_INFO "A&B Soft GigESim GStreamer Sink" +#define DEFAULT_PROP_SERIAL "0001" +#define DEFAULT_PROP_MAC "AA-00-00-00-00-00" + +/* pad templates */ + +static GstStaticPadTemplate gst_gigesimsink_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE + ("{ GRAY8, GRAY16_LE, RGB, BGR, RGBA, BGRA, IYU1, IYU2, UYVY }")) + ); + +/* class initialization */ + +/* setup debug */ +GST_DEBUG_CATEGORY_STATIC (gigesimsink_debug); +#define GST_CAT_DEFAULT gigesimsink_debug + +G_DEFINE_TYPE (GstGigesimSink, gst_gigesimsink, GST_TYPE_BASE_SINK); + +static void +gst_gigesimsink_class_init (GstGigesimSinkClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass); + + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gigesimsink", 0, + "A&B Soft GigESim Camera Link simulator sink"); + + gobject_class->set_property = gst_gigesimsink_set_property; + gobject_class->get_property = gst_gigesimsink_get_property; + gobject_class->dispose = gst_gigesimsink_dispose; + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&gst_gigesimsink_sink_template)); + + gst_element_class_set_details_simple (gstelement_class, + "A&B Soft GigESim Sink", "Sink/Video", + "A&B Soft GigESim Sink to output GigE Vision video", + "Joshua M. Doe "); + + gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_gigesimsink_start); + gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_gigesimsink_stop); + gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_gigesimsink_set_caps); + gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_gigesimsink_render); + gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_gigesimsink_unlock); + gstbasesink_class->unlock_stop = + GST_DEBUG_FUNCPTR (gst_gigesimsink_unlock_stop); + + g_object_class_install_property (gobject_class, PROP_ADDRESS, + g_param_spec_string ("address", "IP address", + "The IP address of the network interface to bind to (default is first found)", + DEFAULT_PROP_ADDRESS, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY))); + + g_object_class_install_property (gobject_class, PROP_MANUFACTURER, + g_param_spec_string ("manufacturer", "Manufacturer", + "Manufacturer of the virtual camera", + DEFAULT_PROP_MANUFACTURER, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY))); + g_object_class_install_property (gobject_class, PROP_MODEL, + g_param_spec_string ("model", "Model", + "Model of the virtual camera", + DEFAULT_PROP_MODEL, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY))); + g_object_class_install_property (gobject_class, PROP_VERSION, + g_param_spec_string ("version", "Version", + "Version of the virtual camera", + DEFAULT_PROP_VERSION, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY))); + g_object_class_install_property (gobject_class, PROP_INFO, + g_param_spec_string ("info", "Info", + "Info of the virtual camera", + DEFAULT_PROP_INFO, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY))); + g_object_class_install_property (gobject_class, PROP_SERIAL, + g_param_spec_string ("serial", "Serial", + "Serial of the virtual camera", + DEFAULT_PROP_SERIAL, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY))); + g_object_class_install_property (gobject_class, PROP_MAC, + g_param_spec_string ("mac", "MAC address", + "MAC address of the virtual camera", + DEFAULT_PROP_MAC, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY))); +} + +bool +gst_gigesimsink_on_feature_write (void *context, const char *feature) +{ + GstGigesimSink *sink = GST_GIGESIMSINK (context); + GST_LOG_OBJECT (sink, "Feature written '%s'", feature); + if (g_strcmp0 (feature, "AcquisitionStart") == 0) { + g_mutex_lock (&sink->mutex); + sink->acquisition_started = TRUE; + g_cond_signal (&sink->cond); + g_mutex_unlock (&sink->mutex); + } else if (g_strcmp0 (feature, "AcquisitionStop") == 0) { + g_mutex_lock (&sink->mutex); + sink->acquisition_started = FALSE; + g_cond_signal (&sink->cond); + g_mutex_unlock (&sink->mutex); + } + return true; +} + +static void +gst_gigesimsink_init (GstGigesimSink * sink) +{ + /* properties */ + sink->timeout = DEFAULT_PROP_TIMEOUT; + sink->address = g_strdup (DEFAULT_PROP_ADDRESS); + sink->manufacturer = g_strdup (DEFAULT_PROP_MANUFACTURER); + sink->model = g_strdup (DEFAULT_PROP_MODEL); + sink->version = g_strdup (DEFAULT_PROP_VERSION); + sink->info = g_strdup (DEFAULT_PROP_INFO); + sink->serial = g_strdup (DEFAULT_PROP_SERIAL); + sink->mac = g_strdup (DEFAULT_PROP_MAC); + + sink->camera_connected = FALSE; + + sink->acquisition_started = FALSE; + sink->stop_requested = FALSE; + + sink->pCamera = createCamera (); + sink->pCamera->SetWriteCallback (sink, gst_gigesimsink_on_feature_write); + + g_mutex_init (&sink->mutex); + g_cond_init (&sink->cond); +} + +void +gst_gigesimsink_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstGigesimSink *sink; + + g_return_if_fail (GST_IS_GIGESIMSINK (object)); + sink = GST_GIGESIMSINK (object); + + switch (property_id) { + case PROP_TIMEOUT: + sink->timeout = g_value_get_int (value); + break; + case PROP_ADDRESS: + g_free (sink->address); + sink->address = g_strdup (g_value_get_string (value)); + break; + case PROP_MANUFACTURER: + g_free (sink->manufacturer); + sink->manufacturer = g_strdup (g_value_get_string (value)); + break; + case PROP_MODEL: + g_free (sink->model); + sink->model = g_strdup (g_value_get_string (value)); + break; + case PROP_VERSION: + g_free (sink->version); + sink->version = g_strdup (g_value_get_string (value)); + break; + case PROP_INFO: + g_free (sink->info); + sink->info = g_strdup (g_value_get_string (value)); + break; + case PROP_SERIAL: + g_free (sink->serial); + sink->serial = g_strdup (g_value_get_string (value)); + break; + case PROP_MAC: + g_free (sink->mac); + sink->mac = g_strdup (g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_gigesimsink_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstGigesimSink *sink; + + g_return_if_fail (GST_IS_GIGESIMSINK (object)); + sink = GST_GIGESIMSINK (object); + + switch (property_id) { + case PROP_TIMEOUT: + g_value_set_int (value, sink->timeout); + break; + case PROP_ADDRESS: + g_value_set_string (value, sink->address); + break; + case PROP_MANUFACTURER: + g_value_set_string (value, sink->manufacturer); + break; + case PROP_MODEL: + g_value_set_string (value, sink->model); + break; + case PROP_VERSION: + g_value_set_string (value, sink->version); + break; + case PROP_INFO: + g_value_set_string (value, sink->info); + break; + case PROP_SERIAL: + g_value_set_string (value, sink->serial); + break; + case PROP_MAC: + g_value_set_string (value, sink->mac); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_gigesimsink_dispose (GObject * object) +{ + GstGigesimSink *sink; + + g_return_if_fail (GST_IS_GIGESIMSINK (object)); + sink = GST_GIGESIMSINK (object); + + /* clean up as possible. may be called multiple times */ + if (sink->pCamera) { + delete sink->pCamera; + sink->pCamera = NULL; + } + + g_mutex_clear (&sink->mutex); + g_cond_clear (&sink->cond); + + g_free (sink->address); + + G_OBJECT_CLASS (gst_gigesimsink_parent_class)->dispose (object); +} + +gboolean +gst_gigesimsink_start (GstBaseSink * basesink) +{ + GstGigesimSink *sink = GST_GIGESIMSINK (basesink); + int ret = 0; + + GST_DEBUG_OBJECT (sink, "Starting"); + + sink->acquisition_started = FALSE; + sink->stop_requested = FALSE; + + return TRUE; +} + +gboolean +gst_gigesimsink_stop (GstBaseSink * basesink) +{ + GstGigesimSink *sink = GST_GIGESIMSINK (basesink); + + if (sink->pCamera) + sink->pCamera->Disconnect (); + + sink->camera_connected = FALSE; + + sink->acquisition_started = FALSE; + sink->stop_requested = FALSE; + + return TRUE; +} + +gboolean +gst_gigesimsink_set_caps (GstBaseSink * basesink, GstCaps * caps) +{ + GstGigesimSink *sink = GST_GIGESIMSINK (basesink); + + GST_DEBUG_OBJECT (sink, "Caps being set"); + + gst_video_info_from_caps (&sink->vinfo, caps); + + return TRUE; +} + +GstFlowReturn +gst_gigesimsink_render (GstBaseSink * basesink, GstBuffer * buffer) +{ + GstGigesimSink *sink = GST_GIGESIMSINK (basesink); + GstMapInfo minfo; + GST_LOG_OBJECT (sink, "Rendering buffer"); + gint64 end_time; + int ret; + + /* configure and connect virtual camera */ + if (!sink->camera_connected) { + GST_DEBUG_OBJECT (sink, "Setting video output to %dx%d", sink->vinfo.width, + sink->vinfo.height); + sink->pCamera->SetImageSize (sink->vinfo.width, sink->vinfo.height); + + switch (GST_VIDEO_INFO_FORMAT (&sink->vinfo)) { + case GST_VIDEO_FORMAT_GRAY8: + sink->pCamera->AddPixelFormat ("Mono8"); + sink->pCamera->SetPixelFormat ("Mono8"); + break; + case GST_VIDEO_FORMAT_GRAY16_LE: + sink->pCamera->AddPixelFormat ("Mono16"); + sink->pCamera->SetPixelFormat ("Mono16"); + break; + case GST_VIDEO_FORMAT_RGB: + sink->pCamera->AddPixelFormat ("RGB8"); + sink->pCamera->SetPixelFormat ("RGB8"); + break; + case GST_VIDEO_FORMAT_RGBA: + sink->pCamera->AddPixelFormat ("RGBa8"); + sink->pCamera->SetPixelFormat ("RGBa8"); + break; + case GST_VIDEO_FORMAT_BGR: + sink->pCamera->AddPixelFormat ("BGR8"); + sink->pCamera->SetPixelFormat ("BGR8"); + break; + case GST_VIDEO_FORMAT_BGRA: + sink->pCamera->AddPixelFormat ("BGRa8"); + sink->pCamera->SetPixelFormat ("BGRa8"); + break; + case GST_VIDEO_FORMAT_IYU1: + sink->pCamera->AddPixelFormat ("YUV411_8_UYYVYY"); + sink->pCamera->SetPixelFormat ("YUV411_8_UYYVYY"); + break; + case GST_VIDEO_FORMAT_IYU2: + sink->pCamera->AddPixelFormat ("YUV8_UYV"); + sink->pCamera->SetPixelFormat ("YUV8_UYV"); + break; + case GST_VIDEO_FORMAT_UYVY: + sink->pCamera->AddPixelFormat ("YUV422_8_UYVY"); + sink->pCamera->SetPixelFormat ("YUV422_8_UYVY"); + break; + default: + g_assert_not_reached (); + } + + ret = + sink->pCamera->SetDeviceInfo (sink->manufacturer, sink->model, + sink->version, sink->info, sink->serial); + if (ret) { + GST_ELEMENT_WARNING (sink, RESOURCE, FAILED, + ("Failed to set device info"), (NULL)); + return GST_FLOW_ERROR; + } + + ret = sink->pCamera->SetMacAddress (sink->mac); + if (ret) { + GST_ELEMENT_WARNING (sink, RESOURCE, FAILED, ("Failed to MAC address"), + (NULL)); + return GST_FLOW_ERROR; + } + + ret = sink->pCamera->SetTimerMode (CGevCamera::TIMER_MODE::TIMER_UNIX); + if (ret) { + GST_ELEMENT_WARNING (sink, RESOURCE, FAILED, ("Failed to timer mode"), + (NULL)); + return GST_FLOW_ERROR; + } + + if (g_strcmp0 (sink->address, "") == 0) { + char ipstr[16]; + GST_DEBUG_OBJECT (sink, "No address specified, using first found"); + ret = sink->pCamera->GetInterfaceAtIndex (0, ipstr); + if (ret) { + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, + ("No network interfaces available"), (NULL)); + return GST_FLOW_ERROR; + } + g_free (sink->address); + sink->address = g_strdup (ipstr); + } + + GST_DEBUG_OBJECT (sink, "Connecting to IP address %s", sink->address); + ret = sink->pCamera->Connect (sink->address); + + if (ret) { + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, + ("Unable to bind virtual camera to network interface"), (NULL)); + return GST_FLOW_ERROR; + } + + sink->camera_connected = TRUE; + } + + if (sink->stop_requested) { + GST_DEBUG_OBJECT (sink, "stop requested, flushing"); + return GST_FLOW_FLUSHING; + } + + /* wait for client to send AcquisitionStart command */ + g_mutex_lock (&sink->mutex); + end_time = g_get_monotonic_time () + sink->timeout * G_TIME_SPAN_MILLISECOND; + while (!sink->acquisition_started && !sink->stop_requested) { + GST_DEBUG_OBJECT (sink, "acq not started and stop not requested, waiting"); + if (!g_cond_wait_until (&sink->cond, &sink->mutex, end_time)) { + g_mutex_unlock (&sink->mutex); + GST_ELEMENT_WARNING (sink, RESOURCE, FAILED, + ("Timed out waiting for client to send AcquisitionStart, dropping frame"), + (NULL)); + return GST_FLOW_OK; + } + } + if (sink->stop_requested) { + GST_DEBUG_OBJECT (sink, "stop requested, flushing"); + g_mutex_unlock (&sink->mutex); + return GST_FLOW_FLUSHING; + } + g_mutex_unlock (&sink->mutex); + + /* we should already have AcquisitionStart, so this shouldn't block */ + sink->pCamera->LockFormat (); + + gst_buffer_map (buffer, &minfo, GST_MAP_READ); + /* TODO: fix stride? */ + ret = sink->pCamera->SendImage ((const char *) minfo.data); + if (ret) { + GST_ELEMENT_WARNING (sink, RESOURCE, FAILED, ("Failed to send image"), + (NULL)); + return GST_FLOW_ERROR; + } + gst_buffer_unmap (buffer, &minfo); + + return GST_FLOW_OK; +} + +gboolean +gst_gigesimsink_unlock (GstBaseSink * basesink) +{ + GstGigesimSink *sink = GST_GIGESIMSINK (basesink); + + g_mutex_lock (&sink->mutex); + sink->stop_requested = TRUE; + g_cond_signal (&sink->cond); + g_mutex_unlock (&sink->mutex); + + return TRUE; +} + +gboolean +gst_gigesimsink_unlock_stop (GstBaseSink * basesink) +{ + GstGigesimSink *sink = GST_GIGESIMSINK (basesink); + + sink->stop_requested = FALSE; + + return TRUE; +} + + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "gigesimsink", GST_RANK_NONE, + GST_TYPE_GIGESIMSINK)) { + return FALSE; + } + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + gigesim, + "A&B Soft GigESim elements", + plugin_init, GST_PACKAGE_VERSION, GST_PACKAGE_LICENSE, GST_PACKAGE_NAME, + GST_PACKAGE_ORIGIN) diff --git a/ext/gigesim/gstgigesim.h b/ext/gigesim/gstgigesim.h new file mode 100644 index 0000000..4902671 --- /dev/null +++ b/ext/gigesim/gstgigesim.h @@ -0,0 +1,70 @@ +/* GStreamer + * Copyright (C) 2011 FIXME + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GST_GIGESIM_H_ +#define _GST_GIGESIM_H_ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GIGESIMSINK (gst_gigesimsink_get_type()) +#define GST_GIGESIMSINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIGESIMSINK,GstGigesimSink)) +#define GST_GIGESIMSINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIGESIMSINK,GstGigesimSinkClass)) +#define GST_IS_GIGESIMSINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIGESIMSINK)) +#define GST_IS_GIGESIMSINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIGESIMSINK)) + +typedef struct _GstGigesimSink GstGigesimSink; +typedef struct _GstGigesimSinkClass GstGigesimSinkClass; + +struct _GstGigesimSink +{ + GstBaseSink base; + + CGevCamera* pCamera; + + gint timeout; + gchar *address; + gchar *manufacturer; + gchar *model; + gchar *version; + gchar *info; + gchar *serial; + gchar *mac; + + gboolean camera_connected; + GstVideoInfo vinfo; + + GMutex mutex; + GCond cond; + gboolean acquisition_started; + gboolean stop_requested; +}; + +struct _GstGigesimSinkClass +{ + GstBaseSinkClass base_class; +}; + +GType gst_gigesimsink_get_type (void); + +G_END_DECLS + +#endif /* _GST_GIGESIM_H_ */ \ No newline at end of file