diff --git a/CMakeLists.txt b/CMakeLists.txt index f4a8069..e114277 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,9 @@ macro_log_feature(FREEIMAGE_FOUND "FreeImage" "Required to build FreeImage plugi find_package(OpenCV) macro_log_feature(OPENCV_FOUND "OpenCV" "Required to build sensorfx plugin" "http://opencv.willowgarage.com/" FALSE) +find_package(EDT) +macro_log_feature(EDT_FOUND "EDT" "Required to build EDT PDV source element" "http://www.edt.com/" FALSE) + find_package(Euresys) macro_log_feature(EURESYS_FOUND "Euresys" "Required to build Euresys source element" "http://www.euresys.com/" FALSE) diff --git a/sys/CMakeLists.txt b/sys/CMakeLists.txt index 89cb69a..76671d2 100644 --- a/sys/CMakeLists.txt +++ b/sys/CMakeLists.txt @@ -1,3 +1,7 @@ +if (EDT_FOUND) + add_subdirectory(edt) +endif (EDT_FOUND) + if (EURESYS_FOUND) add_subdirectory (euresys) endif (EURESYS_FOUND) diff --git a/sys/edt/gstedt.c b/sys/edt/gstedt.c new file mode 100644 index 0000000..ee586cc --- /dev/null +++ b/sys/edt/gstedt.c @@ -0,0 +1,28 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstedtpdvsink.h" + +#define GST_CAT_DEFAULT gst_gstedt_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "edt", 0, + "debug category for EDT elements"); + + if (!gst_element_register (plugin, "edtpdvsink", GST_RANK_NONE, + GST_TYPE_EDT_PDV_SINK)) { + return FALSE; + } + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "edt", + "EDT PDV elements", + plugin_init, VERSION, "LGPL", PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/sys/edt/gstedtpdvsink.c b/sys/edt/gstedtpdvsink.c new file mode 100644 index 0000000..307d882 --- /dev/null +++ b/sys/edt/gstedtpdvsink.c @@ -0,0 +1,349 @@ +/* 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-gstedtpdvsink + * + * The edtpdvsink element is a sink for Camera Link simulators supported by the EDT PDV driver. + * + * + * Example launch line + * |[ + * gst-launch -v videotestsrc ! ffmpegcolorspace ! edtpdvsink + * ]| + * Outputs test video on the default EDT Camera Link channel. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include + +#include "gstedtpdvsink.h" + +/* GObject prototypes */ +static void gst_edt_pdv_sink_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec); +static void gst_edt_pdv_sink_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec); +static void gst_edt_pdv_sink_dispose (GObject * object); +static void gst_edt_pdv_sink_finalize (GObject * object); + +/* GstBaseSink prototypes */ +static gboolean gst_edt_pdv_sink_start (GstBaseSink * basesink); +static gboolean gst_edt_pdv_sink_stop (GstBaseSink * basesink); +static GstCaps *gst_edt_pdv_sink_get_caps (GstBaseSink * basesink); +static gboolean gst_edt_pdv_sink_set_caps (GstBaseSink * basesink, + GstCaps * caps); +static GstFlowReturn gst_edt_pdv_sink_render (GstBaseSink * basesink, + GstBuffer * buffer); + +enum +{ + PROP_0 + /* FILL ME */ +}; + + +/* pad templates */ + +static GstStaticPadTemplate gst_edt_pdv_sink_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_GRAY8) + ); + +/* class initialization */ + +/* setup debug */ +GST_DEBUG_CATEGORY_STATIC (edtpdvsink_debug); +#define GST_CAT_DEFAULT edtpdvsink_debug +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "edtpdvsink", 0, \ + "EDT PDV Camera Link simulator sink"); + +GST_BOILERPLATE_FULL (GstEdtPdvSink, gst_edt_pdv_sink, GstBaseSink, + GST_TYPE_BASE_SINK, DEBUG_INIT); + +static void +gst_edt_pdv_sink_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_edt_pdv_sink_sink_template)); + + gst_element_class_set_details_simple (element_class, + "EDT PDV Sink", "Sink/Video", + "EDT PDV Sink for Camera Link simulator boards", + "Joshua M. Doe "); +} + +static void +gst_edt_pdv_sink_class_init (GstEdtPdvSinkClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstBaseSinkClass *base_sink_class = GST_BASE_SINK_CLASS (klass); + + gobject_class->set_property = gst_edt_pdv_sink_set_property; + gobject_class->get_property = gst_edt_pdv_sink_get_property; + gobject_class->dispose = gst_edt_pdv_sink_dispose; + gobject_class->finalize = gst_edt_pdv_sink_finalize; + + base_sink_class->start = gst_edt_pdv_sink_start; + base_sink_class->stop = gst_edt_pdv_sink_stop; + base_sink_class->set_caps = gst_edt_pdv_sink_set_caps; + base_sink_class->get_caps = gst_edt_pdv_sink_get_caps; + base_sink_class->render = gst_edt_pdv_sink_render; +} + +static void +gst_edt_pdv_sink_init (GstEdtPdvSink * pdvsink, + GstEdtPdvSinkClass * pdvsink_class) +{ + pdvsink->dev = NULL; + pdvsink->buffers = NULL; + pdvsink->n_buffers = 2; + pdvsink->cur_buffer = 0; + + /* TODO: put these in properties */ + pdvsink->unit = 0; + pdvsink->channel = 0; +} + +void +gst_edt_pdv_sink_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstEdtPdvSink *pdvsink; + + g_return_if_fail (GST_IS_EDT_PDV_SINK (object)); + pdvsink = GST_EDT_PDV_SINK (object); + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_edt_pdv_sink_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstEdtPdvSink *pdvsink; + + g_return_if_fail (GST_IS_EDT_PDV_SINK (object)); + pdvsink = GST_EDT_PDV_SINK (object); + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_edt_pdv_sink_dispose (GObject * object) +{ + GstEdtPdvSink *pdvsink; + + g_return_if_fail (GST_IS_EDT_PDV_SINK (object)); + pdvsink = GST_EDT_PDV_SINK (object); + + /* clean up as possible. may be called multiple times */ + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +void +gst_edt_pdv_sink_finalize (GObject * object) +{ + GstEdtPdvSink *pdvsink; + + g_return_if_fail (GST_IS_EDT_PDV_SINK (object)); + pdvsink = GST_EDT_PDV_SINK (object); + + /* clean up object here */ + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +gboolean +gst_edt_pdv_sink_start (GstBaseSink * basesink) +{ + GstEdtPdvSink *pdvsink = GST_EDT_PDV_SINK (basesink); + + GST_DEBUG_OBJECT (pdvsink, "Starting"); + + pdvsink->dev = pdv_open_channel ("pdv", pdvsink->unit, pdvsink->channel); + if (pdvsink->dev == NULL) { + GST_ELEMENT_ERROR (pdvsink, RESOURCE, OPEN_WRITE, + ("Unable to open unit %d, channel %d", pdvsink->unit, pdvsink->channel), + (NULL)); + return FALSE; + } + + if (!pdv_is_simulator (pdvsink->dev)) { + GST_ELEMENT_ERROR (pdvsink, RESOURCE, OPEN_WRITE, + ("EDT unit is not a simulator."), (NULL)); + pdv_close (pdvsink->dev); + } + + /* FIXME: set timeout to wait forever, shouldn't do this of course */ + edt_set_wtimeout (pdvsink->dev, 0); + edt_set_rtimeout (pdvsink->dev, 0); + + pdv_flush_fifo (pdvsink->dev); + + /* turn off counter data so we can DMA our own image data */ + pdv_cls_set_datacnt (pdvsink->dev, 0); + + pdvsink->cur_buffer = 0; + + return TRUE; +} + +gboolean +gst_edt_pdv_sink_stop (GstBaseSink * basesink) +{ + GstEdtPdvSink *pdvsink = GST_EDT_PDV_SINK (basesink); + + if (pdvsink->dev) + pdv_close (pdvsink->dev); + + return TRUE; +} + +GstCaps * +gst_edt_pdv_sink_get_caps (GstBaseSink * basesink) +{ + GstEdtPdvSink *pdvsink = GST_EDT_PDV_SINK (basesink); + int width, height, depth; + GstVideoFormat format; + + if (!pdvsink->dev) { + return gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD + (pdvsink))); + } + + width = pdv_get_width (pdvsink->dev); + height = pdv_get_height (pdvsink->dev); + depth = pdv_get_depth (pdvsink->dev); + + switch (depth) { + case 8: + format = GST_VIDEO_FORMAT_GRAY8; + break; + case 16: + /* TODO: will this be host order or always one of BE/LE? */ + format = GST_VIDEO_FORMAT_GRAY16_BE; + break; + default: + format = GST_VIDEO_FORMAT_UNKNOWN; + } + + return gst_video_format_new_caps (format, width, height, 30, 1, 1, 1); +} + +gboolean +gst_edt_pdv_sink_set_caps (GstBaseSink * basesink, GstCaps * caps) +{ + GstEdtPdvSink *pdvsink = GST_EDT_PDV_SINK (basesink); + GstVideoFormat format; + int width, height, depth; + int buffer_size; + int depth_bytes; + int taps; + + GST_DEBUG_OBJECT (pdvsink, "Caps being set"); + + gst_video_format_parse_caps (caps, &format, &width, &height); + + switch (format) { + case GST_VIDEO_FORMAT_GRAY8: + depth = 8; + depth_bytes = 1; + break; + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_GRAY16_LE: + depth = 16; + depth_bytes = 2; + break; + default: + GST_ERROR_OBJECT (pdvsink, "Unsupported video format"); + return FALSE; + } + + buffer_size = height * pdv_bytes_per_line (width, depth); + + GST_DEBUG_OBJECT (pdvsink, + "Configuring EDT ring buffer with %d buffers each of size %d", + pdvsink->n_buffers, buffer_size); + + /* we'll use just two buffers and ping pong between them */ + edt_configure_ring_buffers (pdvsink->dev, buffer_size, pdvsink->n_buffers, + EDT_WRITE, NULL); + + pdvsink->buffers = edt_buffer_addresses (pdvsink->dev); + + taps = pdvsink->dev->dd_p->cls.taps; + + /* TODO: handle RGB correctly */ + if (depth_bytes == 3) { + taps = 1; + depth_bytes = 4; + } + + if (taps == 0) { + GST_WARNING_OBJECT (pdvsink, "Taps set to 0, changing to 1"); + taps = 1; + } + + GST_DEBUG_OBJECT (pdvsink, "Configuring simulator with %d taps", taps); + + /* configure simulator */ + pdv_cls_set_size (pdvsink->dev, taps, depth, width, height, PDV_CLS_DEFAULT_HGAP, (width / taps) + PDV_CLS_DEFAULT_HGAP, // taps=1 + PDV_CLS_DEFAULT_VGAP, height + PDV_CLS_DEFAULT_VGAP); + + GST_DEBUG ("Configured simulator"); + + return TRUE; +} + +GstFlowReturn +gst_edt_pdv_sink_render (GstBaseSink * basesink, GstBuffer * buffer) +{ + GstEdtPdvSink *pdvsink = GST_EDT_PDV_SINK (basesink); + + GST_LOG_OBJECT (pdvsink, "Rendering buffer"); + + memcpy (pdvsink->buffers[pdvsink->cur_buffer], GST_BUFFER_DATA (buffer), + GST_BUFFER_SIZE (buffer)); + edt_start_buffers (pdvsink->dev, 1); + pdvsink->cur_buffer = (pdvsink->cur_buffer + 1) % pdvsink->n_buffers; + + return GST_FLOW_OK; +} diff --git a/sys/edt/gstedtpdvsink.h b/sys/edt/gstedtpdvsink.h new file mode 100644 index 0000000..da36ff7 --- /dev/null +++ b/sys/edt/gstedtpdvsink.h @@ -0,0 +1,59 @@ +/* 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_EDT_PDV_SINK_H_ +#define _GST_EDT_PDV_SINK_H_ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_EDT_PDV_SINK (gst_edt_pdv_sink_get_type()) +#define GST_EDT_PDV_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_EDT_PDV_SINK,GstEdtPdvSink)) +#define GST_EDT_PDV_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_EDT_PDV_SINK,GstEdtPdvSinkClass)) +#define GST_IS_EDT_PDV_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EDT_PDV_SINK)) +#define GST_IS_EDT_PDV_SINK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EDT_PDV_SINK)) + +typedef struct _GstEdtPdvSink GstEdtPdvSink; +typedef struct _GstEdtPdvSinkClass GstEdtPdvSinkClass; + +struct _GstEdtPdvSink +{ + GstBaseSink base; + + PdvDev *dev; + int unit; + int channel; + + unsigned char **buffers; + int n_buffers; + int cur_buffer; +}; + +struct _GstEdtPdvSinkClass +{ + GstBaseSinkClass base_class; +}; + +GType gst_edt_pdv_sink_get_type (void); + +G_END_DECLS + +#endif /* _GST_EDT_PDV_SINK_H_ */ \ No newline at end of file diff --git a/vs2010/edt/edt.vcxproj b/vs2010/edt/edt.vcxproj new file mode 100644 index 0000000..c48b4cd --- /dev/null +++ b/vs2010/edt/edt.vcxproj @@ -0,0 +1,83 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {351947AF-6445-4644-987D-FFE4FDDD3B4C} + edt + + + + DynamicLibrary + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + + + + + Level3 + Disabled + $(SolutionDir)\..;C:\EDT\pdv;%(AdditionalIncludeDirectories) + HAVE_CONFIG_H;_MBCS;%(PreprocessorDefinitions) + + + true + C:\EDT\pdv;%(AdditionalLibraryDirectories) + pdvlib.lib;gstvideo-0.10.lib;%(AdditionalDependencies) + + + + + Level3 + MaxSpeed + true + true + $(SolutionDir)\..;C:\EDT\pdv;%(AdditionalIncludeDirectories) + HAVE_CONFIG_H;_MBCS;%(PreprocessorDefinitions) + + + true + true + true + C:\EDT\pdv;%(AdditionalLibraryDirectories) + pdvlib.lib;gstvideo-0.10.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vs2010/edt/edt.vcxproj.filters b/vs2010/edt/edt.vcxproj.filters new file mode 100644 index 0000000..faaf338 --- /dev/null +++ b/vs2010/edt/edt.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/vs2010/gst-plugins-vision.sln b/vs2010/gst-plugins-vision.sln index 5d0670f..8e057ad 100644 --- a/vs2010/gst-plugins-vision.sln +++ b/vs2010/gst-plugins-vision.sln @@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "videoadjust", "videoadjust\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "phoenix", "phoenix\phoenix.vcxproj", "{55049618-6388-411C-818C-9140D6F8CE99}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "edt", "edt\edt.vcxproj", "{351947AF-6445-4644-987D-FFE4FDDD3B4C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -25,6 +27,10 @@ Global {55049618-6388-411C-818C-9140D6F8CE99}.Debug|Win32.Build.0 = Debug|Win32 {55049618-6388-411C-818C-9140D6F8CE99}.Release|Win32.ActiveCfg = Release|Win32 {55049618-6388-411C-818C-9140D6F8CE99}.Release|Win32.Build.0 = Release|Win32 + {351947AF-6445-4644-987D-FFE4FDDD3B4C}.Debug|Win32.ActiveCfg = Debug|Win32 + {351947AF-6445-4644-987D-FFE4FDDD3B4C}.Debug|Win32.Build.0 = Debug|Win32 + {351947AF-6445-4644-987D-FFE4FDDD3B4C}.Release|Win32.ActiveCfg = Release|Win32 + {351947AF-6445-4644-987D-FFE4FDDD3B4C}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE