diff options
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | ext/opencv/Makefile.am | 7 | ||||
-rw-r--r-- | ext/opencv/gsthanddetect.c | 220 | ||||
-rw-r--r-- | ext/opencv/gsthanddetect.h | 22 | ||||
-rw-r--r-- | ext/opencv/gstopencv.c | 4 | ||||
-rw-r--r-- | tests/examples/opencv/Makefile.am | 7 | ||||
-rw-r--r-- | tests/examples/opencv/gsthanddetect_test.c | 339 |
7 files changed, 261 insertions, 342 deletions
diff --git a/configure.ac b/configure.ac index 89a967dcb..67a341c37 100644 --- a/configure.ac +++ b/configure.ac @@ -33,6 +33,10 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])], [AM_DEFAULT_VERBOSITY=1 AC_SUBST(AM_DEFAULT_VERBOSITY)]) +dnl define GST_DATADIR +AS_AC_EXPAND(DATADIR, $datadir) +AC_DEFINE_UNQUOTED(GST_DATADIR, "$DATADIR", [data dir]) + dnl our libraries and install dirs use GST_API_VERSION in the filename dnl to allow side-by-side installation of different API versions GST_API_VERSION=1.0 diff --git a/ext/opencv/Makefile.am b/ext/opencv/Makefile.am index c02037b22..4bcc78ed2 100644 --- a/ext/opencv/Makefile.am +++ b/ext/opencv/Makefile.am @@ -14,6 +14,7 @@ libgstopencv_la_SOURCES = gstopencv.c \ gstedgedetect.c \ gstfaceblur.c \ gstfacedetect.c \ + gsthanddetect.c \ gstpyramidsegment.c \ gsttemplatematch.c \ gsttextoverlay.c \ @@ -50,9 +51,15 @@ noinst_HEADERS = gstopencvvideofilter.h gstopencvutils.h \ gstedgedetect.h \ gstfaceblur.h \ gstfacedetect.h \ + gsthanddetect.h \ gstpyramidsegment.h \ gsttemplatematch.h \ gsttextoverlay.h \ gstmotioncells.h \ motioncells_wrapper.h \ MotionCells.h + +opencv_haarcascadesdir = $(datadir)/gstreamer-$(GST_API_VERSION)/opencv_haarcascades +opencv_haarcascades_DATA = fist.xml palm.xml + +EXTRA_DIST = $(opencv_haarcascades_DATA) diff --git a/ext/opencv/gsthanddetect.c b/ext/opencv/gsthanddetect.c index 223a18595..57885c7ba 100644 --- a/ext/opencv/gsthanddetect.c +++ b/ext/opencv/gsthanddetect.c @@ -1,6 +1,7 @@ /* * GStreamer hand gesture detection plugins * Copyright (C) 2012 Andol Li <<andol@andol.info>> + * Copyright (C) 2013 Sreerenj Balachandran <sreerenj.balachandran@intel.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -49,8 +50,8 @@ * <refsect2> * <title>Example launch line</title> * |[ - * gst-launch autovideosrc ! ffmpegcolorspace ! "video/x-raw-rgb, width=320, height=240" ! \ - videoscale ! handdetect ! ffmpegcolorspace ! xvimagesink + * gst-launch autovideosrc ! videoconvert ! "video/x-raw, formt=RGB, width=320, height=240" ! \ + videoscale ! handdetect ! videoconvert ! xvimagesink * ]| * </refsect2> */ @@ -58,23 +59,18 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif -/* interfaces */ -#include <gst/interfaces/navigation.h> + /* element header */ #include "gsthanddetect.h" -/* gst */ -#include <gst/gst.h> -#include <gst/video/video.h> #include "gstopencvutils.h" -/* debugging */ -#include <gst/gstinfo.h> GST_DEBUG_CATEGORY_STATIC (gst_handdetect_debug); #define GST_CAT_DEFAULT gst_handdetect_debug /* define HAAR files */ -#define HAAR_FILE_FIST "/usr/local/share/opencv/haarcascades/fist.xml" -#define HAAR_FILE_PALM "/usr/local/share/opencv/haarcascades/palm.xml" +#define HAAR_CASCADES_DIR GST_DATADIR "/gstreamer-"GST_API_VERSION"/opencv_haarcascades/" +#define HAAR_FILE_FIST HAAR_CASCADES_DIR "fist.xml" +#define HAAR_FILE_PALM HAAR_CASCADES_DIR "palm.xml" /* Filter signals and args */ enum @@ -99,12 +95,12 @@ enum static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB) + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB")) ); static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB) + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("RGB")) ); static void gst_handdetect_set_property (GObject * object, guint prop_id, @@ -119,60 +115,22 @@ static GstFlowReturn gst_handdetect_transform_ip (GstOpencvVideoFilter * static void gst_handdetect_load_profile (GstHanddetect * filter); -static void gst_handdetect_init_interfaces (GType type); -static void -gst_handdetect_implements_interface_init (GstImplementsInterfaceClass * klass); -static void gst_handdetect_navigation_interface_init (gpointer g_iface, - gpointer iface_data); -static gboolean gst_handdetect_interface_supported (GstImplementsInterface * - iface, GType type); +static void gst_handdetect_navigation_interface_init (GstNavigationInterface * + iface); static void gst_handdetect_navigation_send_event (GstNavigation * navigation, GstStructure * structure); -static gboolean gst_handdetect_handle_pad_event (GstPad * pad, - GstEvent * event); -GST_BOILERPLATE_FULL (GstHanddetect, gst_handdetect, GstOpencvVideoFilter, - GST_TYPE_OPENCV_VIDEO_FILTER, gst_handdetect_init_interfaces); +G_DEFINE_TYPE_WITH_CODE (GstHanddetect, gst_handdetect, + GST_TYPE_OPENCV_VIDEO_FILTER, + G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION, + gst_handdetect_navigation_interface_init);); static void -gst_handdetect_init_interfaces (GType type) +gst_handdetect_navigation_interface_init (GstNavigationInterface * iface) { - static const GInterfaceInfo iface_info = { - (GInterfaceInitFunc) gst_handdetect_implements_interface_init, - NULL, - NULL, - }; - g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, - &iface_info); - static const GInterfaceInfo navigation_info = { - (GInterfaceInitFunc) gst_handdetect_navigation_interface_init, - NULL, - NULL, - }; - g_type_add_interface_static (type, GST_TYPE_NAVIGATION, &navigation_info); -} - -static void -gst_handdetect_navigation_interface_init (gpointer g_iface, gpointer iface_data) -{ - GstNavigationInterface *iface = (GstNavigationInterface *) g_iface; iface->send_event = gst_handdetect_navigation_send_event; } -static gboolean -gst_handdetect_interface_supported (GstImplementsInterface * iface, GType type) -{ - if (type == GST_TYPE_NAVIGATION) - return TRUE; - return FALSE; -} - -static void -gst_handdetect_implements_interface_init (GstImplementsInterfaceClass * klass) -{ - klass->supported = gst_handdetect_interface_supported; -} - /* FIXME: this function used to parse the region of interests coordinates * sending from applications when the hand gestures reach the defined regions of interests, * at this moment this function is not doing anything significantly @@ -193,60 +151,9 @@ gst_handdetect_navigation_send_event (GstNavigation * navigation, } } -/* handle element pad event */ -/* no PRACTICAL USE at the moment - * this function is used to debug the fist-move/palm-move event - * will CHANGE in the future - */ -static gboolean -gst_handdetect_handle_pad_event (GstPad * pad, GstEvent * event) -{ - const GstStructure *s = gst_event_get_structure (event); - const gchar *name = gst_structure_get_string (s, "event"); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - break; - case GST_EVENT_NAVIGATION:{ - if (g_str_equal (name, "fist-move")) { - GST_DEBUG_OBJECT (GST_HANDDETECT (gst_pad_get_parent (pad)), - "Fist-move event\n "); - uint x, y; - gst_structure_get_uint (s, "x", &x); - gst_structure_get_uint (s, "y", &y); - GST_DEBUG_OBJECT (GST_HANDDETECT (gst_pad_get_parent (pad)), - "Fist Pos:[%d, %d]\n", x, y); - } else if (g_str_equal (name, "palm-move")) { - GST_DEBUG_OBJECT (GST_HANDDETECT (gst_pad_get_parent (pad)), - "Palm-move event\n "); - uint x, y; - gst_structure_get_uint (s, "x", &x); - gst_structure_get_uint (s, "y", &y); - GST_DEBUG_OBJECT (GST_HANDDETECT (gst_pad_get_parent (pad)), - "Palm Pos:[%d, %d]\n", x, y); - } else if (g_str_equal (name, "mouse-move")) { - gdouble x, y; - gst_structure_get_double (s, "pointer_x", &x); - gst_structure_get_double (s, "pointer_y", &y); - GST_DEBUG_OBJECT (GST_HANDDETECT (gst_pad_get_parent (pad)), - "Mouse-move [%f, %f]\n", x, y); - } else if (g_str_equal (name, "mouse-button-press")) { - GST_DEBUG ("Mouse botton press\n"); - } else if (g_str_equal (name, "mouse-button-release")) { - GST_DEBUG_OBJECT (GST_HANDDETECT (gst_pad_get_parent (pad)), - "Mouse button release\n"); - } - break; - } - default: - break; - } - return gst_pad_event_default (pad, event); -} - /* clean opencv images and parameters */ static void -gst_handdetect_finalise (GObject * obj) +gst_handdetect_finalize (GObject * obj) { GstHanddetect *filter = GST_HANDDETECT (obj); @@ -257,23 +164,7 @@ gst_handdetect_finalise (GObject * obj) g_free (filter->profile_fist); g_free (filter->profile_palm); - G_OBJECT_CLASS (parent_class)->finalize (obj); -} - -/* GObject vmethod implementations */ -static void -gst_handdetect_base_init (gpointer gclass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_set_details_simple (element_class, - "hand detect", - "Filter/Effect/Video", - "Performs hand gesture detection on videos, providing detected hand positions via bus message and navigation event, and deals with hand gesture events", - "Andol Li <<andol@andol.info>>"); - - gst_element_class_add_static_pad_template (element_class, &src_factory); - gst_element_class_add_static_pad_template (element_class, &sink_factory); + G_OBJECT_CLASS (gst_handdetect_parent_class)->finalize (obj); } /* initialise the HANDDETECT class */ @@ -283,13 +174,14 @@ gst_handdetect_class_init (GstHanddetectClass * klass) GObjectClass *gobject_class; GstOpencvVideoFilterClass *gstopencvbasefilter_class; + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); gobject_class = (GObjectClass *) klass; gstopencvbasefilter_class = (GstOpencvVideoFilterClass *) klass; gstopencvbasefilter_class->cv_trans_ip_func = gst_handdetect_transform_ip; gstopencvbasefilter_class->cv_set_caps = gst_handdetect_set_caps; - gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_handdetect_finalise); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_handdetect_finalize); gobject_class->set_property = gst_handdetect_set_property; gobject_class->get_property = gst_handdetect_get_property; @@ -342,6 +234,18 @@ gst_handdetect_class_init (GstHanddetectClass * klass) "HEIGHT of left-top pointer in region of interest \nGestures in the defined region of interest will emit messages", 0, UINT_MAX, 0, G_PARAM_READWRITE) ); + + gst_element_class_set_static_metadata (element_class, + "handdetect", + "Filter/Effect/Video", + "Performs hand gesture detection on videos, providing detected hand positions via bus message and navigation event, and deals with hand gesture events", + "Andol Li <andol@andol.info>"); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); + } /* initialise the new element @@ -350,13 +254,8 @@ gst_handdetect_class_init (GstHanddetectClass * klass) * initialise instance structure */ static void -gst_handdetect_init (GstHanddetect * filter, GstHanddetectClass * gclass) +gst_handdetect_init (GstHanddetect * filter) { - GstBaseTransform *trans = GST_BASE_TRANSFORM_CAST (filter); - - gst_pad_set_event_function (trans->srcpad, - GST_DEBUG_FUNCPTR (gst_handdetect_handle_pad_event)); - filter->profile_fist = g_strdup (HAAR_FILE_FIST); filter->profile_palm = g_strdup (HAAR_FILE_PALM); filter->roi_x = 0; @@ -481,13 +380,17 @@ gst_handdetect_transform_ip (GstOpencvVideoFilter * transform, GstBuffer * buffer, IplImage * img) { GstHanddetect *filter = GST_HANDDETECT (transform); + GstMapInfo info; CvSeq *hands; CvRect *r; GstStructure *s; GstMessage *m; int i; - filter->cvImage->imageData = (char *) GST_BUFFER_DATA (buffer); + buffer = gst_buffer_make_writable (buffer); + gst_buffer_map (buffer, &info, GST_MAP_READWRITE); + + filter->cvImage->imageData = (char *) info.data; /* 320 x 240 is with the best detect accuracy, if not, give info */ if (filter->cvImage->width != 320 || filter->cvImage->height != 240) GST_INFO_OBJECT (filter, @@ -511,6 +414,9 @@ gst_handdetect_transform_ip (GstOpencvVideoFilter * transform, /* if FIST gesture detected */ if (hands && hands->total > 0) { + int min_distance, distance; + CvRect temp_r; + CvPoint c; /* set frame buffer writable */ if (filter->display) { buffer = gst_buffer_make_writable (buffer); @@ -522,15 +428,15 @@ gst_handdetect_transform_ip (GstOpencvVideoFilter * transform, * best_r => best hand in this frame */ /* set min_distance for init comparison */ - int min_distance = filter->cvImage->width + filter->cvImage->height; + min_distance = filter->cvImage->width + filter->cvImage->height; /* Init filter->prev_r */ - CvRect temp_r = cvRect (0, 0, 0, 0); + temp_r = cvRect (0, 0, 0, 0); if (filter->prev_r == NULL) filter->prev_r = &temp_r; /* Get the best FIST gesture */ for (i = 0; i < (hands ? hands->total : 0); i++) { r = (CvRect *) cvGetSeqElem (hands, i); - int distance = (int) sqrt (pow ((r->x - filter->prev_r->x), + distance = (int) sqrt (pow ((r->x - filter->prev_r->x), 2) + pow ((r->y - filter->prev_r->y), 2)); if (distance <= min_distance) { min_distance = distance; @@ -541,8 +447,7 @@ gst_handdetect_transform_ip (GstOpencvVideoFilter * transform, filter->prev_r = (CvRect *) filter->best_r; /* send msg to app/bus if the detected gesture falls in the region of interest */ /* get center point of gesture */ - CvPoint c = - cvPoint (filter->best_r->x + filter->best_r->width / 2, + c = cvPoint (filter->best_r->x + filter->best_r->width / 2, filter->best_r->y + filter->best_r->height / 2); /* send message: * if the center point is in the region of interest, OR, @@ -602,6 +507,9 @@ gst_handdetect_transform_ip (GstOpencvVideoFilter * transform, ); /* if PALM detected */ if (hands && hands->total > 0) { + int min_distance, distance; + CvRect temp_r; + CvPoint c; /* set frame buffer writable */ if (filter->display) { buffer = gst_buffer_make_writable (buffer); @@ -613,15 +521,15 @@ gst_handdetect_transform_ip (GstOpencvVideoFilter * transform, * best_r => best hand in this frame */ /* suppose a min_distance for init comparison */ - int min_distance = filter->cvImage->width + filter->cvImage->height; + min_distance = filter->cvImage->width + filter->cvImage->height; /* Init filter->prev_r */ - CvRect temp_r = cvRect (0, 0, 0, 0); + temp_r = cvRect (0, 0, 0, 0); if (filter->prev_r == NULL) filter->prev_r = &temp_r; /* Get the best PALM gesture */ for (i = 0; i < (hands ? hands->total : 0); i++) { r = (CvRect *) cvGetSeqElem (hands, i); - int distance = (int) sqrt (pow ((r->x - filter->prev_r->x), + distance = (int) sqrt (pow ((r->x - filter->prev_r->x), 2) + pow ((r->y - filter->prev_r->y), 2)); if (distance <= min_distance) { min_distance = distance; @@ -633,8 +541,7 @@ gst_handdetect_transform_ip (GstOpencvVideoFilter * transform, /* send msg to app/bus if the detected gesture falls in the region of interest */ /* get center point of gesture */ - CvPoint c = - cvPoint (filter->best_r->x + filter->best_r->width / 2, + c = cvPoint (filter->best_r->x + filter->best_r->width / 2, filter->best_r->y + filter->best_r->height / 2); /* send message: * if the center point is in the region of interest, OR, @@ -700,7 +607,7 @@ gst_handdetect_transform_ip (GstOpencvVideoFilter * transform, } } } - + gst_buffer_unmap (buffer, &info); /* Push out the incoming buffer */ return GST_FLOW_OK; } @@ -731,7 +638,7 @@ gst_handdetect_load_profile (GstHanddetect * filter) * Initialize the plug-in itself * Register the element factories and other features */ -static gboolean +gboolean gst_handdetect_plugin_init (GstPlugin * plugin) { GST_DEBUG_CATEGORY_INIT (gst_handdetect_debug, @@ -741,22 +648,3 @@ gst_handdetect_plugin_init (GstPlugin * plugin) return gst_element_register (plugin, "handdetect", GST_RANK_NONE, GST_TYPE_HANDDETECT); } - -/* PACKAGE: this is usually set by autotools depending on some _INIT macro - * in configure.ac and then written into and defined in config.h, but we can - * just set it ourselves here in case someone doesn't use autotools to - * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined. - */ -#ifndef PACKAGE -#define PACKAGE "gst_handdetect" -#endif - -/* - * Gstreamer looks for this structure to register handdetect - */ -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "handdetect", - "Detect hand gestures for media operations", - gst_handdetect_plugin_init, VERSION, "LGPL", "GStreamer", - "http://gstreamer.net/") diff --git a/ext/opencv/gsthanddetect.h b/ext/opencv/gsthanddetect.h index 1d4a6831d..9fb69a6a1 100644 --- a/ext/opencv/gsthanddetect.h +++ b/ext/opencv/gsthanddetect.h @@ -1,8 +1,7 @@ /* * GStreamer - * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org> - * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net> * Copyright (C) 2012 andol li <<andol@andol.info>> + * Copyright (c) 2013 Sreerenj Balachandran <sreerenj.balachandran@intel.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -46,20 +45,15 @@ #ifndef __GST_HANDDETECT_H__ #define __GST_HANDDETECT_H__ -#ifndef VERSION -#define VERSION "0.10.36" /* for GST_PLUGIN_DEFINE use */ -#endif - -#include <math.h> -#include <string.h> -#include <stdlib.h> #include <gst/gst.h> -#include <gst/video/gstvideofilter.h> +#include <gst/video/video.h> +#include <gst/video/navigation.h> + #include "gstopencvvideofilter.h" /* opencv */ -#include <opencv/cv.h> -#include <opencv/cxcore.h> -#include <opencv/highgui.h> +#include <cv.h> +#include <cxcore.h> +#include <highgui.h> #if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 2) #include <opencv2/objdetect/objdetect.hpp> #endif @@ -113,5 +107,7 @@ struct _GstHanddetectClass GType gst_handdetect_get_type (void); +gboolean gst_handdetect_plugin_init (GstPlugin * plugin); + G_END_DECLS #endif /* __GST_HANDDETECT_H__ */ diff --git a/ext/opencv/gstopencv.c b/ext/opencv/gstopencv.c index afcdb41ab..289192240 100644 --- a/ext/opencv/gstopencv.c +++ b/ext/opencv/gstopencv.c @@ -36,6 +36,7 @@ #include "gstpyramidsegment.h" #include "gsttemplatematch.h" #include "gsttextoverlay.h" +#include "gsthanddetect.h" static gboolean plugin_init (GstPlugin * plugin) @@ -79,6 +80,9 @@ plugin_init (GstPlugin * plugin) if (!gst_opencv_text_overlay_plugin_init (plugin)) return FALSE; + if (!gst_handdetect_plugin_init (plugin)) + return FALSE; + return TRUE; } diff --git a/tests/examples/opencv/Makefile.am b/tests/examples/opencv/Makefile.am index 4241e9e57..9db9da4bb 100644 --- a/tests/examples/opencv/Makefile.am +++ b/tests/examples/opencv/Makefile.am @@ -1,11 +1,16 @@ -noinst_PROGRAMS = gstmotioncells_dynamic_test +noinst_PROGRAMS = gstmotioncells_dynamic_test \ + gsthanddetect_test gstmotioncells_dynamic_test_SOURCES = \ gstmotioncells_dynamic_test.c \ gst_element_print_properties.c +gsthanddetect_test_SOURCES = gsthanddetect_test.c + gstmotioncells_dynamic_test_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) gstmotioncells_dynamic_test_LDFLAGS = $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) $(GSTPB_BASE_LIBS) +gsthanddetect_test_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) +gsthanddetect_test_LDFLAGS = $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) $(GSTPB_BASE_LIBS) noinst_HEADERS = \ gstmotioncells_dynamic_test.h \ gst_element_print_properties.h diff --git a/tests/examples/opencv/gsthanddetect_test.c b/tests/examples/opencv/gsthanddetect_test.c index 2a2187bb7..05e11ed06 100644 --- a/tests/examples/opencv/gsthanddetect_test.c +++ b/tests/examples/opencv/gsthanddetect_test.c @@ -1,174 +1,189 @@ -/* - *============================================================================ - *Name : gsthanddetect_app.c - *Author : Andol Li, andol@andol.info - *Version : 0.1 - *Copyright : @2012, gstreamer - *Description : gsteramer handdetect plugin demo application in C, part work of GSoc 2012 project - *============================================================================ +/* GStreamer + * Copyright (C) 2012 Andol Li <andol@andol.info> + * + * gsthanddetect_test: gsteramer handdetect plugin demo application, + * part work of GSoc 2012 project + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <gst/gst.h> -#include <glib.h> -#include <glib-object.h> -#define PROFILE_FIST "/usr/local/share/opencv/haarcascades/fist.xml" -#define PROFILE_PALM "/usr/local/share/opencv/haarcascades/palm.xml" +GstElement *playbin, *pipeline; +GstElement *v4l2src, *videoscale, *videoconvert_in, *handdetect, + *videoconvert_out, *xvimagesink; -GstElement *playbin, - *pipeline, - *v4l2src, *videoscale, *ffmpegcolorspace_in, *handdetect, *ffmpegcolorspace_out, *xvimagesink; - -static GstBusSyncHandler -bus_sync_handler(GstBus *bus, GstMessage *message, GstPipeline *pipeline) +static GstBusSyncReply +bus_sync_handler (GstBus * bus, GstMessage * message, GstPipeline * pipeline) { - /* select msg */ - if(GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT || - !gst_structure_has_name(message->structure, "hand-gesture") ) - return GST_BUS_PASS; - - /* parse msg structure */ - const GstStructure *structure = message->structure; - - /* if PALM gesture detected */ - if (structure && - strcmp (gst_structure_get_name (structure), "hand-gesture") == 0 && - strcmp (gst_structure_get_string (structure, "gesture"), "palm") == 0) { - /* media operation - closed palm to stop media play*/ - gst_element_set_state (playbin, GST_STATE_PAUSED); - } - - /* if FIST gesture detected */ - if (structure && - strcmp (gst_structure_get_name (structure), "hand-gesture") == 0 && - strcmp (gst_structure_get_string (structure, "gesture"), "fist") == 0){ - /* print message type and structure name */ - g_print("%s{{%s}}\n", gst_message_type_get_name(message->type), gst_structure_get_name(structure)); - /* print msg structure names&values */ - int i; - for(i = 0; i < gst_structure_n_fields(structure); i++){ - const gchar *name = gst_structure_nth_field_name(structure, i); - GType type = gst_structure_get_field_type(structure, name); - const GValue *value = gst_structure_get_value(structure, name); - type == G_TYPE_STRING ? - g_print("-%s[%s]{%s}\n", name, g_type_name(type), g_value_get_string(value)) : - g_print("-%s[%s]{%d}\n", name, g_type_name(type), g_value_get_uint(value)); - } - g_print("\n"); - - /* get X,Y positions in frame */ - const GValue *x_value = gst_structure_get_value(structure, "x"); - gint x = g_value_get_uint(x_value); - const GValue *y_value = gst_structure_get_value(structure, "y"); - gint y = g_value_get_uint(y_value); - - /* set object volumes [0-10] based on Y */ - g_object_set(G_OBJECT(playbin), "volume", (gdouble)(10 - y/24 ), NULL); - - /* seek playback positions */ - gint64 position, length; - GstFormat format = GST_FORMAT_TIME; - gst_element_query_duration(playbin, &format, &length); - /* Width = 320 is specified in caps */ - position = (gint64) length * x / 320; - gst_element_set_state(playbin, GST_STATE_PAUSED); - gst_element_seek(GST_ELEMENT(playbin), - 1.0, - format, - GST_SEEK_FLAG_FLUSH, - GST_SEEK_TYPE_SET, - position, - GST_SEEK_TYPE_NONE, - GST_CLOCK_TIME_NONE ); - gst_element_set_state(GST_ELEMENT(playbin), GST_STATE_PLAYING); - } - - gst_message_unref(message); - return GST_BUS_DROP; + const GstStructure *structure; + gint64 position, length; + GstFormat format = GST_FORMAT_TIME; + const GValue *x_value, *y_value; + gint x, i, y; + /* select msg */ + if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT || + !gst_structure_has_name (gst_message_get_structure (message), + "hand-gesture")) + return GST_BUS_PASS; + + /* parse msg structure */ + structure = gst_message_get_structure (message); + + /* if PALM gesture detected */ + if (structure && + strcmp (gst_structure_get_name (structure), "hand-gesture") == 0 && + strcmp (gst_structure_get_string (structure, "gesture"), "palm") == 0) { + /* media operation - closed palm to stop media play */ + gst_element_set_state (playbin, GST_STATE_PAUSED); + } + + /* if FIST gesture detected */ + if (structure && + strcmp (gst_structure_get_name (structure), "hand-gesture") == 0 && + strcmp (gst_structure_get_string (structure, "gesture"), "fist") == 0) { + /* print message type and structure name */ + g_print ("%s{{%s}}\n", gst_message_type_get_name (message->type), + gst_structure_get_name (structure)); + /* print msg structure names&values */ + for (i = 0; i < gst_structure_n_fields (structure); i++) { + const gchar *name = gst_structure_nth_field_name (structure, i); + GType type = gst_structure_get_field_type (structure, name); + const GValue *value = gst_structure_get_value (structure, name); + type == G_TYPE_STRING ? + g_print ("-%s[%s]{%s}\n", name, g_type_name (type), + g_value_get_string (value)) : g_print ("-%s[%s]{%d}\n", name, + g_type_name (type), g_value_get_uint (value)); + } + g_print ("\n"); + + /* get X,Y positions in frame */ + x_value = gst_structure_get_value (structure, "x"); + x = g_value_get_uint (x_value); + y_value = gst_structure_get_value (structure, "y"); + y = g_value_get_uint (y_value); + + /* set object volumes [0-10] based on Y */ + g_object_set (G_OBJECT (playbin), "volume", (gdouble) (10 - y / 24), NULL); + + /* seek playback positions */ + gst_element_query_duration (playbin, format, &length); + /* Width = 320 is specified in caps */ + position = (gint64) length *x / 320; + gst_element_set_state (playbin, GST_STATE_PAUSED); + gst_element_seek (GST_ELEMENT (playbin), + 1.0, + format, + GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + gst_element_set_state (GST_ELEMENT (playbin), GST_STATE_PLAYING); + } + + gst_message_unref (message); + return GST_BUS_DROP; } -int main(gint argc, gchar **argv) { - static GMainLoop *loop; - loop = g_main_loop_new(NULL, FALSE); - /* video source */ - gchar *video_device = "/dev/video0"; - gchar *video_file = "file:///home/javauser/workspace/gitfiles/gsthanddetect_app/video.avi"; - /* bus */ - GstBus *bus; - /* caps */ - GstCaps *caps; - - /* init gst */ - gst_init(&argc, &argv); - - /* init elements */ - playbin = gst_element_factory_make("playbin2", "app_playbin"); - pipeline = gst_pipeline_new("app_pipeline"); - v4l2src = gst_element_factory_make("v4l2src", "app_v4l2src"); - videoscale = gst_element_factory_make("videoscale", "app_videoscale"); - ffmpegcolorspace_in = gst_element_factory_make("ffmpegcolorspace", "app_ffmpegcolorspace_in"); - handdetect = gst_element_factory_make("handdetect", "app_handdetect"); - ffmpegcolorspace_out = gst_element_factory_make("ffmpegcolorspace", "app_ffmpegcolorspace_out"); - xvimagesink = gst_element_factory_make("xvimagesink", "app_xvimagesink"); - - /* check init results */ - if(!playbin || !pipeline || !v4l2src || !videoscale || !ffmpegcolorspace_in - || !handdetect || !ffmpegcolorspace_out || !xvimagesink) - g_error("ERROR: element init failed.\n"); - - /* set values */ - g_object_set (G_OBJECT(playbin), "uri", video_file, NULL); - g_object_set (G_OBJECT(v4l2src), "device", video_device, NULL); - g_object_set (G_OBJECT (handdetect), "profile_fist", PROFILE_FIST, NULL); - g_object_set (G_OBJECT (handdetect), "profile_palm", PROFILE_PALM, NULL); - - /* set caps */ - caps = gst_caps_from_string("video/x-raw-rgb, width=320, height=240, framerate=(fraction)30/1"); - - /* set bus */ - bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); - gst_bus_set_sync_handler(bus, (GstBusSyncHandler) bus_sync_handler, pipeline); - gst_object_unref(bus); - - /* add elements to pipeline */ - gst_bin_add_many(GST_BIN(pipeline), - v4l2src, - videoscale, - ffmpegcolorspace_in, - handdetect, - ffmpegcolorspace_out, - xvimagesink, - NULL); - - /* negotiate caps */ - if(!gst_element_link_filtered( v4l2src, videoscale, caps)){ - g_printerr("ERROR:v4l2src -> videoscale caps\n"); - return 0; } - gst_caps_unref(caps); - - /* link elements */ - gst_element_link_many( - videoscale, - ffmpegcolorspace_in, - handdetect, - ffmpegcolorspace_out, - xvimagesink, - NULL); - - /* change states */ - gst_element_set_state(pipeline, GST_STATE_PLAYING); - - /* start main loop */ - g_main_loop_run(loop); - - /* clean all */ - gst_element_set_state(pipeline, GST_STATE_NULL); - gst_object_unref(GST_OBJECT(pipeline)); - gst_element_set_state(playbin, GST_STATE_NULL); - gst_object_unref(GST_OBJECT(playbin)); - - return 0; +int +main (gint argc, gchar ** argv) +{ + static GMainLoop *loop; + GstCaps *caps; + GstBus *bus; + gchar *uri; + + const gchar *video_device = "/dev/video0"; + + if (argc < 2) { + fprintf (stderr, "oops, please give a file to play\n"); + return -1; + } + + uri = g_filename_to_uri (argv[1], NULL, NULL); + if (!uri) { + fprintf (stderr, "failed to create the uri\n"); + return -1; + } + + /* init gst */ + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + /* init elements */ + playbin = gst_element_factory_make ("playbin", "app_playbin"); + pipeline = gst_pipeline_new ("app_pipeline"); + v4l2src = gst_element_factory_make ("v4l2src", "app_v4l2src"); + videoscale = gst_element_factory_make ("videoscale", "app_videoscale"); + videoconvert_in = + gst_element_factory_make ("videoconvert", "app_videoconvert_in"); + handdetect = gst_element_factory_make ("handdetect", "app_handdetect"); + videoconvert_out = + gst_element_factory_make ("videoconvert", "app_videoconvert_out"); + xvimagesink = gst_element_factory_make ("xvimagesink", "app_xvimagesink"); + + /* check init results */ + if (!playbin || !pipeline || !v4l2src || !videoscale || !videoconvert_in + || !handdetect || !videoconvert_out || !xvimagesink) + g_error ("ERROR: element init failed.\n"); + + /* set values */ + g_object_set (G_OBJECT (playbin), "uri", uri, NULL); + g_object_set (G_OBJECT (v4l2src), "device", video_device, NULL); + + /* set caps */ + caps = + gst_caps_from_string + ("video/x-raw, format=(string)RGB, width=320, height=240, framerate=(fraction)30/1"); + + /* set bus */ + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, pipeline, + NULL); + gst_object_unref (bus); + + /* add elements to pipeline */ + gst_bin_add_many (GST_BIN (pipeline), + v4l2src, + videoscale, + videoconvert_in, handdetect, videoconvert_out, xvimagesink, NULL); + + /* negotiate caps */ + if (!gst_element_link_filtered (v4l2src, videoscale, caps)) { + g_printerr ("ERROR:v4l2src -> videoscale caps\n"); + return 0; + } + gst_caps_unref (caps); + + /* link elements */ + gst_element_link_many (videoscale, + videoconvert_in, handdetect, videoconvert_out, xvimagesink, NULL); + + /* change states */ + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* start main loop */ + g_main_loop_run (loop); + + /* clean all */ + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (GST_OBJECT (pipeline)); + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (GST_OBJECT (playbin)); + + return 0; } |