8ec0dca33a2738752539d00572451b56602b597a
[platform/upstream/gstreamer.git] / tutorials / basic-tutorial-3.c
1 #include <gst/gst.h>\r
2   \r
3 /* Structure to contain all our information, so we can pass it to callbacks */\r
4 typedef struct _CustomData {\r
5   GstElement *pipeline;\r
6   GstElement *source;\r
7   GstElement *convert;\r
8   GstElement *sink;\r
9 } CustomData;\r
10   \r
11 /* Handler for the pad-added signal */\r
12 static void pad_added_handler (GstElement *src, GstPad *pad, CustomData *data);\r
13   \r
14 int main(int argc, char *argv[]) {\r
15   CustomData data;\r
16   GstBus *bus;\r
17   GstMessage *msg;\r
18   GstStateChangeReturn ret;\r
19   gboolean terminate = FALSE;\r
20   \r
21   /* Initialize GStreamer */\r
22   gst_init (&argc, &argv);\r
23    \r
24   /* Create the elements */\r
25   data.source = gst_element_factory_make ("uridecodebin", "source");\r
26   data.convert = gst_element_factory_make ("audioconvert", "convert");\r
27   data.sink = gst_element_factory_make ("autoaudiosink", "sink");\r
28   \r
29   /* Create the empty pipeline */\r
30   data.pipeline = gst_pipeline_new ("test-pipeline");\r
31   \r
32   if (!data.pipeline || !data.source || !data.convert || !data.sink) {\r
33     g_printerr ("Not all elements could be created.\n");\r
34     return -1;\r
35   }\r
36   \r
37   /* Build the pipeline. Note that we are NOT linking the source at this\r
38    * point. We will do it later. */\r
39   gst_bin_add_many (GST_BIN (data.pipeline), data.source, data.convert , data.sink, NULL);\r
40   if (!gst_element_link (data.convert, data.sink)) {\r
41     g_printerr ("Elements could not be linked.\n");\r
42     gst_object_unref (data.pipeline);\r
43     return -1;\r
44   }\r
45   \r
46   /* Set the URI to play */\r
47   g_object_set (data.source, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);\r
48   \r
49   /* Connect to the pad-added signal */\r
50   g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler), &data);\r
51   \r
52   /* Start playing */\r
53   ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);\r
54   if (ret == GST_STATE_CHANGE_FAILURE) {\r
55     g_printerr ("Unable to set the pipeline to the playing state.\n");\r
56     gst_object_unref (data.pipeline);\r
57     return -1;\r
58   }\r
59   \r
60   /* Listen to the bus */\r
61   bus = gst_element_get_bus (data.pipeline);\r
62   do {\r
63     msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,\r
64         GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS);\r
65   \r
66     /* Parse message */\r
67     if (msg != NULL) {\r
68       GError *err;\r
69       gchar *debug_info;\r
70       \r
71       switch (GST_MESSAGE_TYPE (msg)) {\r
72         case GST_MESSAGE_ERROR:\r
73           gst_message_parse_error (msg, &err, &debug_info);\r
74           g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);\r
75           g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");\r
76           g_clear_error (&err);\r
77           g_free (debug_info);\r
78           terminate = TRUE;\r
79           break;\r
80         case GST_MESSAGE_EOS:\r
81           g_print ("End-Of-Stream reached.\n");\r
82           terminate = TRUE;\r
83           break;\r
84         case GST_MESSAGE_STATE_CHANGED:\r
85           /* We are only interested in state-changed messages from the pipeline */\r
86           if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data.pipeline)) {\r
87             GstState old_state, new_state, pending_state;\r
88             gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);\r
89             g_print ("Pipeline state changed from %s to %s:\n",\r
90                 gst_element_state_get_name (old_state), gst_element_state_get_name (new_state));\r
91           }\r
92           break;\r
93         default:\r
94           /* We should not reach here */\r
95           g_printerr ("Unexpected message received.\n");\r
96           break;\r
97       }\r
98       gst_message_unref (msg);\r
99     }\r
100   } while (!terminate);\r
101   \r
102   /* Free resources */\r
103   gst_object_unref (bus);\r
104   gst_element_set_state (data.pipeline, GST_STATE_NULL);\r
105   gst_object_unref (data.pipeline);\r
106   return 0;\r
107 }\r
108   \r
109 /* This function will be called by the pad-added signal */\r
110 static void pad_added_handler (GstElement *src, GstPad *new_pad, CustomData *data) {\r
111   GstPad *sink_pad = gst_element_get_static_pad (data->convert, "sink");\r
112   GstPadLinkReturn ret;\r
113   GstCaps *new_pad_caps = NULL;\r
114   GstStructure *new_pad_struct = NULL;\r
115   const gchar *new_pad_type = NULL;\r
116   \r
117   g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (new_pad), GST_ELEMENT_NAME (src));\r
118   \r
119   /* If our converter is already linked, we have nothing to do here */\r
120   if (gst_pad_is_linked (sink_pad)) {\r
121     g_print ("  We are already linked. Ignoring.\n");\r
122     goto exit;\r
123   }\r
124   \r
125   /* Check the new pad's type */\r
126   new_pad_caps = gst_pad_query_caps (new_pad, NULL);\r
127   new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);\r
128   new_pad_type = gst_structure_get_name (new_pad_struct);\r
129   if (!g_str_has_prefix (new_pad_type, "audio/x-raw")) {\r
130     g_print ("  It has type '%s' which is not raw audio. Ignoring.\n", new_pad_type);\r
131     goto exit;\r
132   }\r
133   \r
134   /* Attempt the link */\r
135   ret = gst_pad_link (new_pad, sink_pad);\r
136   if (GST_PAD_LINK_FAILED (ret)) {\r
137     g_print ("  Type is '%s' but link failed.\n", new_pad_type);\r
138   } else {\r
139     g_print ("  Link succeeded (type '%s').\n", new_pad_type);\r
140   }\r
141   \r
142 exit:\r
143   /* Unreference the new pad's caps, if we got them */\r
144   if (new_pad_caps != NULL)\r
145     gst_caps_unref (new_pad_caps);\r
146   \r
147   /* Unreference the sink pad */\r
148   gst_object_unref (sink_pad);\r
149 }\r