2 title: Building a Test Application
5 # Building a Test Application
7 Often, you will want to test your newly written plugin in an as small
8 setting as possible. Usually, `gst-launch-1.0` is a good first step at
9 testing a plugin. If you have not installed your plugin in a directory
10 that GStreamer searches, then you will need to set the plugin path.
11 Either set GST\_PLUGIN\_PATH to the directory containing your plugin, or
12 use the command-line option --gst-plugin-path. If you based your plugin
13 off of the gst-plugin template, then this will look something like `
14 gst-launch-1.0 --gst-plugin-path=$HOME/gst-template/gst-plugin/src/.libs
16 ` However, you will often need more testing features than gst-launch-1.0
17 can provide, such as seeking, events, interactivity and more. Writing
18 your own small testing program is the easiest way to accomplish this.
19 This section explains - in a few words - how to do that. For a complete
20 application development guide, see the [Application Development
21 Manual](../../manual/html/index.html).
23 At the start, you need to initialize the GStreamer core library by
24 calling `gst_init ()`. You can alternatively call
25 `gst_init_get_option_group ()`, which will return a pointer to
26 GOptionGroup. You can then use GOption to handle the initialization, and
27 this will finish the GStreamer initialization.
29 You can create elements using `gst_element_factory_make ()`, where the
30 first argument is the element type that you want to create, and the
31 second argument is a free-form name. The example at the end uses a
32 simple filesource - decoder - soundcard output pipeline, but you can use
33 specific debugging elements if that's necessary. For example, an
34 `identity` element can be used in the middle of the pipeline to act as a
35 data-to-application transmitter. This can be used to check the data for
36 misbehaviours or correctness in your test application. Also, you can use
37 a `fakesink` element at the end of the pipeline to dump your data to the
38 stdout (in order to do this, set the `dump` property to TRUE). Lastly,
39 you can use valgrind to check for memory errors.
41 During linking, your test application can use filtered caps as a way to
42 drive a specific type of data to or from your element. This is a very
43 simple and effective way of checking multiple types of input and output
46 Note that during running, you should listen for at least the “error” and
47 “eos” messages on the bus and/or your plugin/element to check for
48 correct handling of this. Also, you should add events into the pipeline
49 and make sure your plugin handles these correctly (with respect to
50 clocking, internal caching, etc.).
52 Never forget to clean up memory in your plugin or your test application.
53 When going to the NULL state, your element should clean up allocated
54 memory and caches. Also, it should close down any references held to
55 possible support libraries. Your application should `unref ()` the
56 pipeline and make sure it doesn't crash.
62 bus_call (GstBus *bus,
66 GMainLoop *loop = data;
68 switch (GST_MESSAGE_TYPE (msg)) {
70 g_print ("End-of-stream\n");
71 g_main_loop_quit (loop);
73 case GST_MESSAGE_ERROR: {
77 gst_message_parse_error (msg, &err, &debug);
79 g_print ("Error: %s\n", err->message);
83 g_print ("Debug details: %s\n", debug);
87 g_main_loop_quit (loop);
101 GstStateChangeReturn ret;
102 GstElement *pipeline, *filesrc, *decoder, *filter, *sink;
103 GstElement *convert1, *convert2, *resample;
109 gst_init (&argc, &argv);
110 loop = g_main_loop_new (NULL, FALSE);
112 g_print ("Usage: %s <mp3 filename>\n", argv[0]);
116 /* create elements */
117 pipeline = gst_pipeline_new ("my_pipeline");
119 /* watch for messages on the pipeline's bus (note that this will only
120 * work like this when a GLib main loop is running) */
121 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
122 watch_id = gst_bus_add_watch (bus, bus_call, loop);
123 gst_object_unref (bus);
125 filesrc = gst_element_factory_make ("filesrc", "my_filesource");
126 decoder = gst_element_factory_make ("mad", "my_decoder");
128 /* putting an audioconvert element here to convert the output of the
129 * decoder into a format that my_filter can handle (we are assuming it
130 * will handle any sample rate here though) */
131 convert1 = gst_element_factory_make ("audioconvert", "audioconvert1");
133 /* use "identity" here for a filter that does nothing */
134 filter = gst_element_factory_make ("my_filter", "my_filter");
136 /* there should always be audioconvert and audioresample elements before
137 * the audio sink, since the capabilities of the audio sink usually vary
138 * depending on the environment (output used, sound card, driver etc.) */
139 convert2 = gst_element_factory_make ("audioconvert", "audioconvert2");
140 resample = gst_element_factory_make ("audioresample", "audioresample");
141 sink = gst_element_factory_make ("pulsesink", "audiosink");
143 if (!sink || !decoder) {
144 g_print ("Decoder or output could not be found - check your install\n");
146 } else if (!convert1 || !convert2 || !resample) {
147 g_print ("Could not create audioconvert or audioresample element, "
148 "check your installation\n");
150 } else if (!filter) {
151 g_print ("Your self-written filter could not be found. Make sure it "
152 "is installed correctly in $(libdir)/gstreamer-1.0/ or "
153 "~/.gstreamer-1.0/plugins/ and that gst-inspect-1.0 lists it. "
154 "If it doesn't, check with 'GST_DEBUG=*:2 gst-inspect-1.0' for "
155 "the reason why it is not being loaded.");
159 g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
161 gst_bin_add_many (GST_BIN (pipeline), filesrc, decoder, convert1, filter,
162 convert2, resample, sink, NULL);
164 /* link everything together */
165 if (!gst_element_link_many (filesrc, decoder, convert1, filter, convert2,
166 resample, sink, NULL)) {
167 g_print ("Failed to link one or more elements!\n");
172 ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
173 if (ret == GST_STATE_CHANGE_FAILURE) {
176 g_print ("Failed to start up pipeline!\n");
178 /* check if there is an error message with details on the bus */
179 msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
183 gst_message_parse_error (msg, &err, NULL);
184 g_print ("ERROR: %s\n", err->message);
186 gst_message_unref (msg);
191 g_main_loop_run (loop);
194 gst_element_set_state (pipeline, GST_STATE_NULL);
195 gst_object_unref (pipeline);
196 g_source_remove (watch_id);
197 g_main_loop_unref (loop);