| /* GStreamer | |
| * Copyright (C) 2012 Andol Li <andol@andol.info> | |
| * | |
| * gsthanddetect_test: gstreamer handdetect plugin demo application, | |
| * part work of GSoc 2012 project | |
| * | |
| * 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 St, Fifth Floor, | |
| * Boston, MA 02110-1301, USA. | |
| * | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <gst/gst.h> | |
| GstElement *playbin, *pipeline; | |
| GstElement *v4l2src, *videoscale, *videoconvert_in, *handdetect, | |
| *videoconvert_out, *xvimagesink; | |
| static GstBusSyncReply | |
| bus_sync_handler (GstBus * bus, GstMessage * message, GstPipeline * pipeline) | |
| { | |
| 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; | |
| GstCaps *caps; | |
| GstBus *bus; | |
| gchar *uri; | |
| 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); | |
| /* 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; | |
| } |