1 /* GStreamer
2  * Copyright (C) 2012 Andol Li <andol@andol.info>
3  *
4  *  gsthanddetect_test: gstreamer handdetect plugin demo application,
5  *  part work of GSoc 2012 project
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <gst/gst.h>
28 
29 GstElement *playbin, *pipeline;
30 GstElement *v4l2src, *videoscale, *videoconvert_in, *handdetect,
31     *videoconvert_out, *xvimagesink;
32 
33 static GstBusSyncReply
bus_sync_handler(GstBus * bus,GstMessage * message,GstPipeline * pipeline)34 bus_sync_handler (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
35 {
36   const GstStructure *structure;
37   gint64 position, length;
38   GstFormat format = GST_FORMAT_TIME;
39   const GValue *x_value, *y_value;
40   gint x, i, y;
41   /* select msg */
42   if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT ||
43       !gst_structure_has_name (gst_message_get_structure (message),
44           "hand-gesture"))
45     return GST_BUS_PASS;
46 
47   /* parse msg structure */
48   structure = gst_message_get_structure (message);
49 
50   /* if PALM gesture detected */
51   if (structure &&
52       strcmp (gst_structure_get_name (structure), "hand-gesture") == 0 &&
53       strcmp (gst_structure_get_string (structure, "gesture"), "palm") == 0) {
54     /* media operation - closed palm to stop media play */
55     gst_element_set_state (playbin, GST_STATE_PAUSED);
56   }
57 
58   /* if FIST gesture detected */
59   if (structure &&
60       strcmp (gst_structure_get_name (structure), "hand-gesture") == 0 &&
61       strcmp (gst_structure_get_string (structure, "gesture"), "fist") == 0) {
62     /* print message type and structure name */
63     g_print ("%s{{%s}}\n", gst_message_type_get_name (message->type),
64         gst_structure_get_name (structure));
65     /* print msg structure names&values */
66     for (i = 0; i < gst_structure_n_fields (structure); i++) {
67       const gchar *name = gst_structure_nth_field_name (structure, i);
68       GType type = gst_structure_get_field_type (structure, name);
69       const GValue *value = gst_structure_get_value (structure, name);
70       type == G_TYPE_STRING ?
71           g_print ("-%s[%s]{%s}\n", name, g_type_name (type),
72           g_value_get_string (value)) : g_print ("-%s[%s]{%d}\n", name,
73           g_type_name (type), g_value_get_uint (value));
74     }
75     g_print ("\n");
76 
77     /* get X,Y positions in frame */
78     x_value = gst_structure_get_value (structure, "x");
79     x = g_value_get_uint (x_value);
80     y_value = gst_structure_get_value (structure, "y");
81     y = g_value_get_uint (y_value);
82 
83     /* set object volumes [0-10] based on Y */
84     g_object_set (G_OBJECT (playbin), "volume", (gdouble) (10 - y / 24), NULL);
85 
86     /* seek playback positions */
87     gst_element_query_duration (playbin, format, &length);
88     /* Width = 320 is specified in caps */
89     position = (gint64) length *x / 320;
90     gst_element_set_state (playbin, GST_STATE_PAUSED);
91     gst_element_seek (GST_ELEMENT (playbin),
92         1.0,
93         format,
94         GST_SEEK_FLAG_FLUSH,
95         GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
96     gst_element_set_state (GST_ELEMENT (playbin), GST_STATE_PLAYING);
97   }
98 
99   gst_message_unref (message);
100   return GST_BUS_DROP;
101 }
102 
103 int
main(gint argc,gchar ** argv)104 main (gint argc, gchar ** argv)
105 {
106   static GMainLoop *loop;
107   GstCaps *caps;
108   GstBus *bus;
109   gchar *uri;
110 
111   if (argc < 2) {
112     fprintf (stderr, "oops, please give a file to play\n");
113     return -1;
114   }
115 
116   uri = g_filename_to_uri (argv[1], NULL, NULL);
117   if (!uri) {
118     fprintf (stderr, "failed to create the uri\n");
119     return -1;
120   }
121 
122   /* init gst */
123   gst_init (&argc, &argv);
124 
125   loop = g_main_loop_new (NULL, FALSE);
126   /* init elements */
127   playbin = gst_element_factory_make ("playbin", "app_playbin");
128   pipeline = gst_pipeline_new ("app_pipeline");
129   v4l2src = gst_element_factory_make ("v4l2src", "app_v4l2src");
130   videoscale = gst_element_factory_make ("videoscale", "app_videoscale");
131   videoconvert_in =
132       gst_element_factory_make ("videoconvert", "app_videoconvert_in");
133   handdetect = gst_element_factory_make ("handdetect", "app_handdetect");
134   videoconvert_out =
135       gst_element_factory_make ("videoconvert", "app_videoconvert_out");
136   xvimagesink = gst_element_factory_make ("xvimagesink", "app_xvimagesink");
137 
138   /* check init results */
139   if (!playbin || !pipeline || !v4l2src || !videoscale || !videoconvert_in
140       || !handdetect || !videoconvert_out || !xvimagesink)
141     g_error ("ERROR: element init failed.\n");
142 
143   /* set values */
144   g_object_set (G_OBJECT (playbin), "uri", uri, NULL);
145 
146   /* set caps */
147   caps =
148       gst_caps_from_string
149       ("video/x-raw, format=(string)RGB, width=320, height=240, framerate=(fraction)30/1");
150 
151   /* set bus */
152   bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
153   gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, pipeline,
154       NULL);
155   gst_object_unref (bus);
156 
157   /* add elements to pipeline */
158   gst_bin_add_many (GST_BIN (pipeline),
159       v4l2src,
160       videoscale,
161       videoconvert_in, handdetect, videoconvert_out, xvimagesink, NULL);
162 
163   /* negotiate caps */
164   if (!gst_element_link_filtered (v4l2src, videoscale, caps)) {
165     g_printerr ("ERROR:v4l2src -> videoscale caps\n");
166     return 0;
167   }
168   gst_caps_unref (caps);
169 
170   /* link elements */
171   gst_element_link_many (videoscale,
172       videoconvert_in, handdetect, videoconvert_out, xvimagesink, NULL);
173 
174   /* change states */
175   gst_element_set_state (pipeline, GST_STATE_PLAYING);
176 
177   /* start main loop */
178   g_main_loop_run (loop);
179 
180   /* clean all */
181   gst_element_set_state (pipeline, GST_STATE_NULL);
182   gst_object_unref (GST_OBJECT (pipeline));
183   gst_element_set_state (playbin, GST_STATE_NULL);
184   gst_object_unref (GST_OBJECT (playbin));
185 
186   return 0;
187 }
188